Extends Chai with assertions about promises.
npx @tessl/cli install tessl/npm-chai-as-promised@8.0.0Chai as Promised extends Chai with fluent language for asserting facts about promises. It provides an eventually property that transforms any existing Chai assertion into one that works with promises, along with promise-specific assertions like fulfilled, rejected, rejectedWith, and become.
npm install chai-as-promisedimport * as chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
// Then either:
const expect = chai.expect;
// or:
const assert = chai.assert;
// or:
chai.should();For CommonJS (not recommended but supported):
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);import * as chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
chai.should();
// Transform existing assertions to work with promises
return Promise.resolve(42).should.eventually.equal(42);
// Promise-specific assertions
return promise.should.be.fulfilled;
return promise.should.be.rejected;
return promise.should.be.rejectedWith(TypeError);
return promise.should.become("expected value");
// For test frameworks that don't support returning promises
promise.should.be.fulfilled.notify(done);Transforms any existing Chai assertion into one that works with promises.
// Available on all assertions
.eventually
// Usage examples:
promise.should.eventually.equal(expected)
promise.should.eventually.have.property('key')
expect(promise).to.eventually.be.trueAssertions specifically for testing promise fulfillment and rejection states.
// Fulfilled assertion
.fulfilled
// Rejected assertion
.rejected
// Usage examples:
promise.should.be.fulfilled
promise.should.be.rejected
expect(promise).to.be.fulfilled
expect(promise).to.be.rejectedTest promises that reject with specific error types or messages.
.rejectedWith(errorLike?, errMsgMatcher?, message?)
// Parameters:
// - errorLike: Error constructor, Error instance, or null
// - errMsgMatcher: String or RegExp to match error message
// - message: Custom assertion messageUsage Examples:
// Test for specific error type
promise.should.be.rejectedWith(TypeError);
// Test for error message substring
promise.should.be.rejectedWith("error message");
// Test for error message pattern
promise.should.be.rejectedWith(/error pattern/);
// Test for specific error type and message
promise.should.be.rejectedWith(TypeError, "type error message");
// Test with custom assertion message
promise.should.be.rejectedWith(Error, "Expected a generic error");Shorthand for .eventually.deep.equal(value).
.become(value, message?)
// Parameters:
// - value: Expected fulfillment value
// - message: Custom assertion messageUsage Examples:
promise.should.become({foo: "bar"});
promise.should.become("expected string", "Custom message");For test frameworks that don't support returning promises to signal completion.
.notify(done)
// Parameters:
// - done: Callback function from test frameworkUsage Examples:
it("should be fulfilled", function (done) {
promise.should.be.fulfilled.notify(done);
});
it("should be rejected", function (done) {
promise.should.be.rejected.notify(done);
});
// Chain other assertions after promise resolves
it("should change state", function (done) {
otherState.should.equal("before");
promise.should.be.fulfilled.then(function () {
otherState.should.equal("after");
}).should.notify(done);
});Promise-specific methods added to chai.assert.
assert.isFulfilled(promise, message?)
assert.isRejected(promise, errorLike?, errMsgMatcher?, message?)
assert.becomes(promise, value, message?)
assert.doesNotBecome(promise, value, message?)Usage Examples:
// Test promise fulfillment
assert.isFulfilled(promise);
assert.isFulfilled(promise, "Expected promise to be fulfilled");
// Test promise rejection
assert.isRejected(promise);
assert.isRejected(promise, TypeError);
assert.isRejected(promise, /error pattern/);
assert.isRejected(promise, TypeError, /specific error/);
// Test promise fulfillment value
assert.becomes(promise, expectedValue);
assert.doesNotBecome(promise, unwantedValue);All standard assert methods are available through assert.eventually to work with promises.
assert.eventually.{assertMethod}(promise, ...args)
// Available methods include:
assert.eventually.equal(promise, expected)
assert.eventually.deepEqual(promise, expected)
assert.eventually.isTrue(promise)
assert.eventually.isNull(promise)
assert.eventually.property(promise, propertyName)
assert.eventually.typeOf(promise, expectedType)
assert.eventually.include(promise, searchValue)
// ... and all other standard chai assert methodsUsage Examples:
assert.eventually.equal(Promise.resolve(42), 42);
assert.eventually.property(Promise.resolve({foo: "bar"}), "foo");
assert.eventually.include(Promise.resolve("hello world"), "hello");
// With notify for test frameworks
assert.eventually.isTrue(Promise.resolve(true)).notify(done);Handle multiple promise assertions using Promise.all.
// Test multiple promises together
return Promise.all([
promiseA.should.become("happy"),
promiseB.should.eventually.have.property("fun times"),
promiseC.should.be.rejectedWith(TypeError, "only joyful types are allowed")
]);Advanced customization hooks for specialized use cases.
import { setTransferPromiseness } from 'chai-as-promised';
setTransferPromiseness(function (assertion, promise) {
assertion.then = promise.then.bind(promise);
// Add additional promise methods to assertion
assertion.finally = promise.finally.bind(promise);
assertion.done = promise.done.bind(promise);
});import { setTransformAsserterArgs } from 'chai-as-promised';
setTransformAsserterArgs(function (args) {
// Transform arguments synchronously
return args.map(function (x) { return x + 1; });
});
// Or transform asynchronously
setTransformAsserterArgs(function (args) {
// Return promise for transformed arguments
return Promise.all(args); // Convert array of promises to promise for array
});Low-level utility functions exported for advanced use cases.
import { transferPromiseness, transformAsserterArgs } from 'chai-as-promised';
/**
* Transfers promise methods to an assertion object using the configured hook
* @param assertion - The Chai assertion object
* @param promise - The promise to transfer methods from
*/
function transferPromiseness(assertion: Assertion, promise: Promise<any>): void;
/**
* Transforms asserter arguments using the configured hook
* @param values - Array of argument values to transform
* @returns Transformed arguments or promise for transformed arguments
*/
function transformAsserterArgs(values: any[]): any[] | Promise<any[]>;// Main plugin function type
type ChaiAsPromisedPlugin = (chai: ChaiStatic, utils: ChaiUtils) => void;
// Configuration function types
type TransferPromisenessFn = (assertion: Assertion, promise: Promise<any>) => void;
type TransformAsserterArgsFn = (args: any[]) => any[] | Promise<any[]>;
// Assertion extensions (added to Chai's Assertion prototype)
interface Assertion {
eventually: Assertion;
fulfilled: Assertion;
rejected: Assertion;
rejectedWith(errorLike?: any, errMsgMatcher?: string | RegExp, message?: string): Assertion;
become(value: any, message?: string): Assertion;
notify(done: () => void): Assertion;
}
// Assert interface extensions
interface Assert {
isFulfilled(promise: Promise<any>, message?: string): Promise<any>;
isRejected(promise: Promise<any>, errorLike?: any, errMsgMatcher?: string | RegExp, message?: string): Promise<any>;
becomes(promise: Promise<any>, value: any, message?: string): Promise<any>;
doesNotBecome(promise: Promise<any>, value: any, message?: string): Promise<any>;
eventually: EventuallyAsserter;
}
interface EventuallyAsserter {
[key: string]: (promise: Promise<any>, ...args: any[]) => Promise<any>;
}Chai as Promised provides detailed error messages for common failure scenarios:
"expected promise to be rejected but it was fulfilled with [value]""expected promise to be fulfilled but it was rejected with [error]""expected promise to be rejected with 'TypeError' but it was rejected with 'Error'""Chai as Promised is incompatible with thenables of jQuery<3.0.0""[object] is not a thenable"