npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

restmatcher

v1.1.16

Published

Matchers for Jest checking Responses returned via SuperTest

Downloads

273

Readme

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.