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
refactor: overhaul body and query matching #1632
refactor: overhaul body and query matching #1632
Conversation
Also don't bother calling `transformRequestBodyFunction` or `matchBody` if there is no request body on the Interceptor.
Drop `deep-equal` and `qs` dependency. Replace `qs.parse` with `querystring.parse` from the std lib. The main difference between the two being that `qs` "unpacks" nested objects when the search keys use JSON path notation eg "foo[bar][0]". This has no affect on URL encoded form bodies during matching because we manually convert the notation to nested objects for comparison now, which means users can now provide expectations in either form. Similarly, when matching search params using a provided object, there is no net affect. The only breaking change is when a user provides a callback function to `.query()`. Replace `deep-equal` with a custom utility function in common.js. Doing so not only dropped a dependency, it also achieved a more generic utility for our usec ase with less code. Interceptor matching had some refactoring: - Query matching was moved to its own method in an effort to isolate concerns. - Matching the request method was moved to the top of the match method. - Debugging statements were updated as a baby step towards having more insight into why a match was missed. Fixes nock#507 Fixes nock#1552 BREAKING CHANGE: The only argument passed to the Interceptor.query callback now receives the output from querystring.parse instead of qs.parse. This means that instead of nested objects the argument will be a flat object.
@@ -412,3 +412,35 @@ test('query(true) will match when the path has no query', t => { | |||
t.end() | |||
}) | |||
}) | |||
|
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.
These two tests are the regression tests for #1552
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.
Looks great 👍
I'd like to dig into this a little bit, mostly in thinking clearly about exactly what's changed. I'm fine with the breaking change to the query() callback, though we should add a note to the API documentation (probably documenting both the 10.x and 11.x behaviors). |
@paulmelnikow sounds good. I'm going to hold off on the doc updates until you're ok with the change themselves. |
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.
👍
Thanks for giving me the time to read this!
I want to add that I'm in two minds about whether we should support this behavior. It is so common in frameworks that it is a kind of de facto standard, however since it's not really a standard, various systems, including backends written in other languages, may implement it subtly differently. In the future I wonder if we could disable the nested interpretation by default, and enable it with an option passed to nock()
.
Since we currently support it, I'm fine continuing to support it with this new implementation, and appreciate the cleanup. Just something to consider for the future.
🎉 This PR is included in version 11.0.0-beta.30 🎉 The release is available on: Your semantic-release bot 📦🚀 |
🎉 This PR is included in version 11.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
* refactor(match_body): options obj as arg instead of context Also don't bother calling `transformRequestBodyFunction` or `matchBody` if there is no request body on the Interceptor. * perf: prefer regexp.test over match when applicable * refactor: overhaul body and query matching Drop `deep-equal` and `qs` dependency. Replace `qs.parse` with `querystring.parse` from the std lib. The main difference between the two being that `qs` "unpacks" nested objects when the search keys use JSON path notation eg "foo[bar][0]". This has no affect on URL encoded form bodies during matching because we manually convert the notation to nested objects for comparison now, which means users can now provide expectations in either form. Similarly, when matching search params using a provided object, there is no net affect. The only breaking change is when a user provides a callback function to `.query()`. Replace `deep-equal` with a custom utility function in common.js. Doing so not only dropped a dependency, it also achieved a more generic utility for our usec ase with less code. Interceptor matching had some refactoring: - Query matching was moved to its own method in an effort to isolate concerns. - Matching the request method was moved to the top of the match method. - Debugging statements were updated as a baby step towards having more insight into why a match was missed. Fixes #507 Fixes #1552 BREAKING CHANGE: The only argument passed to the Interceptor.query callback now receives the output from querystring.parse instead of qs.parse. This means that instead of nested objects the argument will be a flat object.
* refactor(match_body): options obj as arg instead of context Also don't bother calling `transformRequestBodyFunction` or `matchBody` if there is no request body on the Interceptor. * perf: prefer regexp.test over match when applicable * refactor: overhaul body and query matching Drop `deep-equal` and `qs` dependency. Replace `qs.parse` with `querystring.parse` from the std lib. The main difference between the two being that `qs` "unpacks" nested objects when the search keys use JSON path notation eg "foo[bar][0]". This has no affect on URL encoded form bodies during matching because we manually convert the notation to nested objects for comparison now, which means users can now provide expectations in either form. Similarly, when matching search params using a provided object, there is no net affect. The only breaking change is when a user provides a callback function to `.query()`. Replace `deep-equal` with a custom utility function in common.js. Doing so not only dropped a dependency, it also achieved a more generic utility for our usec ase with less code. Interceptor matching had some refactoring: - Query matching was moved to its own method in an effort to isolate concerns. - Matching the request method was moved to the top of the match method. - Debugging statements were updated as a baby step towards having more insight into why a match was missed. Fixes #507 Fixes #1552 BREAKING CHANGE: The only argument passed to the Interceptor.query callback now receives the output from querystring.parse instead of qs.parse. This means that instead of nested objects the argument will be a flat object.
* refactor(match_body): options obj as arg instead of context Also don't bother calling `transformRequestBodyFunction` or `matchBody` if there is no request body on the Interceptor. * perf: prefer regexp.test over match when applicable * refactor: overhaul body and query matching Drop `deep-equal` and `qs` dependency. Replace `qs.parse` with `querystring.parse` from the std lib. The main difference between the two being that `qs` "unpacks" nested objects when the search keys use JSON path notation eg "foo[bar][0]". This has no affect on URL encoded form bodies during matching because we manually convert the notation to nested objects for comparison now, which means users can now provide expectations in either form. Similarly, when matching search params using a provided object, there is no net affect. The only breaking change is when a user provides a callback function to `.query()`. Replace `deep-equal` with a custom utility function in common.js. Doing so not only dropped a dependency, it also achieved a more generic utility for our usec ase with less code. Interceptor matching had some refactoring: - Query matching was moved to its own method in an effort to isolate concerns. - Matching the request method was moved to the top of the match method. - Debugging statements were updated as a baby step towards having more insight into why a match was missed. Fixes #507 Fixes #1552 BREAKING CHANGE: The only argument passed to the Interceptor.query callback now receives the output from querystring.parse instead of qs.parse. This means that instead of nested objects the argument will be a flat object.
Drop
deep-equal
andqs
dependencies.Replace
qs.parse
withquerystring.parse
from the std lib.The main difference between the two being that
qs
"unpacks" nestedobjects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net effect. The only breaking change is when a user provides a
callback function to
.query()
.Replace
deep-equal
with a custom utility function in common.js.Doing so not only dropped a dependency, it also achieved a more generic
utility for our use case with less code.
Interceptor matching had some refactoring:
Fixes #507
Fixes #1552
BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.