earljs
Version:
Ergonomic, modern and type-safe assertion library
361 lines (360 loc) • 11.8 kB
TypeScript
import { UnionToIntersection } from 'ts-essentials';
import type { Expectation } from '../Expectation';
import { ExpectedEqual } from '../isEqual/rules';
import type { Mock, MockArgs } from '../mocks/types';
import type { Newable } from '../types';
export interface Validators {
}
export declare type ValidatorsFor<T> = __ValidatorsFor<Values<AllValidators<T>>, T>;
export declare type __ValidatorsFor<TValidators, TActual> = UnionToIntersection<TValidators extends [infer A, infer Matchers] ? TActual extends A ? Matchers : unknown extends TActual ? Matchers : never : never> & {
[P in keyof Validators]: Validators[P] extends (this: Expectation<infer A>, ...args: infer Args) => void ? TActual extends A ? (...args: Args) => void : unknown extends TActual ? (...args: Args) => void : never : never;
};
export declare type Values<T> = T[keyof T & number];
export declare type ItemOfIterable<T> = Extract<T, Iterable<any>> extends Iterable<infer R> ? R : never;
export declare type AllValidators<T> = [
[
unknown,
CommonValidators<T>
],
[
Mock<any[], any>,
MockValidators<T>
],
[
number,
NumberValidators
],
[
object,
ObjectValidators
],
[
any[],
ArrayValidators
],
[
Iterable<any>,
IterableValidators<ItemOfIterable<T>>
],
[
Promise<unknown>,
PromiseValidators
],
[
() => any,
FunctionValidators
]
];
export interface CommonValidators<T> extends BooleanValidators, OptionalValidators {
/**
* Performs a recursive equality check. Objects are equal if their fields
* are equal and they share the same prototype.
*
* You can use matchers in place of a value. When a matcher is encountered its
* internal rules are used instead of the usual checks.
*
* @param value - value to check against.
*
* @example
* ```ts
* expect('foo').toEqual('foo') // Equality check against primitive value
* expect([1, { a: 2 }]).toEqual([1, { a: expect.a(Number) }]) // Usage with "a" matcher
* expect({ a: 2, b: 2 }).not.toEqual({ a: 2 }) // Negated equality check
* ```
*/
toEqual(value: ExpectedEqual<T>): void;
/**
* Performs a recursive equality check. Objects are equal if their fields
* are equal. Object prototypes are ignored.
*
* You can use matchers in place of a value. When a matcher is encountered its
* internal rules are used instead of the usual checks.
*
* @param value - value to check against.
*
* @example
* ```ts
* class A {
* a = 1
* }
*
* // using toEqual requires matching prototypes
* expect(new A()).not.toEqual({ a: 1 })
* // toLooseEqual ignores prototypes and focuses only on the value
* expect(new A()).toLooseEqual({ a: 1 })
* ```
*/
toLooseEqual(value: any): void;
/**
* Performs a referential equality check using `Object.is`. It is similar to
* `===`, with two differences:
*
* 1. `Object.is(-0, +0)` returns `false`
* 2. `Object.is(NaN, NaN)` returns `true`
*
* This function should be used if you care about object identity rather than
* deep equality.
*
* @param value - value to check against.
*
* @example
* ```ts
* const x = {}
* expect(x).toReferentiallyEqual(x)
* expect({}).not.toReferentiallyEqual(x)
* expect(NaN).toReferentiallyEqual(NaN)
* ```
*/
toReferentiallyEqual(value: T): void;
/**
* Checks if the value is an instance of a provided class or a primitive type. Works as expected with builtin types like strings, numbers, dates.
*
* 1. `expect.a(MyClass)` - matches `new MyClass`, but not `new Other()`
* 2. `expect.a(String)` - matches `"foo"`, but not `123`
*
* @param clazz - type class or primitive constructor to match against.
* @example
* ```ts
* expect(object).toBeA(MyClass) // checks if object is instance of `MyClass`, but not `Other`
* expect(foo).toBeA(String) // checks if foo is instance of string
* expect(foo).toBeA(Object) // matches any object (not null)
* ```
*/
toBeA(clazz: any): void;
/**
* Checks that the value is the same as in the previous test execution.
*/
toMatchSnapshot(): void;
}
export interface FunctionValidators {
/**
* Calls the provided function and expects an error to be thrown. The message
* of the error is also checked.
*
* @param message - string or matcher to check the message against.
*
* @example
* ```ts
* const doThrow = () => { throw new Error('oops, sorry') }
*
* expect(() => doThrow()).toThrow('oops')
* expect(() => doThrow()).not.toThrow(expect.stringMatching(/end$/))
* ```
*/
toThrow(message?: string): void;
/**
* Calls the provided function and expects an error to be thrown. The error's
* class and message are also checked.
*
* @param errorClass - expected class of the thrown error.
* @param message - string or matcher to check the message against.
*
* @example
* ```ts
* const doThrow = () => {
* throw new Error('oops, sorry')
* }
*
* expect(() => doThrow()).toThrow(Error, 'oops')
* expect(() => doThrow()).not.toThrow(TypeError)
* ```
*/
toThrow(errorClass: Newable<Error>, message?: string): void;
}
export interface NumberValidators {
/**
* Checks if the value is greater than the provided target.
* @param target - number to check against.
*
* @example
* ```ts
* expect(2).toBeGreaterThan(1)
* expect(1).not.toBeGreaterThan(1)
* expect(-3).not.toBeGreaterThan(1)
* ```
*/
toBeGreaterThan(target: number): void;
/**
* Checks if the value is greater than or equal to the provided target.
* @param target - number to check against.
*
* @example
* ```ts
* expect(2).toBeGreaterThanOrEqualTo(1)
* expect(1).toBeGreaterThanOrEqualTo(1)
* expect(-3).not.toBeGreaterThanOrEqualTo(1)
* ```
*/
toBeGreaterThanOrEqualTo(target: number): void;
/**
* Checks if the value is less than the provided target.
* @param target - number to check against.
*
* @example
* ```ts
* expect(-3).toBeLessThan(1)
* expect(1).not.toBeLessThan(1)
* expect(2).not.toBeLessThan(1)
* ```
*/
toBeLessThan(target: number): void;
/**
* Checks if the value is less than or equal the provided target.
* @param target - number to check against.
*
* @example
* ```ts
* expect(-3).toBeLessThanOrEqualTo(1)
* expect(1).toBeLessThanOrEqualTo(1)
* expect(2).not.toBeLessThanOrEqualTo(1)
* ```
*/
toBeLessThanOrEqualTo(target: number): void;
}
export interface BooleanValidators {
/**
* Checks if the value is truthy.
*
* @example
* ```ts
* expect(1).toBeTruthy()
* expect(false).not.toBeTruthy()
* ```
*
* There are six falsy values in JavaScript: `false`, `0`, `''`, `null`, `undefined`, and `NaN`. \
* Everything else is truthy.
*/
toBeTruthy(): void;
/**
* Checks if the value is falsy.
*
* @example
* ```ts
* expect(0).toBeFalsy()
* expect(true).not.toBeFalsy()
* ```
*
* There are six falsy values in JavaScript: `false`, `0`, `''`, `null`, `undefined`, and `NaN`. \
* Everything else is truthy.
*/
toBeFalsy(): void;
}
export interface OptionalValidators {
/**
* Checks if the value is different to `undefined` and `null`.
*
* @example
* ```ts
* expect(0).toBeDefined()
* expect(null).not.toBeDefined()
* ```
*/
toBeDefined(): void;
/**
* Checks if the value is `undefined` or `null`.
*
* @example
* ```ts
* expect(undefined).toBeNullish()
* expect(false).not.toBeNullish()
* ```
*/
toBeNullish(): void;
}
export interface PromiseValidators {
/**
* Awaits the provided promise and expects it to be rejected. The message
* of the error is also checked.
*
* @param message - string or matcher to check the message against.
* @example
* ```ts
* const promise = Promise.reject(new Error('oops, sorry'))
*
* await expect(promise).toBeRejected(Error, 'oops')
* await expect(promise).not.toBeRejected(TypeError)
* ```
*/
toBeRejected(message?: string): Promise<void>;
/**
* Awaits the provided promise and expects it to be rejected. The error's
* class and message are also checked.
*
* @param errorClass - expected class of the thrown error.
* @param message - string or matcher to check the message against.
*/
toBeRejected(errorClass: Newable<Error>, message?: string): Promise<void>;
}
export interface MockValidators<T> {
/**
* Checks if all the expected calls to the mock have been performed.
*/
toBeExhausted(): void;
/**
* Check if the mock has been called with the provided arguments.
*
* You can use matchers in place of a value. When a matcher is encountered its
* internal rules are used instead of the usual checks.
*
* @param args - an array of values or matchers to check the mock calls against.
*/
toHaveBeenCalledWith(args: MockArgs<T>): void;
/**
* Checks the entire history of mock calls.
*
* You can use matchers in place of a value. When a matcher is encountered its
* internal rules are used instead of the usual checks.
*
* @param args - an array where each item is an array of values or matchers to check the mock call against.
*/
toHaveBeenCalledExactlyWith(args: MockArgs<T>[]): void;
}
export interface ObjectValidators {
/**
* Checks if the value is an object containing given key-value pairs.
*
* @param subset - an object to match against.
*
* @example
* ```ts
* expect({ a: 1, b: 2, c: 3 }).toBeAnObjectWith({ b: 2, a: 1 })
* ```
*/
toBeAnObjectWith(subset: object): void;
}
export interface ArrayValidators {
/**
* Checks if the values is an array containing exactly given number of items.
*
* @param length - expected array length. Can be a matcher.
* @example
* ```ts
* expect([1, 2, 3]).toBeAnArrayOfLength(3)
* expect([1, 2, 3]).toBeAnArrayOfLength(expect.numberGreaterThanOrEqualTo(3)))
* ```
*/
toBeAnArrayOfLength(length: number): void;
/**
* Checks if the value is an array containing all of the provided items. Each expected item must be matched uniquely.
*
* @param expectedItems - values or matchers to look for in the matched array. Order of the items doesn't matter.
* @example
* ```ts
* expect([1, 2, 3]).toBeAnArrayWith(1)
* expect([1]).toBeAnArrayWith(1, 1) // throws b/c a second "1" is missing
* ```
*/
toBeAnArrayWith(...expectedItems: ReadonlyArray<any>): void;
}
export interface IterableValidators<T> {
/**
* Checks if the value is an iterable containing all of the provided items. Internally, container is first turned into array and `toBeAnArrayWith` is used for final comparison.
*
* @param expectedItems - values or matchers to look for in the matched iterable. Order of the items doesn't matter.
* @example
* ```ts
* expect([1, 2, 3]).toBeAContainerWith(1, 2)
* ```
*/
toBeAContainerWith(...expectedItems: T[]): void;
}