Profiles·Public

chai

semver>=4.0.0 <7.0.0postconditions4functions4last verified2026-06-24coverage score67%

Postconditions: what we check

  • expect · expect-assertion-failure
    warning
    Whenassertion fails (e.g., expect(value).to.equal(expected) when value !== expected)
    ThrowsAssertionError
    Required handlingAssertions are EXPECTED to throw in test code, but if used outside tests (e.g., in production validation), callers MUST wrap in try-catch. Without error handling, failed assertions crash the application. Use pattern: try { expect(value).to.equal(expected); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • assert · assert-assertion-failure
    warning
    Whenassertion fails (e.g., assert.equal(actual, expected) when actual !== expected)
    ThrowsAssertionError
    Required handlingAssert-style assertions throw AssertionError on failure. In test code, this is expected. If used in production code, MUST wrap in try-catch to prevent crashes.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[2]
  • should · should-assertion-failure
    warning
    Whenassertion fails (e.g., value.should.equal(expected) when value !== expected)
    ThrowsAssertionError
    Required handlingShould-style assertions throw AssertionError on failure. Primarily for test code. If used outside tests, MUST wrap in try-catch.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • assert.ifError · assert-iferror-rethrows-value
    warning
    Whenval is truthy (non-null, non-undefined, non-zero, non-false, non-empty-string). Common usage: assert.ifError(err) in callback-style code where err is an Error. Throws val directly — NOT wrapped in AssertionError.
    Throwsval (the original value passed — typically an Error, but any truthy value)
    Required handlingWhen assert.ifError(err) is used in production code (not test code), the caller must catch the rethrown error with the correct type. A catch block that expects AssertionError will NOT catch errors from assert.ifError — it rethrows the original value as-is. Correct pattern for production use: try { assert.ifError(err); // rethrows err if err is truthy } catch (e) { // e is err itself, not an AssertionError console.error('Callback error:', e.message); throw e; } Note: In test code, assert.ifError is typically called at the top of a callback to fail the test immediately if err is present. The rethrow causes test frameworks to mark the test as failed.
    costmediumin prodsilent failureusers seeservice unavailablevisibilitysilent
    Sources[3][2]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
  • [1]
    chaijs.com/api/bdd
    Bdd
  • [2]
    chaijs.com/api/assert
    Assert
  • [3]
    chaijs.com/api/assert
    Assert

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources: chai

Last Updated: 2026-02-27 Package Version: >=4.0.0 <6.0.0 Research Quality: ⭐⭐⭐⭐ (comprehensive)


Official Documentation


Assertion Styles

Chai provides THREE assertion styles:

1. BDD Style (expect)

const { expect } = require('chai');

expect(foo).to.equal('bar');
expect(foo).to.be.a('string');
expect(foo).to.have.lengthOf(3);

Most popular style - chainable, readable

2. TDD Style (assert)

const { assert } = require('chai');

assert.equal(foo, 'bar');
assert.typeOf(foo, 'string');
assert.lengthOf(foo, 3);

Classic assert style - familiar to C/Java developers

3. Should Style

const chai = require('chai');
chai.should();

foo.should.equal('bar');
foo.should.be.a('string');
foo.should.have.lengthOf(3);

Least common - modifies Object.prototype


Error Handling

AssertionError

All failed assertions throw AssertionError:

const { expect } = require('chai');

try {
  expect(1).to.equal(2);
} catch (error) {
  console.log(error.name); // 'AssertionError'
  console.log(error.message); // 'expected 1 to equal 2'
}

In Test Frameworks

Mocha/Jest handle AssertionError automatically:

it('test', () => {
  expect(value).to.equal(expected); // No try-catch needed
});

Outside Tests (Rare)

Production validation requires try-catch:

function validateInput(data) {
  try {
    expect(data).to.be.an('object');
    expect(data.id).to.be.a('number');
    return true;
  } catch (error) {
    return false; // or log error
  }
}

WARNING: Don't use chai for production validation - use validator libraries instead.


Common Patterns

1. Deep Equality

expect(obj1).to.deep.equal(obj2);
expect(array).to.have.deep.members([1, 2, 3]);

2. Property Assertions

expect(obj).to.have.property('name');
expect(obj).to.have.property('age', 25);
expect(obj).to.have.all.keys('name', 'age');

3. Type Assertions

expect(value).to.be.a('string');
expect(value).to.be.an('array');
expect(value).to.be.null;
expect(value).to.be.undefined;

4. Existence Assertions

expect(value).to.exist;
expect(value).to.not.exist;
expect(value).to.be.ok; // truthy
expect(value).to.be.empty; // array/string/object

5. Comparison Assertions

expect(value).to.be.above(5);
expect(value).to.be.below(10);
expect(value).to.be.within(5, 10);

6. String/Array Contains

expect('hello world').to.include('world');
expect([1, 2, 3]).to.include(2);
expect({ a: 1, b: 2 }).to.include({ a: 1 });

Common Mistakes

Mistake #1: Using Chai in Production Code

Problem: Chai is designed for testing, not production validation

Example (WRONG):

// ❌ In production API
app.post('/api/users', (req, res) => {
  expect(req.body).to.have.property('email');
  expect(req.body.email).to.be.a('string');
  // Throws AssertionError → crashes server!
});

Fix: Use validation libraries (joi, yup, zod):

// ✅ Production validation
const schema = Joi.object({
  email: Joi.string().required()
});
const { error } = schema.validate(req.body);
if (error) return res.status(400).json({ error });

Mistake #2: Forgetting .to / .be

Example (WRONG):

expect(value).equal(5); // ❌ Missing .to
expect(value).a('string'); // ❌ Missing .be

Fix:

expect(value).to.equal(5); // ✅
expect(value).to.be.a('string'); // ✅

Mistake #3: Confusing .equal vs .eql

.equal - strict equality (===):

expect(obj1).to.equal(obj2); // ❌ Different references

.eql / .deep.equal - deep equality:

expect(obj1).to.deep.equal(obj2); // ✅ Compare contents

Best Practices

1. Prefer BDD Style (expect)

Most readable and chainable:

expect(user).to.have.property('name').that.is.a('string');

2. Use Descriptive Messages

expect(value, 'User age should be positive').to.be.above(0);

3. Chain Assertions

expect(user)
  .to.be.an('object')
  .that.has.property('email')
  .that.is.a('string');

4. Only Use in Tests

Never use chai assertions in production code - use proper validation libraries.


Integration with Test Frameworks

Mocha

const { expect } = require('chai');

describe('Math', () => {
  it('should add numbers', () => {
    expect(1 + 1).to.equal(2);
  });
});

Jest

// Jest has built-in assertions, but chai can be used:
const { expect } = require('chai');

test('adds numbers', () => {
  expect(1 + 1).to.equal(2);
});

Contract Rationale

Postconditions (assertion-failure)

All chai assertions throw AssertionError when they fail. This is expected behavior in tests but can crash applications if used outside test contexts.

Evidence:

  • Chai documentation explicitly states assertions throw on failure
  • AssertionError is the standard exception type for all assertion libraries
  • Using chai in production is an anti-pattern

Severity: Warning (expected in tests, problematic in production)

Citations:


Important Notes

  • Testing Library: Chai is for tests only, not production validation
  • Security: No CVEs - development tool
  • AssertionError: All assertions throw on failure
  • Alternatives for Production: joi, yup, zod, ajv

Research Metadata

  • Research Date: 2026-02-27
  • Researcher: Claude Sonnet 4.5
  • Documentation Sources: 6 URLs
  • Common Mistakes Documented: 3
  • Line Count: 200+ lines (target 100+ ✅)
Need a different package?
Request a profile