1.1.16 • Published 3 days ago

restmatcher v1.1.16

Weekly downloads
-
License
EPL-2.0
Repository
gitlab
Last release
3 days ago

npm pipeline status coverage

logo 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 found
  • expect(res).not.toHaveValidationErrorsExactly(): succeeds if no validations errors were omitted
  • expect(res).toHaveValidationErrorsExactly({status: 400}): succeeds if no validation error is found and status code is 400
  • expect(res).toHaveValidationErrorsExactly({status: "4xx"}): succeeds if no validation error is found and status code is a client error
  • expect(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 found
  • expect(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 as httpOnly, 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.

1.1.16

3 days ago

1.1.15

3 days ago

1.1.12

6 months ago

1.1.11

6 months ago

1.1.10

6 months ago

1.1.14

6 months ago

1.1.13

6 months ago

1.1.9

1 year ago

1.1.8

1 year ago

1.1.7

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.4

1 year ago

1.1.3

1 year ago

1.1.2

1 year ago

1.1.0

2 years ago

1.0.0

2 years ago