Skip to content

Commit 38511ae

Browse files
committed
Refactor tests.
1 parent 905e922 commit 38511ae

File tree

4 files changed

+72
-9
lines changed

4 files changed

+72
-9
lines changed

jsonapi-rails.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
2020
spec.add_development_dependency 'sqlite3'
2121
spec.add_development_dependency 'rake', '~> 11.3'
2222
spec.add_development_dependency 'rspec-rails', '~> 3.5'
23+
spec.add_development_dependency 'dry-validation', '~> 0.10.3'
2324
end

spec/dummy/app/controllers/tweets_controller.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ class TweetsController < ActionController::Base
44
def index
55
tweets = Tweet.all
66

7-
render jsonapi: tweets
7+
render jsonapi: tweets,
8+
jsonapi_object: { version: '1.0' },
9+
meta: { foo: 'bar' },
10+
links: {
11+
self: 'http://foo.bar'
12+
}
813
end
914

1015
def show

spec/rails_helper.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require 'spec_helper'
77
require 'rspec/rails'
88
# Add additional requires below this line. Rails is not loaded until this point!
9+
require 'dry-validation'
910

1011
# Requires supporting ruby files with custom matchers and macros, etc, in
1112
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
@@ -55,3 +56,40 @@
5556
# arbitrary gems may also be filtered via:
5657
# config.filter_gems_from_backtrace("gem name")
5758
end
59+
60+
# Custom RSpec matchers
61+
module JSONAPI
62+
module RSpec
63+
class BeValidJsonapiMatcher
64+
def matches?(body)
65+
JSONAPI.parse_response!(JSON.parse(body))
66+
true
67+
end
68+
end
69+
70+
def be_valid_jsonapi
71+
BeValidJsonapiMatcher.new
72+
end
73+
74+
class MatchSchemaMatcher
75+
def matches?(body, &block)
76+
schema = Dry::Validation.Schema(&block)
77+
@body = JSON.parse(body) unless body.is_a?(Hash)
78+
@result = schema.call(@body.with_indifferent_access)
79+
@result.success?
80+
end
81+
82+
def failure_message
83+
"#{@body} #{@result.errors}"
84+
end
85+
end
86+
87+
def match_schema(&block)
88+
MatchSchemaMatcher.new(&block)
89+
end
90+
end
91+
end
92+
93+
RSpec.configure do |config|
94+
config.include JSONAPI::RSpec
95+
end

spec/requests/crud_spec.rb

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@ def body
1010
end
1111

1212
it 'works' do
13+
# Get empty tweets list
1314
get '/tweets', headers: headers
1415
expect(response).to be_success
1516
expect(response).to have_http_status(200)
16-
expected = {
17-
'data' => []
18-
}
19-
expect { JSONAPI.parse_response!(body) }.not_to raise_error
20-
expect(body).to eq(expected)
17+
expect(response.body).to be_valid_jsonapi
18+
expect(response.body).to match_schema do
19+
required(:data).value(eql?: [])
20+
required(:meta).value(eql?: { 'foo' => 'bar' })
21+
required(:jsonapi).value(eql?: { 'version' => '1.0' })
22+
required(:links).value(eql?: { 'self' => 'http://foo.bar' })
23+
end
2124

25+
# Post first tweet
2226
params = {
2327
data: {
2428
type: 'tweets',
@@ -41,9 +45,21 @@ def body
4145
headers: headers.merge('CONTENT_TYPE' => 'application/vnd.api+json')
4246
expect(response).to be_success
4347
expect(response).to have_http_status(201)
44-
expect { JSONAPI.parse_response!(body) }.not_to raise_error
48+
expect(response.body).to be_valid_jsonapi
49+
expect(response.body).to match_schema do
50+
required(:data).schema do
51+
required(:type).value(eql?: 'tweets')
52+
required(:attributes).schema do
53+
required(:content).value(eql?: 'foo')
54+
end
55+
required(:relationships).schema do
56+
required(:author)
57+
end
58+
end
59+
end
4560
first_tweet = body
4661

62+
# Post second tweet
4763
params = {
4864
data: {
4965
type: 'tweets',
@@ -61,20 +77,23 @@ def body
6177
expect { JSONAPI.parse_response!(body) }.not_to raise_error
6278
second_tweet = body
6379

80+
# Get first tweet
6481
get "/tweets/#{first_tweet['data']['id']}", headers: headers
6582
expect(response).to be_success
6683
expect(response).to have_http_status(200)
67-
expect { JSONAPI.parse_response!(body) }.not_to raise_error
84+
expect(response.body).to be_valid_jsonapi
6885
expect(body).to eq(first_tweet)
6986

87+
# Delete first tweet
7088
delete "/tweets/#{first_tweet['data']['id']}"
7189
expect(response).to be_success
7290
expect(response).to have_http_status(204)
7391

92+
# List remaining tweets
7493
get '/tweets'
7594
expect(response).to be_success
7695
expect(response).to have_http_status(200)
77-
expect { JSONAPI.parse_response!(body) }.not_to raise_error
96+
expect(response.body).to be_valid_jsonapi
7897
expect(body['data'].first).to eq(second_tweet['data'])
7998
end
8099
end

0 commit comments

Comments
 (0)