From cc96afb9b70ac2628e8c4c06655e36371577780a Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:07:25 +1000 Subject: [PATCH 01/14] Create .rspec file and remove require 'spec_helper' from all specs As spec_helper is required in all specs, created a default require in .rspec and remove from all specs. --- .rspec | 1 + spec/jsonapi/attributes_spec.rb | 2 -- spec/jsonapi/id_spec.rb | 2 -- spec/jsonapi/jsonapi_object_spec.rb | 2 -- spec/jsonapi/links_spec.rb | 2 -- spec/jsonapi/meta_spec.rb | 2 -- spec/jsonapi/type_spec.rb | 2 -- 7 files changed, 1 insertion(+), 12 deletions(-) create mode 100644 .rspec diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c7a3d35 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require ./spec/spec_helper.rb diff --git a/spec/jsonapi/attributes_spec.rb b/spec/jsonapi/attributes_spec.rb index fec83ac..57a0cac 100644 --- a/spec/jsonapi/attributes_spec.rb +++ b/spec/jsonapi/attributes_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec do let(:doc) do { diff --git a/spec/jsonapi/id_spec.rb b/spec/jsonapi/id_spec.rb index 96a42d0..620df73 100644 --- a/spec/jsonapi/id_spec.rb +++ b/spec/jsonapi/id_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec, '#have_id' do it 'succeeds when id matches' do expect('id' => 'foo').to have_id('foo') diff --git a/spec/jsonapi/jsonapi_object_spec.rb b/spec/jsonapi/jsonapi_object_spec.rb index 9f4539d..8001c90 100644 --- a/spec/jsonapi/jsonapi_object_spec.rb +++ b/spec/jsonapi/jsonapi_object_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec, '#have_jsonapi_object' do context 'when providing no value' do it 'succeeds when jsonapi object is present' do diff --git a/spec/jsonapi/links_spec.rb b/spec/jsonapi/links_spec.rb index cbca90e..496d0c1 100644 --- a/spec/jsonapi/links_spec.rb +++ b/spec/jsonapi/links_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec do let(:doc) do { diff --git a/spec/jsonapi/meta_spec.rb b/spec/jsonapi/meta_spec.rb index 9a9b134..e5f9401 100644 --- a/spec/jsonapi/meta_spec.rb +++ b/spec/jsonapi/meta_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec, '#have_meta' do context 'when providing no value' do it 'succeeds when meta is present' do diff --git a/spec/jsonapi/type_spec.rb b/spec/jsonapi/type_spec.rb index 1b23233..500df1d 100644 --- a/spec/jsonapi/type_spec.rb +++ b/spec/jsonapi/type_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - RSpec.describe JSONAPI::RSpec, '#have_type' do it 'succeeds when type matches' do expect('type' => 'foo').to have_type('foo') From 016868295713dab5211a70083c7487d60510c629 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:09:42 +1000 Subject: [PATCH 02/14] Create allow_symbolized_jsonapi config and as_indifferent_hash method Create configuration setting to allow the use of HashWithIndifferentAccess and symbolized hashes as source documents to match again. Incorporate as_different_hash method into JSONAPI::RSpec to provide a common utility to convert source documents into a known format (if allow_symbolized_jsonapi is enabled) --- lib/jsonapi/rspec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/jsonapi/rspec.rb b/lib/jsonapi/rspec.rb index af70a34..7414de2 100644 --- a/lib/jsonapi/rspec.rb +++ b/lib/jsonapi/rspec.rb @@ -7,6 +7,10 @@ require 'jsonapi/rspec/meta' require 'jsonapi/rspec/jsonapi_object' +RSpec.configure do |c| + c.add_setting :allow_symbolized_jsonapi, default: false +end + module JSONAPI module RSpec include Id @@ -16,5 +20,12 @@ module RSpec include Links include Meta include JsonapiObject + + def self.as_indifferent_hash(doc) + return doc unless ::RSpec.configuration.allow_symbolized_jsonapi + return doc.with_indifferent_access if doc.respond_to?(:with_indifferent_access) + + JSON.parse(JSON.generate(doc)) + end end end From b29bfae863692b64646115c526443d4caa02bc3a Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:10:54 +1000 Subject: [PATCH 03/14] Incorporate as_indifferent_hash into all matchers Start each matcher with a call to as_indifferent_hash to return a string keyed (or indifferent access) version of the source document. --- lib/jsonapi/rspec/attributes.rb | 2 ++ lib/jsonapi/rspec/id.rb | 4 +++- lib/jsonapi/rspec/jsonapi_object.rb | 1 + lib/jsonapi/rspec/links.rb | 2 ++ lib/jsonapi/rspec/meta.rb | 1 + lib/jsonapi/rspec/relationships.rb | 2 ++ lib/jsonapi/rspec/type.rb | 4 +++- 7 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/jsonapi/rspec/attributes.rb b/lib/jsonapi/rspec/attributes.rb index 09b064f..abddb1e 100644 --- a/lib/jsonapi/rspec/attributes.rb +++ b/lib/jsonapi/rspec/attributes.rb @@ -3,6 +3,7 @@ module RSpec module Attributes ::RSpec::Matchers.define :have_attribute do |attr| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) (actual['attributes'] || {}).key?(attr.to_s) && (!@val_set || actual['attributes'][attr.to_s] == @val) end @@ -15,6 +16,7 @@ module Attributes ::RSpec::Matchers.define :have_jsonapi_attributes do |*attrs| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) return false unless actual.key?('attributes') counted = (attrs.size == actual['attributes'].size) if @exactly diff --git a/lib/jsonapi/rspec/id.rb b/lib/jsonapi/rspec/id.rb index 3130610..504df38 100644 --- a/lib/jsonapi/rspec/id.rb +++ b/lib/jsonapi/rspec/id.rb @@ -2,7 +2,9 @@ module JSONAPI module RSpec module Id ::RSpec::Matchers.define :have_id do |expected| - match { |actual| actual['id'] == expected } + match do |actual| + JSONAPI::RSpec.as_indifferent_hash(actual)['id'] == expected + end end end end diff --git a/lib/jsonapi/rspec/jsonapi_object.rb b/lib/jsonapi/rspec/jsonapi_object.rb index 8916bc2..e6c252e 100644 --- a/lib/jsonapi/rspec/jsonapi_object.rb +++ b/lib/jsonapi/rspec/jsonapi_object.rb @@ -3,6 +3,7 @@ module RSpec module JsonapiObject ::RSpec::Matchers.define :have_jsonapi_object do |val| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) actual.key?('jsonapi') && (!val || actual['jsonapi'] == val) end diff --git a/lib/jsonapi/rspec/links.rb b/lib/jsonapi/rspec/links.rb index 3d8265a..62fb940 100644 --- a/lib/jsonapi/rspec/links.rb +++ b/lib/jsonapi/rspec/links.rb @@ -3,6 +3,7 @@ module RSpec module Links ::RSpec::Matchers.define :have_link do |link| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) actual.key?('links') && actual['links'].key?(link.to_s) && (!@val_set || actual['links'][link.to_s] == @val) end @@ -15,6 +16,7 @@ module Links ::RSpec::Matchers.define :have_links do |*links| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) return false unless actual.key?('links') links.all? { |link| actual['links'].key?(link.to_s) } diff --git a/lib/jsonapi/rspec/meta.rb b/lib/jsonapi/rspec/meta.rb index ac33e8c..c8983fa 100644 --- a/lib/jsonapi/rspec/meta.rb +++ b/lib/jsonapi/rspec/meta.rb @@ -3,6 +3,7 @@ module RSpec module Meta ::RSpec::Matchers.define :have_meta do |val| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) actual.key?('meta') && (!val || actual['meta'] == val) end diff --git a/lib/jsonapi/rspec/relationships.rb b/lib/jsonapi/rspec/relationships.rb index fbbe0da..50441e8 100644 --- a/lib/jsonapi/rspec/relationships.rb +++ b/lib/jsonapi/rspec/relationships.rb @@ -3,6 +3,7 @@ module RSpec module Relationships ::RSpec::Matchers.define :have_relationship do |rel| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) return false unless (actual['relationships'] || {}).key?(rel.to_s) !@data_set || actual['relationships'][rel.to_s]['data'] == @data_val @@ -25,6 +26,7 @@ module Relationships ::RSpec::Matchers.define :have_relationships do |*rels| match do |actual| + actual = JSONAPI::RSpec.as_indifferent_hash(actual) return false unless actual.key?('relationships') rels.all? { |rel| actual['relationships'].key?(rel) } diff --git a/lib/jsonapi/rspec/type.rb b/lib/jsonapi/rspec/type.rb index 71d6a18..a2272ac 100644 --- a/lib/jsonapi/rspec/type.rb +++ b/lib/jsonapi/rspec/type.rb @@ -2,7 +2,9 @@ module JSONAPI module RSpec module Type ::RSpec::Matchers.define :have_type do |expected| - match { |actual| actual['type'] == expected } + match do |actual| + JSONAPI::RSpec.as_indifferent_hash(actual)['type'] == expected + end end end end From 3d20cd23e1f829e15004205f86f8ab83a2ada664 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:11:43 +1000 Subject: [PATCH 04/14] Add new cops to .rubocop.yml to remove warnings. Also added ignore for the block length for the specs directory. --- .rubocop.yml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index ef28b33..1972ae6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,7 @@ +Metrics/BlockLength: + Exclude: + - 'spec/**/*_spec.rb' + require: - rubocop-performance @@ -6,3 +10,43 @@ Style/FrozenStringLiteralComment: Style/Documentation: Enabled: false + +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: true + +Layout/SpaceAroundMethodCallOperator: + Enabled: true + +Lint/DeprecatedOpenSSLConstant: + Enabled: true + +Lint/MixedRegexpCaptureTypes: + Enabled: true + +Lint/RaiseException: + Enabled: true + +Lint/StructNewOverride: + Enabled: true + +Style/ExponentialNotation: + Enabled: true + +Style/HashEachMethods: + Enabled: true + +Style/HashTransformKeys: + Enabled: true + +Style/HashTransformValues: + Enabled: true + +Style/RedundantRegexpCharacterClass: + Enabled: true + +Style/RedundantRegexpEscape: + Enabled: true + +Style/SlicingWithRange: + Enabled: true + From 894e393bd0e5e2c9894c58df7be02e43aba61b36 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:22:50 +1000 Subject: [PATCH 05/14] Refactor attributes spec Refactor attributes spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/attributes_spec.rb | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/spec/jsonapi/attributes_spec.rb b/spec/jsonapi/attributes_spec.rb index 57a0cac..63add50 100644 --- a/spec/jsonapi/attributes_spec.rb +++ b/spec/jsonapi/attributes_spec.rb @@ -1,5 +1,5 @@ RSpec.describe JSONAPI::RSpec do - let(:doc) do + json_doc = { 'attributes' => { 'one' => 1, @@ -7,17 +7,28 @@ 'four' => 3 } } - end describe '#have_attribute' do - it { expect(doc).to have_attribute(:one) } - it { expect(doc).not_to have_attribute(:five) } + context 'when attributes is present' do + it { expect(json_doc).to have_attribute(:one) } + it { expect(json_doc).not_to have_attribute(:five) } + end + + context 'when attributes is not present' do + it { expect({}).not_to have_attribute(:one) } + end end describe '#have_jsonapi_attributes' do - it { expect(doc).to have_jsonapi_attributes(:one, :two) } - it { expect(doc).not_to have_jsonapi_attributes(:two, :five) } - it { expect(doc).to have_jsonapi_attributes(:one, :two, :four).exactly } - it { expect(doc).not_to have_jsonapi_attributes(:one).exactly } + context 'when attributes is present' do + it { expect(json_doc).to have_jsonapi_attributes(:one, 'two') } + it { expect(json_doc).not_to have_jsonapi_attributes(:two, 'five') } + it { expect(json_doc).to have_jsonapi_attributes(:one, :two, 'four').exactly } + it { expect(json_doc).not_to have_jsonapi_attributes(:one).exactly } + end + + context 'when attributes is not present' do + it { expect({}).not_to have_jsonapi_attributes(:one, 'two') } + end end end From 1cc464cafd40d2d324a5075b728722128e83a4b7 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 26 Jun 2020 11:10:04 +1000 Subject: [PATCH 06/14] Refactor links spec Refactor links spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/links_spec.rb | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/spec/jsonapi/links_spec.rb b/spec/jsonapi/links_spec.rb index 496d0c1..293fefd 100644 --- a/spec/jsonapi/links_spec.rb +++ b/spec/jsonapi/links_spec.rb @@ -1,22 +1,33 @@ RSpec.describe JSONAPI::RSpec do - let(:doc) do + json_doc = { 'links' => { 'self' => 'self_link', 'related' => 'related_link' } } - end - context '#have_link' do - it { expect(doc).to have_link(:self) } - it { expect(doc).to have_link(:self).with_value('self_link') } - it { expect(doc).not_to have_link(:self).with_value('any_link') } - it { expect(doc).not_to have_link(:any) } + describe '#have_link' do + context 'when links is present' do + it { expect(json_doc).to have_link(:self) } + it { expect(json_doc).to have_link(:self).with_value('self_link') } + it { expect(json_doc).not_to have_link(:self).with_value('any_link') } + it { expect(json_doc).not_to have_link(:any) } + end + + context 'when links is not present' do + it { expect({}).not_to have_link(:self) } + end end - context '#have_links' do - it { expect(doc).to have_links(:self, :related) } - it { expect(doc).not_to have_links(:self, :other) } + describe '#have_links' do + context 'when links is present' do + it { expect(json_doc).to have_links(:self, 'related') } + it { expect(json_doc).not_to have_links(:self, 'other') } + end + + context 'when links is not present' do + it { expect({}).not_to have_links(:self, 'related') } + end end end From 28d8ff08d309b5eb021aa657c8c5d8dcff53b6e4 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:28:46 +1000 Subject: [PATCH 07/14] Create relationships spec based on attributes and links spec --- spec/jsonapi/relationships_spec.rb | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 spec/jsonapi/relationships_spec.rb diff --git a/spec/jsonapi/relationships_spec.rb b/spec/jsonapi/relationships_spec.rb new file mode 100644 index 0000000..c5c7a3b --- /dev/null +++ b/spec/jsonapi/relationships_spec.rb @@ -0,0 +1,50 @@ +RSpec.describe JSONAPI::RSpec do + json_doc = + { + 'relationships' => { + 'posts' => { + 'data' => { + 'id' => '1', + 'type' => 'posts' + } + }, + 'comments' => { + 'data' => [{ + 'id' => '1', + 'type' => 'posts' + }, { + 'id' => '2', + 'type' => 'hides' + }] + } + } + } + + describe '#have_relationship' do + context 'when relationships is present' do + it { expect(json_doc).to have_relationship('posts') } + it { expect(json_doc).not_to have_relationship('mails') } + it { expect(json_doc).to have_relationship('posts').with_data({ 'id' => '1', 'type' => 'posts' }) } + it do + expect(json_doc).to have_relationship('comments').with_data( + [{ 'id' => '1', 'type' => 'posts' }, { 'id' => '2', 'type' => 'hides' }] + ) + end + end + + context 'when relationships is not present' do + it { expect({}).not_to have_relationship('posts') } + end + end + + describe '#have_relationships' do + context 'when relationships is present' do + it { expect(json_doc).to have_relationships('posts', 'comments') } + it { expect(json_doc).not_to have_relationships('posts', 'comments', 'mails') } + end + + context 'when relationships is not present' do + it { expect({}).not_to have_relationships('posts', 'comments') } + end + end +end From ab380704e72d4babdacc2c7e40ef902fd5f068ff Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:35:52 +1000 Subject: [PATCH 08/14] Standardise id spec and add symbolized source doc Refactored the id spec to align it with the pattern provided in the links and attributes specs. Incorporate symbolized source document tests inline with the attributes and relationships specs --- spec/jsonapi/id_spec.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spec/jsonapi/id_spec.rb b/spec/jsonapi/id_spec.rb index 620df73..f61c87d 100644 --- a/spec/jsonapi/id_spec.rb +++ b/spec/jsonapi/id_spec.rb @@ -1,13 +1,17 @@ RSpec.describe JSONAPI::RSpec, '#have_id' do - it 'succeeds when id matches' do - expect('id' => 'foo').to have_id('foo') - end + json_doc = { 'id' => 'foo' } + symbol_doc = { id: 'foo' } - it 'fails when id mismatches' do - expect('id' => 'foo').not_to have_id('bar') - end + describe '#have_id' do + [json_doc, symbol_doc].each do |doc| + subject { doc } + before(:each) { RSpec.configuration.allow_symbolized_jsonapi = (doc == symbol_doc) } - it 'fails when id is absent' do - expect({}).not_to have_id('foo') + it { is_expected.to have_id('foo') } + it { is_expected.not_to have_id('bar') } + end + it 'is expected not to have id "foo" when id is not present' do + expect({}).not_to have_id('foo') + end end end From 5116a07bf88190b5f86848e3effdf3ef14723fa7 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 26 Jun 2020 11:12:39 +1000 Subject: [PATCH 09/14] Refactor id spec Refactor id spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/id_spec.rb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/spec/jsonapi/id_spec.rb b/spec/jsonapi/id_spec.rb index f61c87d..bb1d587 100644 --- a/spec/jsonapi/id_spec.rb +++ b/spec/jsonapi/id_spec.rb @@ -1,17 +1,16 @@ RSpec.describe JSONAPI::RSpec, '#have_id' do - json_doc = { 'id' => 'foo' } - symbol_doc = { id: 'foo' } + json_doc = + { + 'id' => 'foo' + } describe '#have_id' do - [json_doc, symbol_doc].each do |doc| - subject { doc } - before(:each) { RSpec.configuration.allow_symbolized_jsonapi = (doc == symbol_doc) } - - it { is_expected.to have_id('foo') } - it { is_expected.not_to have_id('bar') } + context 'when id is present' do + it { expect(json_doc).to have_id('foo') } + it { expect(json_doc).not_to have_id('bar') } end - it 'is expected not to have id "foo" when id is not present' do - expect({}).not_to have_id('foo') + context 'when id is not present' do + it { expect({}).not_to have_id('foo') } end end end From 988bc9ef4a218c6e2116c2761edda7f5a1249ead Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 11:44:20 +1000 Subject: [PATCH 10/14] Refactor jsonapi spec Refactor jsonapi spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/jsonapi_object_spec.rb | 36 ++++++++++++----------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/spec/jsonapi/jsonapi_object_spec.rb b/spec/jsonapi/jsonapi_object_spec.rb index 8001c90..1121fca 100644 --- a/spec/jsonapi/jsonapi_object_spec.rb +++ b/spec/jsonapi/jsonapi_object_spec.rb @@ -1,27 +1,21 @@ -RSpec.describe JSONAPI::RSpec, '#have_jsonapi_object' do - context 'when providing no value' do - it 'succeeds when jsonapi object is present' do - expect('jsonapi' => { 'version' => '1.0' }).to have_jsonapi_object - end - - it 'fails when jsonapi object is absent' do - expect({}).not_to have_jsonapi_object - end - end - - context 'when providing a value' do - it 'succeeds when jsonapi object matches' do - expect('jsonapi' => { 'version' => '1.0' }) - .to have_jsonapi_object('version' => '1.0') - end +RSpec.describe JSONAPI::RSpec do + json_doc = + { + 'jsonapi' => { + 'version' => '1.0' + } + } - it 'fails when jsonapi object mismatches' do - expect('jsonapi' => { 'version' => '2.0' }) - .not_to have_jsonapi_object('version' => '1.0') + describe '#have_jsonapi_object' do + context 'when jsonapi is present' do + it { expect(json_doc).to have_jsonapi_object } + it { expect(json_doc).to have_jsonapi_object('version' => '1.0') } + it { expect(json_doc).not_to have_jsonapi_object('version' => '2.0') } end - it 'fails when jsonapi object is absent' do - expect({}).not_to have_jsonapi_object('version' => '1.0') + context 'when jsonapi is not present' do + it { expect({}).not_to have_jsonapi_object } + it { expect({}).not_to have_jsonapi_object('version' => '1.0') } end end end From 865ff4bda5ad82f6aafedca64b14330211b345cd Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 12:37:14 +1000 Subject: [PATCH 11/14] Refactor meta spec Refactor meta spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/meta_spec.rb | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/spec/jsonapi/meta_spec.rb b/spec/jsonapi/meta_spec.rb index e5f9401..15bd01a 100644 --- a/spec/jsonapi/meta_spec.rb +++ b/spec/jsonapi/meta_spec.rb @@ -1,25 +1,21 @@ -RSpec.describe JSONAPI::RSpec, '#have_meta' do - context 'when providing no value' do - it 'succeeds when meta is present' do - expect('meta' => {}).to have_meta - end - - it 'fails when meta is absent' do - expect({}).not_to have_meta - end - end - - context 'when providing a value' do - it 'succeeds when meta matches' do - expect('meta' => { foo: 'bar' }).to have_meta(foo: 'bar') - end +RSpec.describe JSONAPI::RSpec do + json_doc = + { + 'meta' => { + 'foo' => 'bar' + } + } - it 'fails when meta mismatches' do - expect('meta' => { foo: 'bar' }).not_to have_meta(bar: 'baz') + describe '#have_meta' do + context 'when meta is present' do + it { expect(json_doc).to have_meta } + it { expect(json_doc).to have_meta('foo' => 'bar') } + it { expect(json_doc).not_to have_meta('foo' => 'baz') } end - it 'fails when meta is absent' do - expect({}).not_to have_meta(foo: 'bar') + context 'when meta is not present' do + it { expect({}).not_to have_meta } + it { expect({}).not_to have_meta('foo' => 'bar') } end end end From 63c8ab5a59c494ccd76472eb0fe652ae87cf4dd7 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 12 Jun 2020 12:40:20 +1000 Subject: [PATCH 12/14] Refactor type spec Refactor type spec to remove the it clauses so the standard test output is visible in documentation mode. Added present and not present tests to align with other existing tests. --- spec/jsonapi/type_spec.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spec/jsonapi/type_spec.rb b/spec/jsonapi/type_spec.rb index 500df1d..e6639db 100644 --- a/spec/jsonapi/type_spec.rb +++ b/spec/jsonapi/type_spec.rb @@ -1,13 +1,17 @@ RSpec.describe JSONAPI::RSpec, '#have_type' do - it 'succeeds when type matches' do - expect('type' => 'foo').to have_type('foo') - end + json_doc = + { + 'type' => 'foo' + } - it 'fails when type mismatches' do - expect('type' => 'foo').not_to have_type('bar') - end + describe '#have_tyoe' do + context 'when type is present' do + it { expect(json_doc).to have_type('foo') } + it { expect(json_doc).not_to have_type('bar') } + end - it 'fails when type is absent' do - expect({}).not_to have_type('foo') + context 'when type is not present' do + it { expect({}).not_to have_type('foo') } + end end end From 88ad5f86b0be6a6ed0600b6e4d89a7c001e10232 Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Fri, 26 Jun 2020 11:17:21 +1000 Subject: [PATCH 13/14] Add rspec_spec and sample document Created spec for the as_indifferent_hash method to validate its responses with the possible configuration options. Created a sample_jsonapi module to provide the various versions of the source and target documents. --- spec/rspec_spec.rb | 47 +++++++++++ spec/support/sample_jsonapi.rb | 144 +++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 spec/rspec_spec.rb create mode 100644 spec/support/sample_jsonapi.rb diff --git a/spec/rspec_spec.rb b/spec/rspec_spec.rb new file mode 100644 index 0000000..4164215 --- /dev/null +++ b/spec/rspec_spec.rb @@ -0,0 +1,47 @@ +require 'support/sample_jsonapi' + +RSpec.describe JSONAPI::RSpec do + include SampleJsonapi + + before(:each) { RSpec.configuration.allow_symbolized_jsonapi = enable } + + describe 'with allow_symbolized_jsonapi true' do + let(:enable) { true } + + it 'returns a string keyed hash unchanged' do + expect(JSONAPI::RSpec.as_indifferent_hash(document)).to eql(document) + end + + it 'returns an indifferent hash unchanged' do + expect( + JSONAPI::RSpec.as_indifferent_hash( + indifferent_document + ).respond_to?(:with_indifferent_access) + ).to be_truthy + end + + it 'returns a symbolized hash with stringifyed keys' do + expect(JSONAPI::RSpec.as_indifferent_hash(symbolized_document)).to eql(document) + end + end + + describe 'with allow_symbolized_jsonapi false' do + let(:enable) { false } + + it 'returns a string keyed hash unchanged' do + expect(JSONAPI::RSpec.as_indifferent_hash(document)).to eql(document) + end + + it 'returns an indifferent hash unchanged' do + expect( + JSONAPI::RSpec.as_indifferent_hash( + indifferent_document + ).respond_to?(:with_indifferent_access) + ).to be_truthy + end + + it 'returns a symbolized hash unchanged' do + expect(JSONAPI::RSpec.as_indifferent_hash(symbolized_document)).to eql(symbolized_document) + end + end +end diff --git a/spec/support/sample_jsonapi.rb b/spec/support/sample_jsonapi.rb new file mode 100644 index 0000000..3757b04 --- /dev/null +++ b/spec/support/sample_jsonapi.rb @@ -0,0 +1,144 @@ +require 'active_support/core_ext/hash/indifferent_access' + +module SampleJsonapi # rubocop:disable Metrics/ModuleLength + SAMPLE_JSONAPI = { + 'jsonapi' => { + 'version' => '1.0' + }, + 'links' => { + 'self' => 'http://example.com/articles', + 'next' => 'http://example.com/articles?page[offset]=2', + 'last' => 'http://example.com/articles?page[offset]=10' + }, + 'data' => [ + { + 'type' => 'articles', + 'id' => '1', + 'attributes' => { + 'title' => 'JSON API paints my bikeshed!' + }, + 'relationships' => { + 'author' => { + 'links' => { + 'self' => 'http://example.com/articles/1/relationships/author', + 'related' => 'http://example.com/articles/1/author' + }, + 'data' => { + 'type' => 'people', + 'id' => '9' + } + }, + 'comments' => { + 'links' => { + 'self' => 'http://example.com/articles/1/relationships/comments', + 'related' => 'http://example.com/articles/1/comments' + }, + 'data' => [ + { + 'type' => 'comments', + 'id' => '5' + }, + { + 'type' => 'comments', + 'id' => '12' + } + ] + } + }, + 'links' => { + 'self' => 'http://example.com/articles/1' + } + } + ], + 'included' => [ + { + 'type' => 'people', + 'id' => '9', + 'attributes' => { + 'first-name' => 'Dan', + 'last-name' => 'Gebhardt', + 'twitter' => 'dgeb' + }, + 'links' => { + 'self' => 'http://example.com/people/9' + } + }, + { + 'type' => 'comments', + 'id' => '5', + 'attributes' => { + 'body' => 'First!' + }, + 'relationships' => { + 'author' => { + 'data' => { + 'type' => 'people', + 'id' => '2' + } + } + }, + 'links' => { + 'self' => 'http://example.com/comments/5' + } + }, + { + 'type' => 'comments', + 'id' => '12', + 'attributes' => { + 'body' => 'I like XML better' + }, + 'relationships' => { + 'author' => { + 'data' => { + 'type' => 'people', + 'id' => '9' + } + } + }, + 'links' => { + 'self' => 'http://example.com/comments/12' + } + } + ], + 'meta' => { + 'totalPages' => 13, + 'numberOfViews' => 25 + } + }.freeze + + # document formats for rspec as_indifferent_hash testing + + def document + SAMPLE_JSONAPI + end + + def symbolized_document + symbolize_keys(SAMPLE_JSONAPI) + end + + def indifferent_document + SAMPLE_JSONAPI.with_indifferent_access + end + + def symbolize_keys(doc) + newdoc = doc.transform_keys(&:to_sym) + newdoc.transform_values! do |val| + if val.respond_to?('transform_keys!') + symbolize_keys(val) + elsif val.is_a?(Array) + symbolize_array(val) + else + val + end + end + end + + def symbolize_array(array) + array.map do |element| + next unless element.respond_to?('transform_keys!') || + element.respond_to?('each') + + symbolize_keys(element) + end + end +end From a66499b8ad6a35c1aa6fdaa032ebb65378f8146e Mon Sep 17 00:00:00 2001 From: Stephen Anderson Date: Tue, 16 Jun 2020 10:04:19 +1000 Subject: [PATCH 14/14] Add indifferent matching configuration option to the README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 6c6983f..4f2f7f8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,17 @@ Available matchers: * `expect(document).to have_jsonapi_object` * `expect(document).to have_jsonapi_object('version' => '1.0')` +### Indifferent Matching +```ruby +# spec/spec_helpers.rb + +RSpec.configure do |config| + # ... + config.allow_symbolized_jsonapi = true +end +``` +The configuration above allows the RSpec matchers to work with a symbolized jsonapi source document. + ## Advanced examples Checking for an included resource: