or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

assert-interface.mdconfiguration.mdcore-assertions.mdexpect-interface.mdindex.mdplugin-system.mdshould-interface.mdutilities.md
tile.json

should-interface.mddocs/

Should Interface

BDD-style assertions that extend Object.prototype with a should property for natural language assertions. The should interface enables expressive test syntax by adding assertion capabilities directly to JavaScript objects.

Capabilities

should Function

Activates the should interface by extending Object.prototype with should property getter/setter.

/**
 * Activates the should interface by extending Object.prototype
 * Must be called once before using should-style assertions
 * @returns void
 */
function should(): void;

Usage Examples:

import { should } from "chai";

// Activate should interface
should();

// Now all objects have .should property
(42).should.equal(42);
("hello").should.be.a("string");
([1, 2, 3]).should.have.lengthOf(3);
({ name: "Alice" }).should.have.property("name", "Alice");

Static should Methods

Static methods available on the should object for explicit failure and utility functions.

/**
 * Throws an assertion error with optional context
 * @param actual - The actual value (optional)
 * @param expected - The expected value (optional)
 * @param message - Custom error message (optional)
 * @param operator - Comparison operator (optional)
 * @throws AssertionError
 */
should.fail(actual?: any, expected?: any, message?: string, operator?: string): never;

/**
 * Non-strict equality assertion for should interface
 * @param actual - Actual value
 * @param expected - Expected value
 * @param message - Optional error message
 */
should.equal(actual: any, expected: any, message?: string): void;

/**
 * Tests that function throws an error
 * @param fn - Function to test
 * @param errorType - Expected error constructor
 * @param errorMessage - Expected error message (string or regex)
 * @param message - Optional assertion message
 */
should.Throw(fn: Function, errorType?: Function, errorMessage?: string | RegExp, message?: string): void;
should.throw(fn: Function, errorType?: Function, errorMessage?: string | RegExp, message?: string): void; // Alias

/**
 * Tests that value exists (not null or undefined)
 * @param value - Value to test
 * @param message - Optional error message
 */
should.exist(value: any, message?: string): void;

Static should.not Methods

Negated versions of static should methods.

/**
 * Non-strict inequality assertion for should interface
 * @param actual - Actual value
 * @param expected - Expected value
 * @param message - Optional error message
 */
should.not.equal(actual: any, expected: any, message?: string): void;

/**
 * Tests that function does not throw an error
 * @param fn - Function to test
 * @param errorType - Error constructor to reject
 * @param errorMessage - Error message to reject (string or regex)
 * @param message - Optional assertion message
 */
should.not.Throw(fn: Function, errorType?: Function, errorMessage?: string | RegExp, message?: string): void;
should.not.throw(fn: Function, errorType?: Function, errorMessage?: string | RegExp, message?: string): void; // Alias

/**
 * Tests that value does not exist (null or undefined)
 * @param value - Value to test
 * @param message - Optional error message
 */
should.not.exist(value: any, message?: string): void;

Object.prototype.should Property

When should() is called, all JavaScript objects gain a should property that returns an Assertion instance.

interface Object {
  should: Assertion;
}

Common Should Patterns

Basic Value Assertions

should(); // Activate should interface

// Equality
(42).should.equal(42);
("42").should.not.equal(42);
({ a: 1 }).should.eql({ a: 1 });
({ a: 1 }).should.deep.equal({ a: 1 });

// Type checking
("hello").should.be.a("string");
(42).should.be.a("number");
([]).should.be.an("array");
({}).should.be.an("object");

// Truthiness
(true).should.be.true;
(false).should.be.false;
(1).should.be.ok;
("").should.not.be.ok;

Comparison Assertions

// Numeric comparisons
(5).should.be.above(3);
(5).should.be.at.least(5);
(3).should.be.below(5);
(3).should.be.at.most(3);
(1.5).should.be.within(1, 2);
(1.5).should.be.closeTo(1.6, 0.2);

// String matching
("hello world").should.match(/world/);
("hello world").should.include("world");
("hello world").should.contain("world");

Object and Property Assertions

const obj = { name: "Alice", age: 25, active: true };

// Property existence and values
obj.should.have.property("name");
obj.should.have.property("age", 25);
obj.should.have.own.property("name");
obj.should.include({ name: "Alice" });
obj.should.deep.include({ name: "Alice", age: 25 });

// Keys
obj.should.have.keys("name", "age", "active");
obj.should.have.any.keys("name", "email");
obj.should.contain.keys("name", "age");

// Nested properties
const nested = { user: { profile: { name: "Bob" } } };
nested.should.have.nested.property("user.profile.name");
nested.should.have.nested.property("user.profile.name", "Bob");

Array and Collection Assertions

const array = [1, 2, 3, 4, 5];

// Length
array.should.have.lengthOf(5);
array.should.have.length.above(3);

// Members
array.should.include(3);
array.should.include.members([2, 4]);
array.should.have.members([1, 2, 3, 4, 5]);
array.should.have.ordered.members([1, 2, 3, 4, 5]);

// Deep member checking
[{a: 1}, {b: 2}].should.deep.include({a: 1});
[{a: 1}, {b: 2}].should.have.deep.members([{a: 1}, {b: 2}]);

// Empty collections
[].should.be.empty;
"".should.be.empty;
({}).should.be.empty;

Function Assertions

function throwsError() {
  throw new Error("Something went wrong");
}

function returnsValue() {
  return 42;
}

// Exception testing with should syntax
throwsError.should.throw();
throwsError.should.throw(Error);
throwsError.should.throw("Something went wrong");
throwsError.should.throw(Error, /went wrong/);

// Static should methods for functions
should.Throw(throwsError);
should.Throw(throwsError, Error);
should.not.Throw(returnsValue);

// Function properties
returnsValue.should.be.a("function");
returnsValue.should.have.property("name", "returnsValue");

Advanced Chaining

// Complex chaining with natural language
(42).should.be.a("number").and.be.above(40).and.be.below(50);

// Object validation chains
const user = { name: "Alice", age: 25, email: "alice@example.com" };
user.should.be.an("object")
    .that.has.property("name")
    .that.is.a("string")
    .and.has.length.above(0);

user.should.have.property("email")
    .that.matches(/@/);

// Negation chains
("hello").should.not.equal("world");
([1, 2, 3]).should.not.include(4);
user.should.not.have.property("password");

Static Method Usage

// Explicit failures
should.fail("Something went wrong");
should.fail(actual, expected, "Values don't match");

// Existence testing
should.exist(someValue);
should.not.exist(null);
should.not.exist(undefined);

// Equality testing
should.equal(actual, expected);
should.not.equal(actual, different);

// Exception testing
should.Throw(() => { throw new Error(); });
should.not.Throw(() => { return 42; });

Browser Compatibility

The should interface modifies Object.prototype, which may conflict with some libraries or environments:

// Safe activation check
if (typeof should === 'function') {
  should();
}

// Alternative: use expect or assert interfaces
// These don't modify global prototypes
import { expect, assert } from "chai";

Error Handling

Should assertions provide the same detailed error messages as other Chai interfaces:

// This will throw: AssertionError: expected 5 to equal 10  
(5).should.equal(10);

// Custom error messages
(5).should.equal(10, "Custom failure message");

// Object diff display
({ a: 1, b: 2 }).should.deep.equal({ a: 1, b: 3 });
// Shows property-by-property diff