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

chai-openapi-response-validator

v0.14.2

Published

Use Chai to assert that HTTP responses satisfy an OpenAPI spec

Downloads

36,311

Readme

Chai OpenAPI Response Validator

downloads npm build status style codecov included contributions welcome

Use Chai to assert that HTTP responses satisfy an OpenAPI spec.

Problem 😕

If your server's behaviour doesn't match your API documentation, then you need to correct your server, your documentation, or both. The sooner you know the better.

Solution 😄

This plugin lets you automatically test whether your server's behaviour and documentation match. It extends the Chai Assertion Library to support the OpenAPI standard for documenting REST APIs. In your JavaScript tests, you can simply assert expect(responseObject).to.satisfyApiSpec

Features:

  • Validates the status and body of HTTP responses against your OpenAPI spec (see example)
  • Validates objects against schemas defined in your OpenAPI spec (see example)
  • Load your OpenAPI spec just once in your tests (load from a filepath or object)
  • Supports OpenAPI 2 and 3
  • Supports OpenAPI specs in YAML and JSON formats
  • Supports $ref in response definitions (i.e. $ref: '#/definitions/ComponentType/ComponentName')
  • Informs you if your OpenAPI spec is invalid
  • Supports responses from axios, request-promise, supertest, superagent, and chai-http
  • Use in Mocha and other test runners

Contributing ✨

If you've come here to help contribute - thanks! Take a look at the contributing docs to get started.

Installation

npm

npm install --save-dev chai-openapi-response-validator

yarn

yarn add --dev chai-openapi-response-validator

Importing

ES6 / TypeScript

import chaiResponseValidator from 'chai-openapi-response-validator';

CommonJS / JavaScript

const chaiResponseValidator = require('chai-openapi-response-validator').default;

Usage

In API tests, validate the status and body of HTTP responses against your OpenAPI spec:

1. Write a test:

// Set up Chai
import chai from 'chai';
const expect = chai.expect;

// Import this plugin
import chaiResponseValidator from 'chai-openapi-response-validator';

// Load an OpenAPI file (YAML or JSON) into this plugin
chai.use(chaiResponseValidator('path/to/openapi.yml'));

// Write your test (e.g. using Mocha)
describe('GET /example/endpoint', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server (e.g. using axios)
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).to.equal(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).to.satisfyApiSpec;
  });
});

2. Write an OpenAPI Spec (and save to path/to/openapi.yml):

openapi: 3.0.0
info:
  title: Example API
  version: 1.0.0
paths:
  /example:
    get:
      responses:
        200:
          description: Response body should be an object with fields 'stringProperty' and 'integerProperty'
          content:
            application/json:
              schema:
                type: object
                required:
                  - stringProperty
                  - integerProperty
                properties:
                  stringProperty:
                    type: string
                  integerProperty:
                    type: integer

3. Run your test to validate your server's response against your OpenAPI spec:

The assertion passes if the response status and body satisfy openapi.yml:
// Response includes:
{
  status: 200,
  body: {
    stringProperty: 'string',
    integerProperty: 123,
  },
};
The assertion fails if the response body is invalid:
// Response includes:
{
  status: 200,
  body: {
    stringProperty: 'string',
    integerProperty: 'invalid (should be an integer)',
  },
};
Output from test failure:
AssertionError: expected res to satisfy API spec

expected res to satisfy the '200' response defined for endpoint 'GET /example/endpoint' in your API spec
res did not satisfy it because: integerProperty should be integer

res contained: {
  body: {
      stringProperty: 'string',
      integerProperty: 'invalid (should be an integer)'
    }
  }
}

The '200' response defined for endpoint 'GET /example/endpoint' in API spec: {
  '200': {
    description: 'Response body should be a string',
    content: {
      'application/json': {
        schema: {
          type: 'string'
        }
      }
    }
  },
}

In unit tests, validate objects against schemas defined in your OpenAPI spec:

1. Write a test:

// Set up Chai
import chai from 'chai';
const expect = chai.expect;

