Chai HTTP
Chai HTTP is an assertion plugin for the Chai Assertion Library, designed specifically for conducting HTTP integration tests. It enables developers to test HTTP APIs by composing requests and asserting on their responses, supporting both web applications (like Express or Connect apps) and external URLs. The library uses Superagent under the hood for making HTTP requests. The current stable version is 5.1.2, which maintains an active release cadence with multiple updates in the past year, indicating sustainable maintenance and a popular standing within the Node.js ecosystem. Key differentiators include its fluent, chainable API for request creation, automatic server management for local applications (starting and stopping it), and comprehensive assertions for common HTTP tasks like status codes, headers, and body content. It ships with TypeScript types, enhancing developer experience in TypeScript projects.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/chai/chai.js from ... not supported.
cause Attempting to use CommonJS `require()` syntax with Chai or Chai HTTP v5+ in a Node.js environment.fixConvert your test files to use ES Module `import` syntax (e.g., `import * as chai from 'chai';`). Ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json`). -
SyntaxError: The requested module 'chai' does not provide an export named 'request'
cause Incorrectly attempting to import `request` from the `chai` package instead of `chai-http`.fixImport `request` directly from `chai-http`: `import { request } from 'chai-http';`. -
TypeError: chaiHttp is not a function
cause Attempting to use `chaiHttp` as a function directly or incorrectly destructuring the import, typically when trying to install the plugin.fixEnsure you are using the default import for `chaiHttp` and passing it to `chai.use()`: `import chaiHttp from 'chai-http'; chai.use(chaiHttp);` -
AssertionError: expected ... to have status ... but got ...
cause The HTTP response status code did not match the expected value in your assertion, or the server failed to send a response within the test timeout.fixVerify that your application/API is sending the correct status code. For asynchronous tests, ensure `done()` is called for Mocha, or return the promise if using promise-based tests. Increase test timeout if necessary.
Warnings
- breaking Chai HTTP v5.0.0 (and its underlying Chai v5.x) dropped support for CommonJS modules, requiring all consumers to use EcmaScript Modules (ESM). Using `require('chai-http')` or `require('chai')` will cause an `ERR_REQUIRE_ESM` error.
- breaking Chai HTTP v5.0.0 raised the minimum supported Node.js version to `>=v16.20`. Older Node.js versions are no longer supported.
- breaking Chai HTTP v5.0.0 updated its internal `superagent` dependency to version `^9`. This might introduce subtle behavioral changes if your project relied on specific `superagent` behaviors from older versions.
- gotcha When testing a local application (e.g., an Express app) by passing it to `request.execute(app)`, Chai HTTP will automatically open and then close the server after the request. If you intend to make multiple requests and keep the server open between them, you must explicitly call `.keepOpen()` on the request object and then manually `.close()` it.
- gotcha For browser-based testing, the README explicitly states to use `chai-http` v4.x. Version 5.x and above are primarily focused on Node.js environments for HTTP integration testing.
Install
-
npm install chai-http -
yarn add chai-http -
pnpm add chai-http
Imports
- chaiHttp
import { chaiHttp } from 'chai-http';import chaiHttp from 'chai-http';
- request
import { request } from 'chai';import { request } from 'chai-http'; - chai
const chai = require('chai');import * as chai from 'chai';
Quickstart
import * as chai from 'chai';
import chaiHttp from 'chai-http';
import { request } from 'chai-http';
import express from 'express';
chai.use(chaiHttp);
const expect = chai.expect;
const app = express();
app.get('/', (req, res) => {
res.status(200).send('Hello Chai HTTP!');
});
app.post('/data', (req, res) => {
res.status(201).json({ received: req.body });
});
describe('Chai HTTP Basic Test', () => {
it('should get a 200 response from the root path', (done) => {
request.execute(app)
.get('/')
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(200);
expect(res.text).to.equal('Hello Chai HTTP!');
done();
});
});
it('should post data and get a 201 response', (done) => {
request.execute(app)
.post('/data')
.send({ key: 'value' })
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(201);
expect(res.body).to.deep.equal({ received: {} }); // Express needs body-parser for req.body
done();
});
});
});