Files
2025-11-29 18:01:33 +08:00

1409 lines
31 KiB
Markdown

# Bupkis API Reference
Complete reference for all built-in Bupkis assertions. This document is organized by assertion category.
## Table of Contents
- [Core Concepts](#core-concepts)
- [Primitive Assertions](#primitive-assertions)
- [Numeric Assertions](#numeric-assertions)
- [String & Pattern Assertions](#string--pattern-assertions)
- [Collection Assertions](#collection-assertions)
- [Object Assertions](#object-assertions)
- [Function Assertions](#function-assertions)
- [Equality & Comparison Assertions](#equality--comparison-assertions)
- [Error Assertions](#error-assertions)
- [Date & Time Assertions](#date--time-assertions)
- [Promise Assertions](#promise-assertions)
- [Other Assertions](#other-assertions)
---
## Core Concepts
### Natural Language Assertions
Bupkis uses natural language phrases instead of method chaining:
```typescript
// Instead of:
expect(actual).toEqual(expected);
// Write:
expect(actual, 'to equal', expected);
expect(actual, 'is', expected);
expect(actual, 'to be', expected);
```
### Anatomy of an Assertion
```typescript
expect(subject, 'phrase', [parameter?, phrase?, parameter?, ...]);
```
- **Subject**: The value being tested (first parameter)
- **Phrase**: String describing the assertion (e.g., 'to be', 'to equal')
- **Parameter**: Optional values for comparison or validation
### Negation
ANY assertion can be negated by prepending `not` to the first phrase:
```typescript
expect(42, 'to be', 42); // passes
expect(42, 'not to be', '42'); // passes
expect('hello', 'not to be a number'); // passes
```
### Concatenation with 'and'
Chain multiple assertions on the same subject:
```typescript
expect(
user,
'to be an object',
'and',
'to have property',
'name',
'and',
'to satisfy',
{ age: expect.it('to be greater than', 18) },
);
```
### Embeddable Assertions with expect.it()
Use `expect.it()` to embed assertions within "to satisfy" patterns:
```typescript
expect(user, 'to satisfy', {
name: expect.it('to be a string'),
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, // RegExp works too
age: expect.it('to be greater than', 18),
roles: [expect.it('to be a string')], // Each element must be a string
});
```
---
## Primitive Assertions
### `{unknown} to be a string`
**Aliases:** None
**Checks:** Value is a string primitive or String object
```typescript
expect('hello', 'to be a string'); // ✓
expect(42, 'to be a string'); // ✗
expect(42, 'not to be a string'); // ✓
```
### `{unknown} to be a boolean`
**Aliases:** `to be a bool`, `to be boolean`
**Checks:** Value is a boolean primitive or Boolean object
```typescript
expect(true, 'to be a boolean'); // ✓
expect(0, 'to be a boolean'); // ✗
expect(0, 'not to be a boolean'); // ✓
```
### `{unknown} to be a number`
**Aliases:** `to be finite`
**Checks:** Value is a finite number (NaN and Infinity excluded)
```typescript
expect(42, 'to be a number'); // ✓
expect(NaN, 'to be a number'); // ✗ (NaN not considered a number)
expect(Infinity, 'to be a number'); // ✗ (Infinity not considered a number)
```
### `{unknown} to be a bigint`
**Aliases:** None
**Checks:** Value is a BigInt
```typescript
expect(9007199254741991n, 'to be a bigint'); // ✓
expect(42, 'to be a bigint'); // ✗
```
### `{unknown} to be a symbol`
**Aliases:** None
**Checks:** Value is a Symbol
```typescript
expect(Symbol('foo'), 'to be a symbol'); // ✓
expect('foo', 'to be a symbol'); // ✗
```
### `{unknown} to be null`
**Aliases:** None
**Checks:** Value is exactly null
```typescript
expect(null, 'to be null'); // ✓
expect(undefined, 'to be null'); // ✗
```
### `{unknown} to be undefined`
**Aliases:** None
**Checks:** Value is exactly undefined
```typescript
expect(undefined, 'to be undefined'); // ✓
expect(null, 'to be undefined'); // ✗
```
### `{unknown} to be a primitive`
**Aliases:** None
**Checks:** Value is a primitive (string, number, boolean, null, undefined, symbol, bigint)
```typescript
expect('hello', 'to be a primitive'); // ✓
expect(42, 'to be a primitive'); // ✓
expect({}, 'to be a primitive'); // ✗
```
---
## Numeric Assertions
### `{unknown} to be infinite`
**Aliases:** None
**Checks:** Value is Infinity or -Infinity
```typescript
expect(Infinity, 'to be infinite'); // ✓
expect(-Infinity, 'to be infinite'); // ✓
expect(42, 'to be infinite'); // ✗
```
### `{unknown} to be Infinity`
**Aliases:** None
**Checks:** Value is exactly positive Infinity
```typescript
expect(Infinity, 'to be Infinity'); // ✓
expect(-Infinity, 'to be Infinity'); // ✗
```
### `{unknown} to be -Infinity`
**Aliases:** None
**Checks:** Value is exactly negative Infinity
```typescript
expect(-Infinity, 'to be -Infinity'); // ✓
expect(Infinity, 'to be -Infinity'); // ✗
```
### `{unknown} to be positive`
**Aliases:** `to be a positive number`
**Checks:** Value is a positive finite number (excludes 0)
```typescript
expect(42, 'to be positive'); // ✓
expect(0, 'to be positive'); // ✗ (zero is not positive)
expect(-5, 'to be positive'); // ✗
```
### `{unknown} to be a positive integer`
**Aliases:** `to be a positive int`
**Checks:** Value is a positive integer (excludes 0)
```typescript
expect(42, 'to be a positive integer'); // ✓
expect(3.14, 'to be a positive integer'); // ✗ (not an integer)
expect(0, 'to be a positive integer'); // ✗ (zero excluded)
```
### `{unknown} to be negative`
**Aliases:** `to be a negative number`
**Checks:** Value is a negative finite number (excludes 0)
```typescript
expect(-42, 'to be negative'); // ✓
expect(0, 'to be negative'); // ✗
expect(5, 'to be negative'); // ✗
```
### `{unknown} to be a negative integer`
**Aliases:** `to be a negative int`
**Checks:** Value is a negative integer (excludes 0)
```typescript
expect(-42, 'to be a negative integer'); // ✓
expect(-3.14, 'to be a negative integer'); // ✗ (not an integer)
```
### `{unknown} to be NaN`
**Aliases:** None
**Checks:** Value is NaN
```typescript
expect(NaN, 'to be NaN'); // ✓
expect(42, 'to be NaN'); // ✗
```
### `{unknown} to be an integer`
**Aliases:** `to be a safe integer`, `to be an int`, `to be a safe int`
**Checks:** Value is a safe integer
```typescript
expect(42, 'to be an integer'); // ✓
expect(3.14, 'to be an integer'); // ✗
```
### `{unknown} to be greater than {number}`
**Aliases:** None
**Checks:** Value is strictly greater than the parameter
```typescript
expect(10, 'to be greater than', 5); // ✓
expect(5, 'to be greater than', 10); // ✗
```
### `{unknown} to be less than {number}`
**Aliases:** `to be lt`
**Checks:** Value is strictly less than the parameter
```typescript
expect(5, 'to be less than', 10); // ✓
expect(10, 'to be less than', 5); // ✗
```
### `{unknown} to be greater than or equal to {number}`
**Aliases:** `to be at least`, `to be gte`
**Checks:** Value is greater than or equal to the parameter
```typescript
expect(10, 'to be at least', 10); // ✓
expect(15, 'to be at least', 10); // ✓
expect(5, 'to be at least', 10); // ✗
```
### `{unknown} to be less than or equal to {number}`
**Aliases:** `to be at most`, `to be lte`
**Checks:** Value is less than or equal to the parameter
```typescript
expect(10, 'to be at most', 10); // ✓
expect(5, 'to be at most', 10); // ✓
expect(15, 'to be at most', 10); // ✗
```
### `{number} to be between {number} and {number}`
**Aliases:** `to be within`
**Checks:** Value is between two numbers (inclusive)
```typescript
expect(5, 'to be between', 1, 10); // ✓
expect(15, 'to be between', 1, 10); // ✗
```
### `{number} to be close to {number} within {number}`
**Aliases:** None
**Checks:** Value is within tolerance of target
**Parameters:** (subject, target, tolerance)
```typescript
expect(1.0, 'to be close to', 1.1, 0.2); // ✓ (diff = 0.1)
expect(3.14159, 'to be close to', 3.14, 0.01); // ✓
expect(1.0, 'to be close to', 2.0, 0.5); // ✗ (diff = 1.0)
```
---
## String & Pattern Assertions
### `{string} to begin with {string}`
**Aliases:** `to start with`
**Checks:** String starts with the specified prefix
```typescript
expect('hello world', 'to begin with', 'hello'); // ✓
expect('hello world', 'to start with', 'world'); // ✗
```
### `{string} to end with {string}`
**Aliases:** None
**Checks:** String ends with the specified suffix
```typescript
expect('hello world', 'to end with', 'world'); // ✓
expect('hello world', 'to end with', 'hello'); // ✗
```
### `{string} to match {RegExp}`
**Aliases:** None
**Checks:** String matches the regular expression
```typescript
expect('hello123', 'to match', /\d+/); // ✓
expect('JavaScript', 'to match', /^Java/); // ✓
expect('hello', 'to match', /\d+/); // ✗
```
### `{string} to be empty`
**Aliases:** None
**Checks:** String has zero length
```typescript
expect('', 'to be empty'); // ✓
expect('hello', 'to be empty'); // ✗
```
### `{string} to be non-empty`
**Aliases:** None
**Checks:** String has at least one character
```typescript
expect('hello', 'to be non-empty'); // ✓
expect(' ', 'to be non-empty'); // ✓ (whitespace counts)
expect('', 'to be non-empty'); // ✗
```
### `{string} includes {string}`
**Aliases:** `contains`
**Checks:** String contains the substring
```typescript
expect('hello world', 'includes', 'world'); // ✓
expect('hello', 'includes', 'world'); // ✗
```
### `{unknown} to be a RegExp`
**Aliases:** `to be a regex`, `to be a regexp`
**Checks:** Value is a RegExp object
```typescript
expect(/hello/, 'to be a RegExp'); // ✓
expect(new RegExp('world'), 'to be a regex'); // ✓
expect('hello', 'to be a RegExp'); // ✗
```
---
## Collection Assertions
### `{unknown} to be an array`
**Aliases:** `to be array`
**Checks:** Value is an Array
```typescript
expect([], 'to be an array'); // ✓
expect([1, 2, 3], 'to be an array'); // ✓
expect('hello', 'to be an array'); // ✗
```
### `{arraylike} to be empty`
**Aliases:** None
**Checks:** Array/string/collection has zero length
```typescript
expect([], 'to be empty'); // ✓
expect([1, 2, 3], 'to be empty'); // ✗
```
### `{array} to have length {nonnegative-integer}`
**Aliases:** `to have size`
**Checks:** Array/string has exact length
```typescript
expect([1, 2, 3], 'to have length', 3); // ✓
expect('hello', 'to have length', 5); // ✓
expect([1, 2], 'to have length', 3); // ✗
```
### `{arraylike} to be non-empty`
**Aliases:** None
**Checks:** Array/string has at least one element
```typescript
expect([1, 2, 3], 'to be non-empty'); // ✓
expect([], 'to be non-empty'); // ✗
```
### `{array} to contain {any}`
**Aliases:** `to include`
**Checks:** Array contains the value
```typescript
expect([1, 2, 3], 'to contain', 2); // ✓
expect(['a', 'b'], 'to include', 'c'); // ✗
```
### `{Map} to contain {any}`
**Aliases:** `to include`
**Checks:** Map contains the key
```typescript
const map = new Map([['key1', 'value1']]);
expect(map, 'to contain', 'key1'); // ✓
expect(map, 'to contain', 'key2'); // ✗
```
### `{Map} to have size {nonnegative-integer}`
**Aliases:** None
**Checks:** Map has exact size
```typescript
const map = new Map([
['a', 1],
['b', 2],
]);
expect(map, 'to have size', 2); // ✓
expect(map, 'to have size', 3); // ✗
```
### `{Map} to be empty`
**Aliases:** None
**Checks:** Map has no entries
```typescript
expect(new Map(), 'to be empty'); // ✓
expect(new Map([['a', 1]]), 'to be empty'); // ✗
```
### `{Set} to contain {any}`
**Aliases:** `to include`
**Checks:** Set contains the value
```typescript
const set = new Set([1, 2, 3]);
expect(set, 'to contain', 2); // ✓
expect(set, 'to contain', 5); // ✗
```
### `{Set} to have size {nonnegative-integer}`
**Aliases:** None
**Checks:** Set has exact size
```typescript
const set = new Set([1, 2, 3]);
expect(set, 'to have size', 3); // ✓
expect(set, 'to have size', 5); // ✗
```
### `{Set} to be empty`
**Aliases:** None
**Checks:** Set has no elements
```typescript
expect(new Set(), 'to be empty'); // ✓
expect(new Set([1]), 'to be empty'); // ✗
```
### `{unknown} to be a Set`
**Aliases:** None
**Checks:** Value is a Set
```typescript
expect(new Set(), 'to be a Set'); // ✓
expect([1, 2, 3], 'to be a Set'); // ✗
```
### `{WeakMap} to contain {object | symbol}`
**Aliases:** `to include`
**Checks:** WeakMap contains the key
```typescript
const obj = {};
const wm = new WeakMap([[obj, 'value']]);
expect(wm, 'to contain', obj); // ✓
```
### `{unknown} to be a WeakMap`
**Aliases:** None
**Checks:** Value is a WeakMap
```typescript
expect(new WeakMap(), 'to be a WeakMap'); // ✓
expect(new Map(), 'to be a WeakMap'); // ✗
```
### `{WeakSet} to contain {object | symbol}`
**Aliases:** `to include`
**Checks:** WeakSet contains the value
```typescript
const obj = {};
const ws = new WeakSet([obj]);
expect(ws, 'to contain', obj); // ✓
```
### `{unknown} to be a WeakSet`
**Aliases:** None
**Checks:** Value is a WeakSet
```typescript
expect(new WeakSet(), 'to be a WeakSet'); // ✓
expect(new Set(), 'to be a WeakSet'); // ✗
```
---
## Object Assertions
### `{unknown} to be an object`
**Aliases:** None
**Checks:** Value is an object (includes arrays, excludes null)
```typescript
expect({}, 'to be an object'); // ✓
expect([], 'to be an object'); // ✓ (arrays are objects)
expect(new Date(), 'to be an object'); // ✓
expect(null, 'to be an object'); // ✗
expect('hello', 'to be an object'); // ✗
```
**Note:** `to be an object` already implies non-null. No need for redundant null checks.
### `{unknown} to be a record`
**Aliases:** `to be a plain object`
**Checks:** Value is a plain object (excludes arrays, dates, etc.)
```typescript
expect({}, 'to be a record'); // ✓
expect({ a: 1 }, 'to be a plain object'); // ✓
expect([], 'to be a record'); // ✗
expect(new Date(), 'to be a record'); // ✗
```
### `{object} to be empty`
**Aliases:** None
**Checks:** Object has no own enumerable properties
```typescript
expect({}, 'to be empty'); // ✓
expect({ a: 1 }, 'to be empty'); // ✗
```
### `{object} to have keys {array}`
**Aliases:** `to have properties`, `to have props`, `to include keys`, `to include properties`, `to include props`, `to contain keys`, `to contain properties`, `to contain props`
**Checks:** Object has all specified keys
```typescript
expect({ a: 1, b: 2 }, 'to have keys', ['a', 'b']); // ✓
expect({ a: 1 }, 'to have keys', ['a', 'b']); // ✗ (missing 'b')
```
### `{object} to have key {keypath}`
**Aliases:** `to have property`, `to have prop`, `to include key`, `to include property`, `to include prop`, `to contain key`, `to contain property`, `to contain prop`
**Checks:** Object has property at keypath (supports dot/bracket notation)
**Keypath formats:**
- Dot notation: `'prop.nested'`
- Bracket notation: `'arr[0]'`, `'obj["key"]'`
- Mixed: `'data.items[1].name'`
```typescript
const obj = {
foo: { bar: [{ baz: 'value' }] },
items: [{ id: 1 }, { id: 2 }],
};
expect(obj, 'to have property', 'foo.bar'); // ✓
expect(obj, 'to have key', 'foo.bar[0].baz'); // ✓
expect(obj, 'to have property', 'items[1].id'); // ✓
expect(obj, 'to have key', 'nonexistent.path'); // ✗
```
### `{object} to have exact key {string | number | symbol}`
**Aliases:** `to have exact property`, `to have exact prop`
**Checks:** Object has direct property (no keypath traversal)
```typescript
const sym = Symbol('test');
const obj = {
'key.with.dots': 'value', // literal key, not nested
'key[with]brackets': 'value', // literal key, not array
[sym]: 'symbol value',
};
expect(obj, 'to have exact key', 'key.with.dots'); // ✓ (literal key)
expect(obj, 'to have exact property', 'key[with]brackets'); // ✓
expect(obj, 'to have exact key', sym); // ✓
```
### `{object} to satisfy {any}`
**Aliases:** `to be like`
**Checks:** Object contains at least the specified properties (partial match)
**Special features:**
- RegExp values test corresponding property as string
- `expect.it()` embeds assertions
- Ignores extra properties
```typescript
expect({ a: 1, b: 2, c: 3 }, 'to satisfy', { a: 1, b: 2 }); // ✓
// Using RegExp
expect({ email: 'user@example.com', phone: '+1-555-0123' }, 'to satisfy', {
email: /^user@/,
phone: /^\+1-555/,
}); // ✓
// Using expect.it()
expect({ name: 'John', age: 30 }, 'to satisfy', {
name: expect.it('to be a string'),
age: expect.it('to be greater than', 18),
}); // ✓
```
### `{object} to have a null prototype`
**Aliases:** `to be a dictionary`
**Checks:** Object was created with Object.create(null)
```typescript
const obj = Object.create(null);
expect(obj, 'to have a null prototype'); // ✓
expect({}, 'to have a null prototype'); // ✗
```
### `{string | number | symbol} to be an enumerable property of {non-null}`
**Aliases:** `{non-null} to have enumerable property {string | number | symbol}`
**Checks:** Property exists and is enumerable
```typescript
const obj = { a: 1, b: 2 };
expect('a', 'to be an enumerable property of', obj); // ✓
Object.defineProperty(obj, 'c', { value: 3, enumerable: false });
expect('c', 'to be an enumerable property of', obj); // ✗
```
### `{unknown} to be sealed`
**Aliases:** None
**Checks:** Object is sealed (Object.seal())
```typescript
const obj = { a: 1 };
Object.seal(obj);
expect(obj, 'to be sealed'); // ✓
expect({}, 'to be sealed'); // ✗
```
### `{unknown} to be frozen`
**Aliases:** None
**Checks:** Object is frozen (Object.freeze())
```typescript
const obj = { a: 1 };
Object.freeze(obj);
expect(obj, 'to be frozen'); // ✓
expect({}, 'to be frozen'); // ✗
```
### `{unknown} to be extensible`
**Aliases:** None
**Checks:** New properties can be added to object
```typescript
expect({}, 'to be extensible'); // ✓
const obj = {};
Object.preventExtensions(obj);
expect(obj, 'to be extensible'); // ✗
```
---
## Function Assertions
### `{unknown} to be a function`
**Aliases:** None
**Checks:** Value is a function
```typescript
expect(() => {}, 'to be a function'); // ✓
expect(Math.max, 'to be a function'); // ✓
expect('hello', 'to be a function'); // ✗
```
### `{unknown} to be an async function`
**Aliases:** None
**Checks:** Value is an async function
```typescript
expect(async () => {}, 'to be an async function'); // ✓
expect(() => {}, 'to be an async function'); // ✗
```
### `{unknown} to be a constructor`
**Aliases:** `to be constructible`, `to be a class`
**Checks:** Function can be called with 'new'
**Warning:** Cannot reliably distinguish classes from regular functions
```typescript
class MyClass {}
expect(MyClass, 'to be a class'); // ✓
expect(Date, 'to be a constructor'); // ✓
```
### `{function} to have arity {nonnegative-integer}`
**Aliases:** None
**Checks:** Function has exact number of parameters
```typescript
function add(a, b) {
return a + b;
}
expect(add, 'to have arity', 2); // ✓
expect(add, 'to have arity', 3); // ✗
```
### `{function} to throw [{any}]`
**Aliases:** `to throw an error satisfying`
**Checks:** Function throws when called
**Optional parameter:** Uses "to satisfy" semantics (string/RegExp/object matching)
```typescript
expect(() => {
throw new Error('oops');
}, 'to throw'); // ✓
// String matching
expect(
() => {
throw new Error('Specific error');
},
'to throw',
'Specific error',
); // ✓
// RegExp matching
expect(
() => {
throw new Error('Error: failed');
},
'to throw',
/failed/,
); // ✓
// Object matching
expect(
() => {
throw new Error('Custom error');
},
'to throw',
{ message: 'Custom error' },
); // ✓
```
### `{function} to throw a {constructor}`
**Aliases:** `to throw an`
**Checks:** Function throws specific error type
```typescript
expect(
() => {
throw new TypeError('type error');
},
'to throw a',
TypeError,
); // ✓
expect(
() => {
throw new TypeError('type error');
},
'to throw a',
RangeError,
); // ✗
```
### `{function} to throw a {constructor} satisfying {any}`
**Aliases:** `to throw an {constructor} satisfying`
**Checks:** Function throws specific error type matching pattern
```typescript
expect(
() => {
const err = new Error('Custom error');
err.code = 'CUSTOM_CODE';
throw err;
},
'to throw a',
Error,
'satisfying',
{ code: 'CUSTOM_CODE' },
); // ✓
```
---
## Equality & Comparison Assertions
### `{unknown} to equal {any}`
**Aliases:** `to be`, `equals`, `is`, `is equal to`, `to strictly equal`, `is strictly equal to`
**Checks:** Values are strictly equal (===)
```typescript
expect(42, 'to be', 42); // ✓
expect('hello', 'to equal', 'hello'); // ✓
expect(42, 'is', '42'); // ✗ (different types)
expect({}, 'to equal', {}); // ✗ (different references)
```
### `{unknown} to deep equal {any}`
**Aliases:** `to deeply equal`
**Checks:** Values are deeply equal (recursive comparison)
```typescript
expect({ a: 1, b: 2 }, 'to deep equal', { a: 1, b: 2 }); // ✓
expect([1, 2, 3], 'to deeply equal', [1, 2, 3]); // ✓
expect({ a: 1 }, 'to deep equal', { a: 1, b: 2 }); // ✗
```
### `{unknown} to be one of {array}`
**Aliases:** None
**Checks:** Value is in the array
```typescript
expect(2, 'to be one of', [1, 2, 3]); // ✓
expect('blue', 'to be one of', ['red', 'green', 'blue']); // ✓
expect(5, 'to be one of', [1, 2, 3]); // ✗
```
### `{unknown} to be an instance of {constructor}`
**Aliases:** `to be a`, `to be an`
**Checks:** Value is instance of constructor
```typescript
expect(new Date(), 'to be an instance of', Date); // ✓
expect([], 'to be a', Array); // ✓
expect('hello', 'to be an instance of', Number); // ✗
```
### `{unknown} to be a {intrinsic-type}`
**Aliases:** `to be an`, `to have type`
**Checks:** Value is of intrinsic type (case-insensitive)
**Intrinsic types:** string, number, boolean, bigint, symbol, undefined, object, function, null, Map, Set, WeakMap, WeakSet, WeakRef, Date, Error, Array, RegExp, Promise
```typescript
expect(new Date(), 'to be a', 'Date'); // ✓
expect([], 'to be an', 'Array'); // ✓
expect(1, 'to be a', 'number'); // ✓
```
---
## Error Assertions
### `{unknown} to be an Error`
**Aliases:** `to be a Error`
**Checks:** Value is an Error instance
```typescript
expect(new Error(), 'to be an Error'); // ✓
expect(new TypeError(), 'to be an Error'); // ✓
expect('error message', 'to be an Error'); // ✗
```
### `{Error} to have message {string}`
**Aliases:** None
**Checks:** Error has exact message
```typescript
const error = new Error('Something went wrong');
expect(error, 'to have message', 'Something went wrong'); // ✓
expect(error, 'to have message', 'Different message'); // ✗
```
### `{Error} to have message matching {RegExp}`
**Aliases:** None
**Checks:** Error message matches pattern
```typescript
const error = new Error('File not found: /path/to/file.txt');
expect(error, 'to have message matching', /File not found/); // ✓
expect(error, 'to have message matching', /\.txt$/); // ✓
```
---
## Date & Time Assertions
### `{unknown} to be a Date`
**Aliases:** `to be a date`
**Checks:** Value is a Date object
```typescript
expect(new Date(), 'to be a Date'); // ✓
expect('2024-01-01', 'to be a Date'); // ✗
expect(1704067200000, 'to be a Date'); // ✗ (timestamp)
```
### `{unknown} to be a valid date`
**Aliases:** `to be date-like`
**Checks:** Value can be converted to a valid date
```typescript
expect(new Date(), 'to be a valid date'); // ✓
expect('2024-01-01', 'to be date-like'); // ✓
expect(1704067200000, 'to be a valid date'); // ✓ (timestamp)
expect('invalid-date', 'to be a valid date'); // ✗
```
### `{date-like} to be before {date-like}`
**Aliases:** None
**Checks:** Date is before another date
```typescript
expect(new Date('2022-01-01'), 'to be before', new Date('2023-01-01')); // ✓
expect('2022-01-01', 'to be before', '2023-01-01'); // ✓
```
### `{date-like} to be after {date-like}`
**Aliases:** None
**Checks:** Date is after another date
```typescript
expect(new Date('2023-01-01'), 'to be after', new Date('2022-01-01')); // ✓
expect(Date.now(), 'to be after', new Date('2020-01-01')); // ✓
```
### `{date-like} to be between {date-like} and {date-like}`
**Aliases:** None
**Checks:** Date is between two dates (inclusive)
```typescript
expect(
new Date('2022-06-01'),
'to be between',
new Date('2022-01-01'),
new Date('2022-12-31'),
); // ✓
```
### `{date-like} to be the same date as {date-like}`
**Aliases:** None
**Checks:** Dates represent the same calendar day (ignores time)
```typescript
expect(
new Date('2023-01-01T10:00:00'),
'to be the same date as',
new Date('2023-01-01T15:30:00'),
); // ✓ (same date, different times)
```
### `{date-like} to equal {date-like} within {duration}`
**Aliases:** None
**Checks:** Dates are within specified duration
**Duration formats:** "100 milliseconds", "30 seconds", "5 minutes", "2 hours", "7 days"
```typescript
const date1 = new Date('2023-01-01T10:00:00.000Z');
const date2 = new Date('2023-01-01T10:00:00.500Z');
expect(date1, 'to equal', date2, 'within', '1 second'); // ✓ (500ms diff)
```
### `{unknown} to be a weekend`
**Aliases:** None
**Checks:** Date is Saturday or Sunday (in UTC)
```typescript
expect(new Date('2023-01-07'), 'to be a weekend'); // ✓ (Saturday)
expect(new Date('2023-01-09'), 'to be a weekend'); // ✗ (Monday)
```
### `{unknown} to be a weekday`
**Aliases:** None
**Checks:** Date is Monday-Friday (in UTC)
```typescript
expect(new Date('2023-01-09'), 'to be a weekday'); // ✓ (Monday)
expect(new Date('2023-01-07'), 'to be a weekday'); // ✗ (Saturday)
```
---
## Promise Assertions
**Note:** All promise assertions require `expectAsync()` instead of `expect()`
### `{Promise} to resolve`
**Aliases:** `to fulfill`
**Checks:** Promise resolves successfully
```typescript
await expectAsync(Promise.resolve(42), 'to resolve'); // ✓
await expectAsync(async () => 'result', 'to resolve'); // ✓
await expectAsync(Promise.reject('error'), 'to resolve'); // ✗
```
### `{Promise} to reject`
**Aliases:** None
**Checks:** Promise rejects
```typescript
await expectAsync(Promise.reject('error'), 'to reject'); // ✓
await expectAsync(async () => {
throw new Error('failed');
}, 'to reject'); // ✓
await expectAsync(Promise.resolve(42), 'to reject'); // ✗
```
### `{Promise} to reject with a {constructor}`
**Aliases:** `to reject with an`
**Checks:** Promise rejects with specific error type
```typescript
await expectAsync(
Promise.reject(new TypeError('Type error')),
'to reject with a',
TypeError,
); // ✓
```
### `{Promise} to reject with error satisfying {any}`
**Aliases:** None
**Checks:** Promise rejection matches pattern (string/RegExp/object)
```typescript
// String matching
await expectAsync(
Promise.reject(new Error('Specific error')),
'to reject with',
'Specific error',
); // ✓
// RegExp matching
await expectAsync(
Promise.reject(new Error('Error: Something failed')),
'to reject with',
/Something failed/,
); // ✓
// Object matching
await expectAsync(
Promise.reject({ message: 'Custom error', code: 500 }),
'to reject with',
{ message: 'Custom error' },
); // ✓
```
### `{Promise} to resolve with value satisfying {any}`
**Aliases:** `to fulfill with value satisfying`
**Checks:** Promise resolves to value matching pattern
```typescript
// String matching
await expectAsync(
Promise.resolve('Hello World'),
'to fulfill with value satisfying',
'Hello World',
); // ✓
// RegExp matching
await expectAsync(
Promise.resolve('Success: Operation completed'),
'to resolve to value satisfying',
/Success/,
); // ✓
// Object matching
await expectAsync(
Promise.resolve({ status: 'ok', data: [1, 2, 3] }),
'to fulfill with value satisfying',
{ status: 'ok' },
); // ✓
```
---
## Other Assertions
### `{unknown} to be truthy`
**Aliases:** `to exist`, `to be ok`
**Checks:** Value is truthy
```typescript
expect(1, 'to be truthy'); // ✓
expect('hello', 'to be truthy'); // ✓
expect(true, 'to exist'); // ✓
expect(0, 'to be truthy'); // ✗
expect('', 'to exist'); // ✗
expect(null, 'to be ok'); // ✗
```
### `{unknown} to be falsy`
**Aliases:** None
**Checks:** Value is falsy
```typescript
expect(0, 'to be falsy'); // ✓
expect('', 'to be falsy'); // ✓
expect(false, 'to be falsy'); // ✓
expect(null, 'to be falsy'); // ✓
expect(undefined, 'to be falsy'); // ✓
expect(1, 'to be falsy'); // ✗
```
### `{unknown} to be defined`
**Aliases:** None
**Checks:** Value is not undefined
```typescript
expect(0, 'to be defined'); // ✓
expect('', 'to be defined'); // ✓
expect(null, 'to be defined'); // ✓
expect(undefined, 'to be defined'); // ✗
```
---
## Quick Reference Tables
### Type Checking
| Phrase | Checks |
| ------------------ | ----------------------- |
| `to be a string` | Is a string |
| `to be a number` | Is a finite number |
| `to be a boolean` | Is a boolean |
| `to be a bigint` | Is a BigInt |
| `to be a symbol` | Is a Symbol |
| `to be an object` | Is an object (non-null) |
| `to be a function` | Is a function |
| `to be an array` | Is an Array |
| `to be a Date` | Is a Date object |
| `to be an Error` | Is an Error |
| `to be null` | Is null |
| `to be undefined` | Is undefined |
| `to be defined` | Is not undefined |
### Comparisons
| Phrase | Checks |
| ------------------------- | ------------------------ |
| `to equal`, `to be`, `is` | Strict equality (===) |
| `to deep equal` | Deep structural equality |
| `to be greater than` | Numeric > comparison |
| `to be less than` | Numeric < comparison |
| `to be between` | Within range (inclusive) |
| `to be one of` | Value in array |
### Collections
| Phrase | Checks |
| ------------------------------------ | ------------------------------ |
| `to be empty` | Length/size is 0 |
| `to have length` | Exact length/size |
| `to contain`, `to include` | Contains value |
| `to have property`, `to have key` | Has property (keypath support) |
| `to have properties`, `to have keys` | Has all specified keys |
### Object Patterns
| Phrase | Checks |
| ------------ | ---------------------------------------------------- |
| `to satisfy` | Partial object match with RegExp/expect.it() support |
| `to be like` | Alias for `to satisfy` |
### Promises
| Phrase | Requires | Checks |
| ---------------------------------- | --------------- | -------------------------- |
| `to resolve` | `expectAsync()` | Promise resolves |
| `to reject` | `expectAsync()` | Promise rejects |
| `to reject with` | `expectAsync()` | Rejection matches pattern |
| `to resolve with value satisfying` | `expectAsync()` | Resolution matches pattern |
### Functions
| Phrase | Checks |
| ------------------- | ----------------------------------- |
| `to throw` | Function throws |
| `to throw a {Type}` | Function throws specific error type |
| `to have arity` | Function parameter count |