restmatcher
v1.1.16
Published
Matchers for Jest checking Responses returned via SuperTest
Downloads
273
Readme
restmatcher
Matchers for Jest checking Responses returned via SuperTest
Install
Install with npm:
npm install --save-dev restmatcher
Setup
You need to somehow import the restmatcher module in order to extend expect
at runtime. This can be done by either importing the module in your tests (simply import "restmatcher"
) or by importing it in your setup file.
Usage of Matchers
You send a request to your (express) app via SuperTest. Then you can use restmatcher for matching the response.
Note that in any case invalid or missing status codes in the response lead to failing tests,
even when used with not
.
statusCode
Will match status code in response against given expectation.
The status code could be a number, a string, an array with strings or numbers, or undefined.
- '' (or simply not providing 3 digits) matches any number after the prefix, e.g. "4" or "4" matches 400, 401, 402, etc.
- if the pattern is provided as a number, it is converted to a string and 'x' is appended at the end (e.g. 4 is converted to "4xx")
- '?' o 'x' matches any single digit, e.g. "4?1" matches 401, 411, 421, etc.
- Several codes can be combined by using an array. If no code is provided, any status code matches (but there must be any status code)
If any status code is expected, an invalid or missing code will lead the test to fail, even if not.statusCode is used.
toHaveValidationErrorsExactly
This works with express-validator. It expects errors to be found in the body, e.g.
const response = {
status: 400,
body: {
"errors": [
{
"location": "params",
"msg": "Invalid ID",
"path": "resID",
"value": "1234"
}
]
}
This structure can easily be created like that:
resRouter.get("/:resID",
param("resID").isMongoId(),
async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).send({ errors: errors.array() });
}
...
})
If you set up your project like that, you can use toHaveValidationErrorsExactly
to check the validations errors, e.g.
test("some GET, invalid ID", async () => {
const request = supertest(app);
const response = await request.get(`/resource/1234`)
// assuming your path is "/resource/:resID"
expect(response)
.toHaveValidationErrorsExactly({ status: "4xx", params: "resID" })
})
toHaveValidationErrorsExactly
takes an object with properties for
- every location ("body", "query", "params", "cookies", "headers") or an unspecific location ("anyLocation"). All these properties are optional and can either be a string or an array of strings.
- the status code; details see statusCode matcher
Here are some examples:
expect(res).toHaveValidationErrorsExactly()
: succeeds if no validation error is foundexpect(res).not.toHaveValidationErrorsExactly()
: succeeds if no validations errors were omittedexpect(res).toHaveValidationErrorsExactly({status: 400})
: succeeds if no validation error is found and status code is 400expect(res).toHaveValidationErrorsExactly({status: "4xx"})
: succeeds if no validation error is found and status code is a client errorexpect(res).toHaveValidationErrorsExactly({params: "resID"})
: succeeds if the parameter resID caused a validation error and no more errors occurred!expect(res).toHaveValidationErrorsExactly({anyLocation: "ID"})
: succeeds if any field (body, query, params etc.) named "ID" caused a validation error and no more errors occurred!expect(res2).toHaveValidationErrorsExactly({params: ["resID", "otherID"]});
: succeeds if parameters resID and otherID caused a validation error (and no other fields!)
Attention: Using not
might be a little bit misleading here. It inverses the expectation, which maybe does not 100% match your expectation. E.g., expect(res2).not.toHaveValidationErrorsExactly({params: "resID"})
succeeds, if resID and another field omitted validation errors. Emphasize the exactly at the end of this matcher!
toHaveAtLeastValidationErrors
toHaveAtLeastValidationErrors
is very similar to toHaveValidationErrorsExactly
, except that it ignores superfluous validation errors and it expects at least one error
That is,
expect(res).toHaveAtLeastValidationErrors()
: succeeds if at least one validation error is foundexpect(res2).toHaveAtLeastValidationErrors({params: "resID"})
succeeds, if resID omitted an error. There may or may not be other fields causing errors!expect(res2).not.toHaveAtLeastValidationErrors({params: "resID"})
succeeds if resID did not omit an error, even if any other field omitted an error!
That also means that
expect(res).not.toHaveAtLeastValidationErrors()
: succeeds if at no validation error is found
toHaveNoValidationErrors
This works with express-validator.
It matches if no validation error is found, i.e. no property errors
is found in the body or the field is an empty array.
You can pass an optional parameter indicating the status code expectation.
toHaveAnyValidationErrors
This works with express-validator.
It matches if any validation error is found, i.e. property errors
is found in the body, it is an array, and it is not empty.
You can pass an optional parameter indicating the status code expectation.
Message Pre- and Postfix
In order to somehow use the created error message afterwards (e.g. in a report), you can define a pre- and postfix which will be added to the error message. For that, environment variables are used:
CUSTOM_MATCHER_MSG_PREFIX
CUSTOM_MATCHER_MSG_POSTFIX
Additional helpers
parseCookies
parses cookies in a response created by supertest and sets them as properties in the same response. That is, two new properties are added:cookies
: this property contains the values of cookies as properties, the name of the cookie is the name of the property (similar to the express middleware cookieParser)cookiesRaw
: the full cookie (as returned by set-cookies), i.e. including all properties (such ashttpOnly
,secure
, etc.)
supertestWithReqMiddleware
: Works similar as the supertest function, but injects calls to middleware functions for each request (or HTTP method respectively).
Status
This library is developed on demand. It is not a fully-features code testing library but only contains matchers as far as needed by the author.
Limitations
At the moment, the response must be a subtype of
type ResponseWithErrors = {
body: {
errors: {
location: "body" | "query" | "params" | "cookies" | "headers"
param?: string // must be set when using express-validator version <=6
path?: string // must be set when using express-validator version >=7
}[]
}
}
In particular the path body.errors
is hardcoded.
License
This program and the accompanying materials are made available under the terms of the Eclipse Public License v. 2.0 which is available at https://www.eclipse.org/legal/epl-2.0.