-
Notifications
You must be signed in to change notification settings - Fork 23
Allow jsonapi-rspec to match Symbol or String based source documents #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@sa73917 thank you for the contribution and the nice PR!!! Before we proceed with the full review, I'd like to raise some questions and try to understand your approach a bit on a higher level... Particularly, I believe you took the ActiveSupport approach here, and ended up monkey-patching tested data (based on the Would you reconsider the approach and instead use the core Consider this... module JSONAPI
module RSpec
mattr_accessor :use_indifferent_access
def as_indifferent_hash(doc)
return doc unless self.use_indifferent_access
return doc.with_indifferent_access if doc.respond_to?(:with_indifferent_access) && self.use_indifferent_access
JSON.parse(JSON.generate(doc))
end
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'] == JSONAPI::RSpec.as_indifferent_hash(val))
end
end
end
end
end An in a similar manner just convert the names to string if the indifferent access is set. Another important thing to mention is that I believe this should be an absolutely optional feature. JSONAPI spec clearly communicates that the format is JSON, it's just the Ruby that blurries the lines between how JSON can be parsed/handled. As in, a parsed JSON response would never have symbols or mixed key names in it... Let me know what you think and thanks again for the contribution! |
Hi @stas , thanks for the quick reply :). I'm more than happy to consider any approach as I'm pretty new to ruby (and this being a first PR here, open to feedback).. Using Reading through the code you've provided above to add a toggle for indifferent access (assuming I'm reading things right), you're relying on various rails methods/variables ( I agree with you that the jsonapi payload should be JSON rather than a Symbol key'd hash but symbolizing the payload makes other (non jsonapi-rspec) tests far more readable and having two versions of the payload, one for jsonapi-rspec tests and one for all the others seems wonky - hence this PR. Anyway, I was playing around with your example this morning (though with a manually created setter/getter for the toggle in the module) and as written Meta was just returning ::RSpec::Matchers.define :have_type do |expected|
match do |actual|
actual = JSONAPI::RSpec.as_indifferent_hash(actual) if @use_indifferent_access
(actual || {})['type'] == expected
end
chain :with_indifferent_access do
@use_indifferent_access = true
end
end which makes it obvious in the test
and makes the output pretty clear: JSONAPI::RSpec::Type
#have_type
with empty document
is expected not to have type "bar"
with stringifyed doc
is expected to have type "bar" with indifferent access
is expected not to have type "foo" with indifferent access
without indifferent access
is expected to have type "bar"
with symbolized doc
is expected not to have type "foo" with indifferent access
is expected to have type "bar" with indifferent access
without indifferent access
is expected not to have type "bar" But made me wonder whether adding Post edit - understand now that it parses the entire spec file before running the individual tests in it - so setting the toggle on and off between tests doesn't work :) - hence my somewhat random results earlier |
Yup, you're right, in fact,
Apologies for that, I was in a rush, please look at the code I pasted as more of a pseudocode. It's definitely not working 🙈
Indeed, this is actually a nice idea, but I believe it would be a lot to type for some folks, so a more global option would be desired... Thanks again for working on this! 🙇 |
f01d01b
to
6dd89e0
Compare
@stas - I think it's in a pretty good state to review now. I've removed the monkey-patching and used the JSON parsing logic (though I do wonder if this will have a performance impact - hopefully not given most of these payloads are unlikely to be huge?) I've refactored all the rspec tests so they all loop through:
I've made the allow_symbolized_jsonapi setting impact how the source document is handled but it doesn't affect the parameter values. ie. { version: '1.0' } and { "version" => "1.0" } are both accepted by the jsonapi_object matcher regardless of the setting. Let me know if there's anything more you think I should change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sa73917 I did a quick review, aside from some cleanups, I'd like us to reduce the changeset to minimum and do not alter existing tests. There's no need for all the tests to be run twice, just add a new test where the new optional configuration is enabled, or consider adding a unit test for the new module method.
Also, please try to touch as little the existing code, overall, we're adding a new functionality and not rewriting the whole gem. Let's just keep things simple.
I'm sorry for having to ask you to reconsider some of the work you've done and thanks again for working on this 🙈 🙇
6dd89e0
to
935eeaa
Compare
As spec_helper is required in all specs, created a default require in .rspec and remove from all specs.
935eeaa
to
2bedd7f
Compare
@stas - finally had a chance to go through and refactor everything to split out the two changes that were in this PR. PR #19 has the code to allow jsonapi-rspec to accept Symbol/String Parameters, and this one has the code to allow jsonapi-rspec to match against Symbol/String source documents. (obviously a rebase in one of them's future) Hopefully a little easier to review - thanks for your patience :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sa73917 this looks great. I suggested a change related to how the tests are organized. Let me know if you have time to take a look and quickly update those. Thank you! 🙇
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)
Start each matcher with a call to as_indifferent_hash to return a string keyed (or indifferent access) version of the source document.
Also added ignore for the block length for the specs directory.
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.
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.
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
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.
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.
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.
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.
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.
7859481
to
a66499b
Compare
@stas I've run through and refactored all the specs as requested. Makes sense to have test of as_indifferent_hash and keep the noise out of the other tests so I've put together one that tests the various combinations. All of the existing tests are now in the same format, all include a present/not present test and where applicable include symbol and string parameters. |
What is the current behavior?
The current version of the jsonapi-rspec matcher requires the source jsonapi document to be a string keyed hash and requires all hash parameters to use the same key style as the source jsonapi document.
What is the new behavior?
All matchers now support:
Checklist
Please make sure the following requirements are complete:
Tests for the changes have been added (for bug fixes / features)
All Matchers have a spec that tests the matcher against Symbol and String keyed jsonapi documents. The Relationships matcher did not have an spec so I have created one based on the sample matchers in the README and the code.
Where applicable the tests include Symbol and String keyed hash parameters
Docs have been reviewed and added / updated if needed (for bug fixes / features)
README.md document has been updated to provide an example spec helper, and examples of String and Symbol based keys.
All automated checks pass (CI/CD)
rubocop and rspec tests pass.
NB1. I have added the new rubocop tests and a few cop defaults to rubocop.yml in 633b06.
NB2. I have added spec_helper into .rspec to save including it in all specs in 33eb64.