Skip to content

Commit 7bac726

Browse files
committed
Add specs and docs
1 parent bc1516f commit 7bac726

6 files changed

+232
-38
lines changed

.gitignore

-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
.bundle/*
2-
log/*
31
*.swp
42
*.swo

README.md

+104-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,114 @@
1+
# Tarot Api
2+
3+
## Requests
4+
5+
`GET /`
6+
7+
Returns an array of every card
8+
9+
`GET /cards`
10+
11+
Returns an array of every card
12+
13+
`GET /cards/[suit]/[rank]`
14+
15+
| argument | values | required |
16+
|----------|-------------------------------------------------------------------------|----------|
17+
| suit | one of: swords, wands, cups, coins, or major | yes |
18+
| rank | one of: king, queen, 1-10 for swords/wands/cups/coins or 0-21 for major | yes |
19+
20+
Returns a single card in the form of
21+
22+
| field | type | description |
23+
|--------------------|------------------|---------------------------------------------------------------------------------------------|
24+
| fortune_telling | array of strings | what this card might mean in a fortune |
25+
| keywords | array of strings | what words are associated with this card |
26+
| meanings | hash | |
27+
| meanings["light"] | array of strings | meanings for this card in the upright position |
28+
| meanings["shadow"] | array of strings | meanings for this card in the reverse position |
29+
| name | string | the name of the card written out in words |
30+
| rank | string or int | rank of the card in the suit up to 21 for major arcana, king through 10 for all other suits |
31+
| suit | string | major, coins, cups, swords, or wands |
32+
33+
### Example
34+
35+
`GET /cards/swords/10`
36+
37+
<details>
38+
<summary>
39+
returns the following JSON
40+
</summary>
41+
42+
```JSON
43+
{
44+
"fortune_telling":[
45+
"Disaster",
46+
"Put off plans and do not take action until omens are better"
47+
],
48+
"keywords":[
49+
"exhaustion",
50+
"ruin",
51+
"disaster",
52+
"stamina",
53+
"obsession"
54+
],
55+
"meanings":{
56+
"light":[
57+
"Seeing the signs that you've reached your limits",
58+
"Paying attention to what your body is trying to tell you",
59+
"Giving in to the need for rest and renewal",
60+
"Acknowledging that you've hit bottom",
61+
"Committing to a turnaround",
62+
"Knowing the worst is over"
63+
],
64+
"shadow":[
65+
"Accepting defeat prematurely",
66+
"Driving yourself to total exhaustion, especially mentally",
67+
"Experiencing a mental breakdown",
68+
"Obsessing on a problem to the breaking point",
69+
"Giving up",
70+
"Refusing to move from thought to action",
71+
"Deeply unhealthy thoughts"
72+
]
73+
},
74+
"name":"ten of swords",
75+
"rank":10,
76+
"suit":"swords"
77+
}
78+
```
79+
</details>
80+
81+
`GET /draw/[n]`
82+
83+
Returns n randomly selected cards
84+
85+
| argument | values | required |
86+
|----------|--------------|----------|
87+
| n | positive int | yes |
88+
89+
`GET /find/:name`
90+
91+
Returns the card by the specified name. Note that the numbers will be spelled out and pentacles will be replaced by coins.
92+
93+
| argument | values | required |
94+
|----------|--------------------------------------------|----------|
95+
| name | string name of the card (eg: The Magician) | yes |
96+
197

298
## Testing
399

4-
rake spec
100+
```
101+
rake test
102+
```
5103

6104
## Getting Started
7105

106+
```
8107
bundle install
9-
rake db:migrate
10-
shotgun application.rb
108+
rackup
109+
```
11110

12111
## Thanks
13112

14-
Sinatra API template https://github.com/noplay/sinatra-api-template
113+
* Sinatra API template https://github.com/noplay/sinatra-api-template
114+
* Tarot Corupus from https://github.com/dariusk/corpora

Rakefile

+8-10
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ require 'rubygems'
22
require 'bundler/setup'
33
require 'rspec/core/rake_task'
44

5-
task :default => :test
6-
task :test => :spec
5+
task default: %w[server]
76

8-
if !defined?(RSpec)
9-
puts "spec targets require RSpec"
10-
else
11-
desc "Run all examples"
12-
RSpec::Core::RakeTask.new(:spec) do |t|
13-
#t.pattern = 'spec/**/*_spec.rb' # not needed this is default
14-
t.rspec_opts = ['-cfs']
15-
end
7+
task :server do
8+
sh "rackup --host 0.0.0.0"
169
end
10+
11+
task :test do
12+
RSpec::Core::RakeTask.new(:spec)
13+
Rake::Task["spec"].execute
14+
end

application.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ def halt_with_403_forbidden_error(message = nil)
3636
# return card by suit and rank
3737
get '/cards/:suit/:rank' do
3838
suit = params[:suit].downcase.gsub("pentacles", "coins")
39-
rank = params[:rank].downcase
39+
rank = params[:rank].downcase # ranks can be strings or ints
4040

41-
card = cards.detect { |card| card["rank"] == rank.to_s && card["suit"] == suit }
41+
card = cards.detect { |card| card["rank"].to_s == rank && card["suit"] == suit }
4242
halt_with_404_not_found unless card
4343
json card
4444
end

spec/application_spec.rb

+109-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,115 @@
1-
require "#{File.dirname(__FILE__)}/spec_helper"
2-
3-
describe 'main application' do
4-
include Rack::Test::Methods
1+
require "spec_helper"
52

3+
describe 'Application' do
64
def app
7-
Sinatra::Application.new
5+
Application
6+
end
7+
8+
describe "/" do
9+
it "should return all cards" do
10+
get "/"
11+
expect(last_response).to be_ok
12+
13+
expect(last_response.body).to include("The Magician")
14+
expect(JSON.parse(last_response.body).length).to eq 78
15+
end
16+
end
17+
18+
describe "/cards" do
19+
it "should return all cards" do
20+
get "/cards"
21+
expect(last_response).to be_ok
22+
23+
expect(last_response.body).to include("The Magician")
24+
expect(JSON.parse(last_response.body).length).to eq 78
25+
end
826
end
927

10-
specify 'should show the default index page' do
11-
get '/'
12-
last_response.should be_ok
28+
describe "/cards/:suit/:rank" do
29+
it "returns the specified card" do
30+
get "/cards/major/1"
31+
expect(last_response).to be_ok
32+
33+
card = JSON.parse(last_response.body)
34+
expect(card["name"]).to eq "The Magician"
35+
expect(card["suit"]).to eq "major"
36+
expect(card["rank"]).to eq 1
37+
end
38+
39+
it "is case insensitive" do
40+
get "/cards/sWoRdS/QuEeN"
41+
expect(last_response).to be_ok
42+
43+
card = JSON.parse(last_response.body)
44+
expect(card["name"]).to eq "queen of swords"
45+
expect(card["suit"]).to eq "swords"
46+
expect(card["rank"]).to eq "queen"
47+
end
48+
49+
it "replaces pentacles with coins" do
50+
get "/cards/pentacles/10"
51+
expect(last_response).to be_ok
52+
53+
card = JSON.parse(last_response.body)
54+
expect(card["name"]).to eq "ten of coins"
55+
expect(card["suit"]).to eq "coins"
56+
expect(card["rank"]).to eq 10
57+
end
58+
59+
it "returns a 404 if card not found" do
60+
get "/cards/cats/dash"
61+
expect(last_response).to be_not_found
62+
end
63+
end
64+
65+
describe "/draw/:n" do
66+
it "returns the number of requested cards" do
67+
get "/draw/3"
68+
expect(last_response).to be_ok
69+
70+
expect(JSON.parse(last_response.body).length).to eq 3
71+
end
72+
73+
it "returns an error if negative cards requested" do
74+
get "/draw/-1"
75+
expect(last_response).to be_forbidden
76+
end
77+
end
78+
79+
describe "/find/:name" do
80+
it "returns the specified card" do
81+
get "/find/The%20Magician"
82+
expect(last_response).to be_ok
83+
84+
card = JSON.parse(last_response.body)
85+
expect(card["name"]).to eq "The Magician"
86+
expect(card["suit"]).to eq "major"
87+
expect(card["rank"]).to eq 1
88+
end
89+
90+
it "is case insensitive" do
91+
get "/find/thE%20magician"
92+
expect(last_response).to be_ok
93+
94+
card = JSON.parse(last_response.body)
95+
expect(card["name"]).to eq "The Magician"
96+
expect(card["suit"]).to eq "major"
97+
expect(card["rank"]).to eq 1
98+
end
99+
100+
it "replaces pentacles with coins" do
101+
get "/find/ten%20of%20pentacles"
102+
expect(last_response).to be_ok
103+
104+
card = JSON.parse(last_response.body)
105+
expect(card["name"]).to eq "ten of coins"
106+
expect(card["suit"]).to eq "coins"
107+
expect(card["rank"]).to eq 10
108+
end
109+
110+
it "returns 404 if card not found" do
111+
get "/find/dash"
112+
expect(last_response).to be_not_found
113+
end
13114
end
14115
end

spec/spec_helper.rb

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
require 'rubygems'
2-
require 'bundler'
3-
Bundler.setup(:default, :test)
4-
require 'sinatra'
5-
require 'rspec'
6-
require 'rack/test'
1+
# spec/spec_helper.rb
2+
require "rack/test"
3+
require "rspec"
74

8-
# set test environment
9-
Sinatra::Base.set :environment, :test
10-
Sinatra::Base.set :run, false
11-
Sinatra::Base.set :raise_errors, true
12-
Sinatra::Base.set :logging, false
5+
ENV["RACK_ENV"] = "test"
136

14-
require File.join(File.dirname(__FILE__), '../application')
7+
require File.expand_path "../../application.rb", __FILE__
8+
9+
RSpec.configure do |config|
10+
config.include Rack::Test::Methods
11+
end

0 commit comments

Comments
 (0)