// Import this plugin and the function you want to test
import chaiResponseValidator from 'chai-openapi-response-validator';
import { functionToTest } from 'path/to/your/code';

// Load an OpenAPI file (YAML or JSON) into this plugin
chai.use(chaiResponseValidator('path/to/openapi.yml'));

// Write your test (e.g. using Mocha)
describe('functionToTest()', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Assert that the function returns a value satisfying a schema defined in your OpenAPI spec
    expect(functionToTest()).to.satisfySchemaInApiSpec('ExampleSchemaObject');
  });
});

2. Write an OpenAPI Spec (and save to path/to/openapi.yml):

openapi: 3.0.0
info:
  title: Example API
  version: 1.0.0
paths:
  /example:
    get:
      responses:
        200:
          description: Response body should be an ExampleSchemaObject
          content:
            application/json:
              schema: '#/components/schemas/ExampleSchemaObject'
components:
  schemas:
    ExampleSchemaObject:
      type: object
      required:
        - stringProperty
        - integerProperty
      properties:
        stringProperty:
          type: string
        integerProperty:
          type: integer

3. Run your test to validate your object against your OpenAPI spec:

The assertion passes if the object satisfies the schema ExampleSchemaObject:
// object includes:
{
  stringProperty: 'string',
  integerProperty: 123,
};
The assertion fails if the object does not satisfy the schema ExampleSchemaObject:
// object includes:
{
  stringProperty: 123,
  integerProperty: 123,
};
Output from test failure:
AssertionError: expected object to satisfy schema 'ExampleSchemaObject' defined in API spec:
object did not satisfy it because: stringProperty should be string

object was: {
    {
      stringProperty: 123,
      integerProperty: 123
    }
  }
}

The 'ExampleSchemaObject' schema in API spec: {
  type: 'object',
  required: [
    'stringProperty'
    'integerProperty'
  ],
  properties: {
    stringProperty: {
      type: 'string'
    },
    integerProperty: {
      type: 'integer'
    }
  }
}

Loading your OpenAPI spec (3 different ways):

1. From an absolute filepath (see above)

2. From an object:

// Set up Chai
import chai from 'chai';
const expect = chai.expect;

// Import this plugin
import chaiResponseValidator from 'chai-openapi-response-validator';

// Get an object representing your OpenAPI spec
const openApiSpec = {
  openapi: '3.0.0',
  info: {
    title: 'Example API',
    version: '0.1.0',
  },
  paths: {
    '/example/endpoint': {
      get: {
        responses: {
          200: {
            description: 'Response body should be a string',
            content: {
              'application/json': {
                schema: {
                  type: 'string',
                },
              },
            },
          },
        },
      },
    },
  },
};

// Load that OpenAPI object into this plugin
chai.use(chaiResponseValidator(openApiSpec));

// Write your test (e.g. using Mocha)
describe('GET /example/endpoint', () => {
  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server (e.g. using axios)
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).to.equal(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).to.satisfyApiSpec;
  });
});

3. From a web endpoint:

// Set up Chai
import chai from 'chai';
const expect = chai.expect;

// Import this plugin and an HTTP client (e.g. axios)
import chaiResponseValidator from 'chai-openapi-response-validator';
import axios from 'axios';

// Write your test (e.g. using Mocha)
describe('GET /example/endpoint', () => {
  // Load your OpenAPI spec from a web endpoint
  before(async () => {
    const response = await axios.get('url/to/openapi/spec');
    const openApiSpec = response.data; // e.g. { openapi: '3.0.0', <etc> };
    chai.use(chaiResponseValidator(openApiSpec));
  });

  it('should satisfy OpenAPI spec', async () => {
    // Get an HTTP response from your server (e.g. using axios)
    const res = await axios.get('http://localhost:3000/example/endpoint');

    expect(res.status).to.equal(200);

    // Assert that the HTTP response satisfies the OpenAPI spec
    expect(res).to.satisfyApiSpec;
  });
});