Files
AI/참고/playwright-main/tests/page/expect-builtins.spec.ts
2026-05-12 19:40:31 +09:00

923 lines
27 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
* Modifications copyright (c) Microsoft Corporation.
*
* This source code is licensed under the MIT license found here
* https://github.com/jestjs/jest/blob/v30.2.0/LICENSE
*/
// Adapted from jest/packages/expect/src/__tests__/matchers.test.js,
// asymmetricMatchers.test.ts and toThrowMatchers.test.ts.
import { test, expect } from './pageTest';
test.describe('.toBe()', () => {
test('does not throw', () => {
expect('a').not.toBe('b');
expect('a').toBe('a');
expect(1).not.toBe(2);
expect(1).toBe(1);
expect(null).not.toBe(undefined);
expect(null).toBe(null);
expect(undefined).toBe(undefined);
expect(NaN).toBe(NaN);
expect(BigInt(1)).not.toBe(BigInt(2));
expect(BigInt(1)).not.toBe(1);
expect(BigInt(1)).toBe(BigInt(1));
});
for (const [i, [a, b]] of [
[1, 2],
[true, false],
[{}, {}],
[{ a: 1 }, { a: 1 }],
[{ a: 1 }, { a: 5 }],
[{ a: undefined, b: 2 }, { b: 2 }],
[new Date('2020-02-20'), new Date('2020-02-20')],
[/received/, /expected/],
[['abc'], ['cde']],
[[], []],
[null, undefined],
[-0, +0],
].entries()) {
test(`fails for: ${JSON.stringify(a)} and ${JSON.stringify(b)} #${i}`, () => {
expect(() => expect(a).toBe(b)).toThrow();
});
}
for (const v of [false, 1, 'a', undefined, null, {}, []]) {
test(`fails for '${JSON.stringify(v)}' with '.not'`, () => {
expect(() => expect(v).not.toBe(v)).toThrow();
});
}
test('does not crash on circular references', () => {
const obj: any = {};
obj.circular = obj;
expect(() => expect(obj).toBe({})).toThrow();
});
test('matcherResult property contains matcher name, expected and actual values', () => {
const actual = { a: 1 };
const expected = { a: 2 };
try {
expect(actual).toBe(expected);
} catch (error) {
expect(error.matcherResult).toEqual(expect.objectContaining({
actual,
expected,
name: 'toBe',
}));
}
});
});
test.describe('.toStrictEqual()', () => {
class TestClassA {
a: number;
b: number;
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
}
class TestClassB {
a: number;
b: number;
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
}
test('does not ignore keys with undefined values', () => {
expect({ a: undefined, b: 2 }).not.toStrictEqual({ b: 2 });
});
test('does not ignore keys with undefined values inside an array', () => {
expect([{ a: undefined }]).not.toStrictEqual([{}]);
});
test('passes when comparing same type', () => {
expect({ test: new TestClassA(1, 2) }).toStrictEqual({ test: new TestClassA(1, 2) });
});
test('does not pass for different types', () => {
expect({ test: new TestClassA(1, 2) }).not.toStrictEqual({ test: new TestClassB(1, 2) });
});
test('passes for matching buffers', () => {
expect(Uint8Array.from([1]).buffer).toStrictEqual(Uint8Array.from([1]).buffer);
expect(Uint8Array.from([]).buffer).toStrictEqual(Uint8Array.from([]).buffer);
expect(Uint8Array.from([9, 3]).buffer).toStrictEqual(Uint8Array.from([9, 3]).buffer);
});
test('does not pass when ArrayBuffers are not equal', () => {
expect(Uint8Array.from([1, 2]).buffer).not.toStrictEqual(Uint8Array.from([0, 0]).buffer);
});
});
test.describe('.toEqual()', () => {
for (const [a, b] of [
[true, false],
[1, 2],
[0, Number.MIN_VALUE],
[{ a: 1 }, { a: 2 }],
['banana', 'apple'],
[null, undefined],
[[1], [2]],
[new Set([1, 2]), new Set()],
[new Set([1, 2]), new Set([1, 2, 3])],
[new Map([['a', 0]]), new Map([['b', 0]])],
[new Uint8Array([97, 98, 99]), new Uint8Array([97, 98, 100])],
[{ a: 1, b: 2 }, expect.objectContaining({ a: 2 })],
[[1, 3], expect.arrayContaining([1, 2])],
['abd', expect.stringContaining('bc')],
['abd', expect.stringMatching(/bc/i)],
[undefined, expect.anything()],
[undefined, expect.any(Function)],
].entries()) {
test(`{pass: false} expect().toEqual() #${a}`, () => {
expect(() => expect(b[0]).toEqual(b[1])).toThrow();
expect(b[0]).not.toEqual(b[1]);
});
}
for (const [a, b] of [
[true, true],
[1, 1],
[NaN, NaN],
['abc', 'abc'],
[[1], [1]],
[{}, {}],
[{ a: 99 }, { a: 99 }],
[new Set(), new Set()],
[new Set([1, 2]), new Set([1, 2])],
[new Set([1, 2]), new Set([2, 1])],
[new Map(), new Map()],
[new Uint8Array([97, 98, 99]), new Uint8Array([97, 98, 99])],
[{ a: 1, b: 2 }, expect.objectContaining({ a: 1 })],
[[1, 2, 3], expect.arrayContaining([2, 3])],
['abcd', expect.stringContaining('bc')],
['abcd', expect.stringMatching('bc')],
[true, expect.anything()],
[() => {}, expect.any(Function)],
].entries()) {
test(`{pass: true} expect().toEqual() #${a}`, () => {
expect(b[0]).toEqual(b[1]);
expect(() => expect(b[0]).not.toEqual(b[1])).toThrow();
});
}
test('assertion error matcherResult property contains matcher name, expected and actual values', () => {
const actual = { a: 1 };
const expected = { a: 2 };
try {
expect(actual).toEqual(expected);
} catch (error) {
expect(error.matcherResult).toEqual(expect.objectContaining({
actual,
expected,
name: 'toEqual',
}));
}
});
test('symbol based keys in arrays are processed correctly', () => {
const mySymbol = Symbol('test');
const actual1: any[] = [];
actual1[mySymbol as any] = 3;
const actual2: any[] = [];
actual2[mySymbol as any] = 4;
const expected: any[] = [];
expected[mySymbol as any] = 3;
expect(actual1).toEqual(expected);
expect(actual2).not.toEqual(expected);
});
test('non-enumerable members should be skipped during equal', () => {
const actual: any = { x: 3 };
Object.defineProperty(actual, 'test', { enumerable: false, value: 5 });
expect(actual).toEqual({ x: 3 });
});
test('objectContaining sample can be used multiple times', () => {
const expected = expect.objectContaining({ b: 7 });
expect({ a: 1, b: 2 }).not.toEqual(expected);
expect({ a: 3, b: 7 }).toEqual(expected);
});
test.describe('cyclic object equality', () => {
test('properties with the same circularity are equal', () => {
const a: any = {};
a.x = a;
const b: any = {};
b.x = b;
expect(a).toEqual(b);
expect(b).toEqual(a);
});
test('properties with different circularity are not equal', () => {
const a: any = {};
a.x = { y: a };
const b: any = {};
const bx: any = {};
b.x = bx;
bx.y = bx;
expect(a).not.toEqual(b);
expect(b).not.toEqual(a);
});
});
});
test.describe('.toBeInstanceOf()', () => {
class A {}
class B {}
class C extends B {}
class E extends C {}
for (const [i, [a, b]] of ([
[new Map(), Map],
[[], Array],
[new A(), A],
[new C(), B],
[new E(), B],
] as const).entries()) {
test(`passing instanceof #${i}`, () => {
expect(() => expect(a).not.toBeInstanceOf(b)).toThrow();
expect(a).toBeInstanceOf(b);
});
}
for (const [i, [a, b]] of ([
['a', String],
[1, Number],
[true, Boolean],
[new A(), B],
] as const).entries()) {
test(`failing instanceof #${i}`, () => {
expect(() => expect(a).toBeInstanceOf(b)).toThrow();
expect(a).not.toBeInstanceOf(b);
});
}
test('throws if constructor is not a function', () => {
expect(() => expect({}).toBeInstanceOf(4 as any)).toThrow();
});
});
test.describe('.toBeTruthy(), .toBeFalsy()', () => {
for (const v of [{}, [], true, 1, 'a', 0.5, new Map(), () => {}, Infinity]) {
test(`'${String(v)}' is truthy`, () => {
expect(v).toBeTruthy();
expect(v).not.toBeFalsy();
expect(() => expect(v).not.toBeTruthy()).toThrow();
expect(() => expect(v).toBeFalsy()).toThrow();
});
}
for (const v of [false, null, NaN, 0, '', undefined]) {
test(`'${String(v)}' is falsy`, () => {
expect(v).toBeFalsy();
expect(v).not.toBeTruthy();
expect(() => expect(v).toBeTruthy()).toThrow();
expect(() => expect(v).not.toBeFalsy()).toThrow();
});
}
});
test.describe('.toBeNaN()', () => {
test('{pass: true}', () => {
for (const v of [NaN, Math.sqrt(-1), Infinity - Infinity, 0 / 0]) {
expect(v).toBeNaN();
expect(() => expect(v).not.toBeNaN()).toThrow();
}
});
test('throws', () => {
for (const v of [1, '', null, undefined, {}, [], 0.2, 0, Infinity, -Infinity]) {
expect(() => expect(v).toBeNaN()).toThrow();
expect(v).not.toBeNaN();
}
});
});
test.describe('.toBeNull()', () => {
for (const v of [{}, [], true, 1, 'a', 0.5, new Map(), () => {}, Infinity]) {
test(`fails for '${String(v)}'`, () => {
expect(v).not.toBeNull();
expect(() => expect(v).toBeNull()).toThrow();
});
}
test('fails for null with .not', () => {
expect(() => expect(null).not.toBeNull()).toThrow();
});
test('pass for null', () => {
expect(null).toBeNull();
});
});
test.describe('.toBeDefined(), .toBeUndefined()', () => {
for (const v of [{}, [], true, 1, 'a', 0.5, new Map(), () => {}, Infinity]) {
test(`'${String(v)}' is defined`, () => {
expect(v).toBeDefined();
expect(v).not.toBeUndefined();
expect(() => expect(v).not.toBeDefined()).toThrow();
expect(() => expect(v).toBeUndefined()).toThrow();
});
}
test('undefined is undefined', () => {
expect(undefined).toBeUndefined();
expect(undefined).not.toBeDefined();
expect(() => expect(undefined).toBeDefined()).toThrow();
expect(() => expect(undefined).not.toBeUndefined()).toThrow();
});
});
test.describe('.toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual()', () => {
for (const [small, big] of [
[1, 2],
[-Infinity, Infinity],
[Number.MIN_VALUE, Number.MAX_VALUE],
[0.1, 0.2],
] as const) {
test(`comparing ${small} and ${big}`, () => {
expect(small).toBeLessThan(big);
expect(big).not.toBeLessThan(small);
expect(big).toBeGreaterThan(small);
expect(small).not.toBeGreaterThan(big);
expect(small).toBeLessThanOrEqual(big);
expect(big).not.toBeLessThanOrEqual(small);
expect(big).toBeGreaterThanOrEqual(small);
expect(small).not.toBeGreaterThanOrEqual(big);
expect(() => expect(small).toBeGreaterThan(big)).toThrow();
expect(() => expect(small).not.toBeLessThan(big)).toThrow();
expect(() => expect(big).not.toBeGreaterThan(small)).toThrow();
expect(() => expect(big).toBeLessThan(small)).toThrow();
expect(() => expect(small).toBeGreaterThanOrEqual(big)).toThrow();
expect(() => expect(small).not.toBeLessThanOrEqual(big)).toThrow();
expect(() => expect(big).not.toBeGreaterThanOrEqual(small)).toThrow();
expect(() => expect(big).toBeLessThanOrEqual(small)).toThrow();
});
}
test('can compare BigInt to Numbers', () => {
const a = BigInt(2);
expect(a).toBeGreaterThan(1);
expect(a).toBeGreaterThanOrEqual(2);
expect(2).toBeLessThanOrEqual(a);
expect(a).toBeLessThan(3);
expect(a).toBeLessThanOrEqual(2);
});
for (const [n1, n2] of [
[1, 1],
[Number.MIN_VALUE, Number.MIN_VALUE],
[Infinity, Infinity],
[-Infinity, -Infinity],
]) {
test(`equal numbers: [${n1}, ${n2}]`, () => {
expect(n1).toBeGreaterThanOrEqual(n2);
expect(n1).toBeLessThanOrEqual(n2);
expect(() => expect(n1).not.toBeGreaterThanOrEqual(n2)).toThrow();
expect(() => expect(n1).not.toBeLessThanOrEqual(n2)).toThrow();
});
}
});
test.describe('.toContain(), .toContainEqual()', () => {
const typedArray = new Int8Array(2);
typedArray[0] = 0;
typedArray[1] = 1;
test('iterable', () => {
const iterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
},
};
expect(iterable).toContain(2);
expect(iterable).toContainEqual(2);
expect(() => expect(iterable).not.toContain(1)).toThrow();
expect(() => expect(iterable).not.toContainEqual(1)).toThrow();
});
for (const [i, [list, v]] of ([
[[1, 2, 3, 4], 1],
[['a', 'b', 'c', 'd'], 'a'],
[[undefined, null], null],
[[undefined, null], undefined],
['abcdef', 'abc'],
['11112111', '2'],
[new Set(['abc', 'def']), 'abc'],
[typedArray, 1],
] as const).entries()) {
test(`contains #${i}`, () => {
expect(list).toContain(v);
expect(() => expect(list).not.toContain(v)).toThrow();
});
}
for (const [i, [list, v]] of ([
[[1, 2, 3], 4],
[[null, undefined], 1],
[[{}, []], []],
[[{}, []], {}],
] as const).entries()) {
test(`does not contain #${i}`, () => {
expect(list).not.toContain(v);
expect(() => expect(list).toContain(v)).toThrow();
});
}
test('error cases', () => {
expect(() => expect(null).toContain(1)).toThrow();
});
for (const [i, [list, v]] of ([
[[1, 2, 3, 4], 1],
[['a', 'b', 'c', 'd'], 'a'],
[[undefined, null], null],
[[{ a: 'b' }, { a: 'c' }], { a: 'b' }],
[new Set([1, 2, 3, 4]), 1],
] as const).entries()) {
test(`contains a value equal #${i}`, () => {
expect(list).toContainEqual(v);
expect(() => expect(list).not.toContainEqual(v)).toThrow();
});
}
test('error cases for toContainEqual', () => {
expect(() => expect(null).toContainEqual(1)).toThrow();
});
});
test.describe('.toBeCloseTo', () => {
for (const [n1, n2] of [
[0, 0],
[0, 0.001],
[1.23, 1.229],
[1.23, 1.226],
[1.23, 1.234],
[Infinity, Infinity],
[-Infinity, -Infinity],
]) {
test(`{pass: true} expect(${n1}).toBeCloseTo(${n2})`, () => {
expect(n1).toBeCloseTo(n2);
expect(() => expect(n1).not.toBeCloseTo(n2)).toThrow();
});
}
for (const [n1, n2] of [
[0, 0.01],
[1, 1.23],
[Infinity, -Infinity],
[Infinity, 1.23],
[-Infinity, -1.23],
]) {
test(`{pass: false} expect(${n1}).toBeCloseTo(${n2})`, () => {
expect(n1).not.toBeCloseTo(n2);
expect(() => expect(n1).toBeCloseTo(n2)).toThrow();
});
}
for (const [n1, n2, p] of [
[0, 0.1, 0],
[0, 0.0001, 3],
[0, 0.000_004, 5],
[2.000_000_2, 2, 5],
]) {
test(`{pass: true} expect(${n1}).toBeCloseTo(${n2}, ${p})`, () => {
expect(n1).toBeCloseTo(n2, p);
expect(() => expect(n1).not.toBeCloseTo(n2, p)).toThrow();
});
}
});
test.describe('.toMatch()', () => {
for (const [n1, n2] of [
['foo', 'foo'],
['Foo bar', /^foo/i],
] as const) {
test(`{pass: true} expect(${n1}).toMatch(${n2})`, () => {
expect(n1).toMatch(n2);
expect(() => expect(n1).not.toMatch(n2)).toThrow();
});
}
for (const [n1, n2] of [
['bar', 'foo'],
['bar', /foo/],
] as const) {
test(`throws: [${n1}, ${n2}]`, () => {
expect(() => expect(n1).toMatch(n2)).toThrow();
});
}
for (const [i, [n1, n2]] of ([
[1, 'foo'],
[{}, 'foo'],
[[], 'foo'],
[true, 'foo'],
[/foo/i, 'foo'],
[() => {}, 'foo'],
[undefined, 'foo'],
] as const).entries()) {
test(`throws if non String actual value passed #${i}`, () => {
expect(() => expect(n1).toMatch(n2)).toThrow();
});
}
for (const [i, [n1, n2]] of ([
['foo', 1],
['foo', {}],
['foo', []],
['foo', true],
['foo', () => {}],
['foo', undefined],
] as const).entries()) {
test(`throws if non String/RegExp expected value passed #${i}`, () => {
expect(() => expect(n1).toMatch(n2 as any)).toThrow();
});
}
test('escapes strings properly', () => {
expect('this?: throws').toMatch('this?: throws');
});
test('does not maintain RegExp state between calls', () => {
const regex = /f\d+/gi;
expect('f123').toMatch(regex);
expect('F456').toMatch(regex);
expect(regex.lastIndex).toBe(0);
});
});
test.describe('.toHaveLength', () => {
for (const [i, [received, length]] of ([
[[1, 2], 2],
[[], 0],
[['a', 'b'], 2],
['abc', 3],
['', 0],
[() => {}, 0],
] as const).entries()) {
test(`{pass: true} toHaveLength(${length}) #${i}`, () => {
expect(received).toHaveLength(length);
expect(() => expect(received).not.toHaveLength(length)).toThrow();
});
}
for (const [i, [received, length]] of ([
[[1, 2], 3],
[[], 1],
[['a', 'b'], 99],
['abc', 66],
['', 1],
] as const).entries()) {
test(`{pass: false} toHaveLength(${length}) #${i}`, () => {
expect(received).not.toHaveLength(length);
expect(() => expect(received).toHaveLength(length)).toThrow();
});
}
test('error cases', () => {
expect(() => expect({ a: 9 }).toHaveLength(1)).toThrow();
expect(() => expect(0).toHaveLength(1)).toThrow();
expect(() => expect(undefined).not.toHaveLength(1)).toThrow();
});
});
test.describe('.toHaveProperty()', () => {
for (const [i, [obj, keyPath, value]] of ([
[{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d', 1],
[{ a: { b: { c: { d: 1 } } } }, ['a', 'b', 'c', 'd'], 1],
[{ 'a.b.c.d': 1 }, ['a.b.c.d'], 1],
[{ a: { b: [1, 2, 3] } }, ['a', 'b', 1], 2],
[{ a: { b: [1, 2, 3] } }, ['a', 'b', 1], expect.any(Number)],
[{ a: 0 }, 'a', 0],
[{ a: { b: undefined } }, 'a.b', undefined],
[{ a: { b: { c: 5 } } }, 'a.b', { c: 5 }],
[{ a: { b: [{ c: [{ d: 1 }] }] } }, 'a.b[0].c[0].d', 1],
[{ '': 1 }, '', 1],
] as const).entries()) {
test(`{pass: true} toHaveProperty with value #${i}`, () => {
expect(obj).toHaveProperty(keyPath as any, value);
expect(() => expect(obj).not.toHaveProperty(keyPath as any, value)).toThrow();
});
}
for (const [i, [obj, keyPath, value]] of ([
[{ a: { b: { c: { d: 1 } } } }, 'a.b.ttt.d', 1],
[{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d', 2],
[{ 'a.b.c.d': 1 }, 'a.b.c.d', 2],
[{ a: { b: { c: {} } } }, 'a.b.c.d', 1],
[{ a: 1 }, 'a.b.c.d', 5],
[{}, 'a', 'test'],
[{ a: { b: 3 } }, 'a.b', undefined],
] as const).entries()) {
test(`{pass: false} toHaveProperty with value #${i}`, () => {
expect(() => expect(obj).toHaveProperty(keyPath, value)).toThrow();
expect(obj).not.toHaveProperty(keyPath, value);
});
}
for (const [i, [obj, keyPath]] of ([
[{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d'],
[{ a: { b: { c: { d: 1 } } } }, ['a', 'b', 'c', 'd']],
[{ 'a.b.c.d': 1 }, ['a.b.c.d']],
[{ a: 0 }, 'a'],
[{ a: { b: undefined } }, 'a.b'],
] as const).entries()) {
test(`{pass: true} toHaveProperty without value #${i}`, () => {
expect(obj).toHaveProperty(keyPath as any);
expect(() => expect(obj).not.toHaveProperty(keyPath as any)).toThrow();
});
}
for (const [i, [obj, keyPath]] of ([
[{ a: { b: { c: {} } } }, 'a.b.c.d'],
[{ a: 1 }, 'a.b.c.d'],
[{}, 'a'],
] as const).entries()) {
test(`{pass: false} toHaveProperty without value #${i}`, () => {
expect(() => expect(obj).toHaveProperty(keyPath)).toThrow();
expect(obj).not.toHaveProperty(keyPath);
});
}
for (const [i, [obj, keyPath]] of ([
[null, 'a.b'],
[undefined, 'a'],
[{ a: { b: {} } }, undefined],
[{ a: { b: {} } }, null],
[{ a: { b: {} } }, 1],
] as const).entries()) {
test(`{error} toHaveProperty #${i}`, () => {
expect(() => expect(obj).toHaveProperty(keyPath as any)).toThrow();
});
}
});
test.describe('.toMatchObject()', () => {
for (const [i, [a, b]] of ([
[{ a: 'b', c: 'd' }, { a: 'b' }],
[{ a: 'b', c: 'd' }, { a: 'b', c: 'd' }],
[{ a: 'b', t: { x: { r: 'r' }, z: 'z' } }, { a: 'b', t: { z: 'z' } }],
[{ a: [3, 4, 5], b: 'b' }, { a: [3, 4, 5] }],
[{ a: 1, c: 2 }, { a: expect.any(Number) }],
[new Set([1, 2]), new Set([1, 2])],
[new Date('2015-11-30'), new Date('2015-11-30')],
[{ a: null, b: 'b' }, { a: null }],
[{ a: undefined, b: 'b' }, { a: undefined }],
[[1, 2], [1, 2]],
[new Error('foo'), new Error('foo')],
[new Error('bar'), { message: 'bar' }],
] as const).entries()) {
test(`{pass: true} toMatchObject #${i}`, () => {
expect(a).toMatchObject(b as any);
expect(() => expect(a).not.toMatchObject(b as any)).toThrow();
});
}
for (const [i, [a, b]] of ([
[{ a: 'b', c: 'd' }, { e: 'b' }],
[{ a: 'b', c: 'd' }, { a: 'b!', c: 'd' }],
[{ a: 'a', c: 'd' }, { a: expect.any(Number) }],
[{ a: [3, 4, 5], b: 'b' }, { a: [3, 4, 5, 6] }],
[[1, 2], [1, 3]],
[new Set([1, 2]), new Set([2])],
[new Error('foo'), new Error('bar')],
] as const).entries()) {
test(`{pass: false} toMatchObject #${i}`, () => {
expect(a).not.toMatchObject(b as any);
expect(() => expect(a).toMatchObject(b as any)).toThrow();
});
}
for (const [i, [a, b]] of ([
[null, {}],
[4, {}],
['44', {}],
[true, {}],
[undefined, {}],
[{}, null],
[{}, 4],
] as const).entries()) {
test(`throws toMatchObject #${i}`, () => {
expect(() => expect(a).toMatchObject(b as any)).toThrow();
});
}
test('does not match properties up in the prototype chain', () => {
const a: any = {};
a.ref = a;
const b = Object.create(a);
b.other = 'child';
const matcher: any = { other: 'child' };
matcher.ref = matcher;
expect(b).not.toMatchObject(matcher);
expect(() => expect(b).toMatchObject(matcher)).toThrow();
});
});
test.describe('.toThrow()', () => {
class CustomError extends Error {}
test('to throw or not to throw', () => {
expect(() => {
throw new CustomError('apple');
}).toThrow();
expect(() => {}).not.toThrow();
});
test('substring passes', () => {
expect(() => {
throw new CustomError('apple');
}).toThrow('apple');
expect(() => {
throw new CustomError('banana');
}).not.toThrow('apple');
expect(() => {}).not.toThrow('apple');
});
test('substring fails when did not throw', () => {
expect(() => expect(() => {}).toThrow('apple')).toThrow();
});
test('substring fails when message did not match', () => {
expect(() => expect(() => {
throw new CustomError('apple');
}).toThrow('banana')).toThrow();
});
test('regexp passes', () => {
expect(() => {
throw new CustomError('apple');
}).toThrow(/apple/);
expect(() => {
throw new CustomError('banana');
}).not.toThrow(/apple/);
expect(() => {}).not.toThrow(/apple/);
});
test('regexp fails when did not throw', () => {
expect(() => expect(() => {}).toThrow(/apple/)).toThrow();
});
test('error class passes', () => {
class Err extends CustomError {}
class Err2 extends CustomError {}
expect(() => {
throw new Err('apple');
}).toThrow(Err);
expect(() => {
throw new Err('apple');
}).toThrow(CustomError);
expect(() => {
throw new Err('apple');
}).not.toThrow(Err2);
});
test('object with message passes', () => {
expect(() => {
throw new CustomError('apple');
}).toThrow({ message: 'apple' });
expect(() => {
throw new CustomError('banana');
}).not.toThrow({ message: 'apple' });
});
test('properly escapes strings when matching against errors', () => {
expect(() => {
throw new TypeError('"this"? throws.');
}).toThrow('"this"? throws.');
});
test('error message and cause properties', () => {
const errorCause = new Error('cause');
const error = new Error('message', { cause: errorCause });
expect(() => {
throw error;
}).toThrow({ message: 'message', cause: errorCause });
});
});
test.describe('asymmetric matchers', () => {
test('Any matches primitives', () => {
expect('jest').toEqual(expect.any(String));
expect(1).toEqual(expect.any(Number));
expect(() => {}).toEqual(expect.any(Function));
expect(true).toEqual(expect.any(Boolean));
expect({}).toEqual(expect.any(Object));
expect([]).toEqual(expect.any(Array));
});
test('Any throws when called with empty constructor', () => {
expect(() => (expect.any as any)()).toThrow(
'any() expects to be passed a constructor function. Please pass one or use anything() to match any object.');
});
test('Anything matches any type', () => {
expect('jest').toEqual(expect.anything());
expect(1).toEqual(expect.anything());
expect(() => {}).toEqual(expect.anything());
expect(true).toEqual(expect.anything());
expect({}).toEqual(expect.anything());
expect([]).toEqual(expect.anything());
});
test('Anything does not match null and undefined', () => {
expect(null).not.toEqual(expect.anything());
expect(undefined).not.toEqual(expect.anything());
});
test('ArrayContaining matches', () => {
expect(['foo']).toEqual(expect.arrayContaining(['foo']));
expect(['foo', 'bar']).toEqual(expect.arrayContaining(['foo']));
});
test('ArrayContaining does not match', () => {
expect(['bar']).not.toEqual(expect.arrayContaining(['foo']));
});
test('ObjectContaining matches', () => {
expect({ foo: 'foo', jest: 'jest' }).toEqual(expect.objectContaining({ foo: 'foo' }));
expect({ foo: undefined }).toEqual(expect.objectContaining({ foo: undefined }));
});
test('ObjectContaining does not match', () => {
expect({ bar: 'bar' }).not.toEqual(expect.objectContaining({ foo: 'foo' }));
expect({ foo: 'foox' }).not.toEqual(expect.objectContaining({ foo: 'foo' }));
expect({}).not.toEqual(expect.objectContaining({ foo: undefined }));
});
test('ObjectContaining throws for non-objects', () => {
expect(() => expect({}).toEqual(expect.objectContaining(1337 as any))).toThrow(
"You must provide an object to ObjectContaining, not 'number'.");
});
test('StringContaining matches string against string', () => {
expect('queen*').toEqual(expect.stringContaining('en*'));
expect('queue').not.toEqual(expect.stringContaining('en*'));
});
test('StringMatching matches string against regexp', () => {
expect('queen').toEqual(expect.stringMatching(/en/));
expect('queue').not.toEqual(expect.stringMatching(/en/));
});
test('StringMatching matches string against string', () => {
expect('queen').toEqual(expect.stringMatching('en'));
expect('queue').not.toEqual(expect.stringMatching('en'));
});
test('closeTo matches', () => {
expect(0).toEqual(expect.closeTo(0));
expect(0.001).toEqual(expect.closeTo(0));
expect(1.229).toEqual(expect.closeTo(1.23));
expect(Infinity).toEqual(expect.closeTo(Infinity));
});
test('closeTo does not match', () => {
expect(0.01).not.toEqual(expect.closeTo(0));
expect(1.23).not.toEqual(expect.closeTo(1));
expect(Infinity).not.toEqual(expect.closeTo(-Infinity));
});
test('closeTo with precision', () => {
expect(0.1).toEqual(expect.closeTo(0, 0));
expect(0.0001).toEqual(expect.closeTo(0, 3));
expect(0.000_004).toEqual(expect.closeTo(0, 5));
});
test('closeTo throws if expected is not number', () => {
expect(() => (expect.closeTo as any)('a')).toThrow('Expected is not a Number');
});
test('arrayOf matches', () => {
expect([1]).toEqual(expect.arrayOf(1));
expect([1, 1, 1]).toEqual(expect.arrayOf(1));
expect([{ a: 1 }, { a: 1 }]).toEqual(expect.arrayOf({ a: 1 }));
expect(['a', 'b', 'c']).toEqual(expect.arrayOf(expect.any(String)));
});
test('arrayOf does not match', () => {
expect([2]).not.toEqual(expect.arrayOf(1));
expect([1, 2]).not.toEqual(expect.arrayOf(1));
expect('not an array').not.toEqual(expect.arrayOf(1));
expect({}).not.toEqual(expect.arrayOf(1));
expect([1, 2]).not.toEqual(expect.arrayOf(expect.any(String)));
});
});