-
Notifications
You must be signed in to change notification settings - Fork 36
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
Add support for Server Variables and relevant tests in Chai OpenAPI Response Validator #161
Add support for Server Variables and relevant tests in Chai OpenAPI Response Validator #161
Conversation
…esponse Validator
Codecov Report
@@ Coverage Diff @@
## master #161 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 33 33
Lines 646 665 +19
Branches 47 47
=========================================
+ Hits 646 665 +19
Continue to review full report at Codecov.
|
Cheers, let's get the Chai code ready to merge, then port it to Jest. I'll review this code this week, and it'll be great if Nitwel confirms it functions as requested |
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 very much for this, great to see plenty of test cases. I think we can ignore server variables in the host, and we may need to add one more test case to cover an edge case, but otherwise the suggestions are minor!
commonTestResources/exampleOpenApiFiles/valid/serversDefinedDifferently/withServerVariables.yml
Outdated
Show resolved
Hide resolved
packages/chai-openapi-response-validator/lib/openapi-validator/lib/classes/OpenApi3Spec.js
Outdated
Show resolved
Hide resolved
...napi-response-validator/test/assertions/satisfyApiSpec/specsDefineServersDifferently.test.js
Outdated
Show resolved
Hide resolved
status: 200, | ||
req: { | ||
method: 'GET', | ||
path: 'https://test.com:1234/test/responseBody/string', |
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.
I don't think a real req.path
(e.g. from axios, superagent) contains the host (following this definition: scheme://host:port/path?query
). You can confirm this yourself running our differentRequestModules.test.js
tests with the debugger.
(Note that in the preceding test blocks, whenever req.path
overlaps with a server
URL from the OpenAPI spec, only the path overlaps)
This probably means your new replaceServerVarsInURLs
function just needs to act on server variables in the path
, ignoring those in the host
.
(And I guess we need to add a test case with multiple server variables in the path
, to make sure the final solution handles more than 1 variable in the path
)
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.
You're absolutely right, about to push changes to the tests which reflect real request structures. I have left the server variables in the spec to ensure that we work as expected when they are included. Agree we only need to change the variables after the paths - is detecting the start of the path as simple as looking for the first single /
or are there some edge cases we would also need to be able to detect?
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.
you may be able to make use of url.parse
e.g. https://github.com/RuntimeTools/OpenAPIValidators/blob/48eddb49bdc5a18af4de01bfb1055d315335ff26/packages/chai-openapi-response-validator/lib/openapi-validator/lib/utils.js#L11
commonTestResources/exampleOpenApiFiles/valid/serversDefinedDifferently/withServerVariables.yml
Outdated
Show resolved
Hide resolved
expect(assertion).to.throw( | ||
AssertionError, | ||
`'/nonExistentEndpointPath' matches servers ${inspect([ | ||
'https://test.com:1234', |
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.
Since this PR was opened, we decided to list only what the user wrote in their spec. Here this PR lists all the possible combinations of servers, which may be inconsistent with the decision.
An alternative error message of '/nonExistentEndpointPath' matches servers 'https://test.com/{serverVariable1}' but no <server/endpointPath> combinations
may be easier for the user to debug. (I don't think we need to list all the server variables out - they can check their spec).
(btw, master
may already output this error message, which would mean no extra implementation for you here)
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.
I think we might actually want to be a little more specific than this, and it goes hand in hand with the comment you made elsewhere about only changing the server variables in the path.
I.e. in my tests I have a server with a port variable, and a path variable: https://test.com:{portVariable}/{pathVariable}
. When I make a request with the path /defaultPathVariable
at the moment I would get back:
'/defaultPathVariable' matches servers [
'https://test.com:1234/defaultPathVariable',
'https://test.com:5678/defaultPathVariable'
]
Obviously the multiple servers with different port numbers is excessive, however if we changed it to
'/defaultPathVariable' matches servers [
'https://test.com:{portVariable}/{pathVariable}'
]
Then it's actually too vague, since in reality the request only matches one of the pathVariable
enums: defaultPathVariable
, not all pathVariable
enums.
Instead, if we do the work to only change the server variables in the path, then it should be possible to give the following error message, which I think is the preferred solution:
'/defaultPathVariable' matches servers [
'https://test.com:{portVariable}/defaultPathVariable'
]
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.
well put, I agree!
return serverVarMap; | ||
} | ||
|
||
function replaceServerVarsInURLs (serverURLs, serverVarMap) { |
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.
Although the tests prove this function works, ideally I'd prefer a simpler, more intuitive function if possible (esp without recursion).
I'll re-review this function after we've resolved the other comments, to see if we can think of a way to write it so that a newcomer (or I) can understand it easily :)
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.
Happy to work on this another way, but not exactly sure how else to approach it. If you have any suggestions I'd be happy to take another crack at it.
I've pushed another commit which resolves the minor comments you had with the code. Happy to also do the work for splitting the host and path parts of the server URL, but want to make sure I'm doing it correctly and not somehow breaking other things by splitting in the wrong place in certain scenarios. |
More thoughts, having looked at this more closely: Given:
This PR already contains most/all of the test cases we need. We could rename our test cases roughly like this to clarify exactly what we are testing:
Our test openapi.yml could be this?
What do you think? edit: updated with more thoughts, you can see a PoC branch at https://github.com/RuntimeTools/OpenAPIValidators/compare/89-add-server-variable-support?expand=1 |
Superceded by #222. Thanks @JonnySpruce for your work on this, you'll be credited in the release! |
I believe this PR resolves #89, by adding support for server variables. I have added all tests and code for the Chai plugin - the Jest plugin is still TODO at this stage, although now the code is written it should be very easy to port across.
@Nitwel - can you confirm this resolves the issue for you?