mirror of
https://github.com/pezkuwichain/pezkuwi-dev.git
synced 2026-10-21 19:26:18 +00:00
Merge pull request #19 from pezkuwichain/fix/dev-test-asymmetric-matchers
dev-test: asymmetric matchers in .toEqual; arrayContaining (0.86.5)
This commit is contained in:
9 files changed
+111
-20
No files matched your search
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "0.86.4",
|
||||
"version": "0.86.5",
|
||||
"main": "./index.js",
|
||||
"exports": {
|
||||
"./globals.d.ts": "./src/globals.d.ts"
|
||||
|
||||
+36
@@ -219,4 +219,40 @@ describe('expect', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('asymmetric matchers in .toEqual', () => {
|
||||
it('matches an array containing all expected entries, in any order', () => {
|
||||
expect([1, 2, 3]).toEqual(expect.arrayContaining([3, 1]));
|
||||
expect(['a', 'b']).toEqual(expect.arrayContaining(['b', 'a']));
|
||||
});
|
||||
|
||||
it('fails when an expected entry is missing', () => {
|
||||
expect(() => expect([1, 2]).toEqual(expect.arrayContaining([3]))).toThrow();
|
||||
});
|
||||
|
||||
it('compares array entries deeply', () => {
|
||||
expect([{ a: 1 }, { b: 2 }]).toEqual(expect.arrayContaining([{ b: 2 }]));
|
||||
expect(() => expect([{ a: 1 }]).toEqual(expect.arrayContaining([{ a: 2 }]))).toThrow();
|
||||
});
|
||||
|
||||
it('matches a string containing the expected part', () => {
|
||||
expect('hello world').toEqual(expect.stringContaining('lo w'));
|
||||
expect(() => expect('hello').toEqual(expect.stringContaining('xyz'))).toThrow();
|
||||
});
|
||||
|
||||
it('applies matchers nested in objects and arrays', () => {
|
||||
expect({ a: [1, 2], b: 'x' }).toEqual({ a: expect.arrayContaining([2]), b: 'x' });
|
||||
expect([{ a: 'xyz' }]).toEqual([{ a: expect.stringContaining('y') }]);
|
||||
expect(() => expect({ a: [1], b: 'x' }).toEqual({ a: expect.arrayContaining([2]), b: 'x' })).toThrow();
|
||||
});
|
||||
|
||||
it('still requires equal keys around a nested matcher', () => {
|
||||
expect(() => expect({ a: [1], b: 'x', c: 1 }).toEqual({ a: expect.arrayContaining([1]), b: 'x' })).toThrow();
|
||||
});
|
||||
|
||||
it('supports .not with a matcher', () => {
|
||||
expect([1, 2]).not.toEqual(expect.arrayContaining([3]));
|
||||
expect(() => expect([1, 2]).not.toEqual(expect.arrayContaining([2]))).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
Vendored
+63
-8
@@ -183,15 +183,66 @@ function assertInstanceOf (value: unknown, Clazz: Function): void {
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* A helper to ensure that the supplied string/array does include the checker string.
|
||||
* True when an asymmetric matcher appears anywhere in the expected value
|
||||
*/
|
||||
function containsMatcher (check: unknown): boolean {
|
||||
return check instanceof Matcher ||
|
||||
(Array.isArray(check)
|
||||
? check.some(containsMatcher)
|
||||
: !!check && typeof check === 'object' && Object.values(check).some(containsMatcher));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param {string | unknown[]} value
|
||||
* @param {string} check
|
||||
* Equality as .toEqual has it (deep, loose), with asymmetric matchers
|
||||
* applied wherever they appear in the expected value
|
||||
*/
|
||||
function assertEqualMatch (value: unknown, check: unknown): void {
|
||||
if (check instanceof Matcher) {
|
||||
check.assertMatch(value);
|
||||
} else if (Array.isArray(check)) {
|
||||
assert.ok(Array.isArray(value), `Expected array value, found ${typeof value}`);
|
||||
assert.ok(value.length === check.length, `Expected array with ${check.length} entries, found ${value.length}`);
|
||||
check.forEach((other, i) => assertEqualMatch(value[i], other));
|
||||
} else if (check && typeof check === 'object' && containsMatcher(check)) {
|
||||
assert.ok(value && typeof value === 'object', `Expected object value, found ${typeof value}`);
|
||||
assert.deepEqual(Object.keys(value).sort(), Object.keys(check).sort());
|
||||
Object
|
||||
.entries(check)
|
||||
.forEach(([key, other]) => assertEqualMatch((value as Record<string, unknown>)[key], other));
|
||||
} else {
|
||||
assert.deepEqual(value, check);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* For a string, that it contains the expected substring; for an array, that
|
||||
* every expected entry equals (or matches) one of its entries
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
function assertIncludes (value: string | unknown[], [check, Clazz]: [string, Function]): void {
|
||||
function assertIncludes (value: string | unknown[], [check, Clazz]: [string | unknown[], Function]): void {
|
||||
assertInstanceOf(value, Clazz);
|
||||
assert.ok(value?.includes(check), `${value as string} does not include ${check}`);
|
||||
|
||||
if (Array.isArray(check)) {
|
||||
const entries = value as unknown[];
|
||||
|
||||
check.forEach((other) => {
|
||||
assert.ok(entries.some((entry) => {
|
||||
try {
|
||||
assertEqualMatch(entry, other);
|
||||
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}), `Expected array to contain ${JSON.stringify(other)}`);
|
||||
});
|
||||
} else {
|
||||
assert.ok((value as string).includes(check), `${value as string} does not include ${check}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,7 +255,7 @@ export function expect () {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
any: (Clazz: Function) => new Matcher(assertInstanceOf, Clazz),
|
||||
anything: () => new Matcher(assertNonNullish),
|
||||
arrayContaining: (check: string) => new Matcher(assertIncludes, [check, Array]),
|
||||
arrayContaining: (check: unknown[]) => new Matcher(assertIncludes, [check, Array]),
|
||||
objectContaining: (check: object) => new Matcher(assertMatchObj, check),
|
||||
stringContaining: (check: string) => new Matcher(assertIncludes, [check, String]),
|
||||
stringMatching: (check: string | RegExp) => new Matcher(assertMatchStr, check)
|
||||
@@ -218,7 +269,9 @@ export function expect () {
|
||||
toBeDefined: () => assert.ok(value === undefined),
|
||||
toBeNull: (value: unknown) => assert.ok(value !== null),
|
||||
toBeUndefined: () => assert.ok(value !== undefined),
|
||||
toEqual: (other: unknown) => assert.notDeepEqual(value, other),
|
||||
toEqual: (other: unknown) => containsMatcher(other)
|
||||
? assert.throws(() => assertEqualMatch(value, other))
|
||||
: assert.notDeepEqual(value, other),
|
||||
toHaveBeenCalled: () => assert.ok(!(value as Mocked | undefined)?.mock?.calls.length),
|
||||
toThrow: (message?: RegExp | Error | string) => assert.doesNotThrow(value as () => unknown, message && { message } as Error)
|
||||
}, stubExpectFnNot),
|
||||
@@ -234,7 +287,9 @@ export function expect () {
|
||||
toBeNull: (value: unknown) => assert.ok(value === null),
|
||||
toBeTruthy: () => assert.ok(value),
|
||||
toBeUndefined: () => assert.ok(value === undefined),
|
||||
toEqual: (other: unknown) => assert.deepEqual(value, other),
|
||||
toEqual: (other: unknown) => containsMatcher(other)
|
||||
? assertEqualMatch(value, other)
|
||||
: assert.deepEqual(value, other),
|
||||
toHaveBeenCalled: () => assert.ok((value as Mocked | undefined)?.mock?.calls.length),
|
||||
toHaveBeenCalledTimes: (count: number) => assert.equal((value as Mocked | undefined)?.mock?.calls.length, count),
|
||||
toHaveBeenCalledWith: (...args: unknown[]) => assertSomeCallHasArgs((value as Mocked | undefined), args),
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Do not edit, auto-generated by @pezkuwi/dev
|
||||
|
||||
export const packageInfo = { name: '@pezkuwi/dev-test', path: 'auto', type: 'auto', version: '0.86.4' };
|
||||
export const packageInfo = { name: '@pezkuwi/dev-test', path: 'auto', type: 'auto', version: '0.86.5' };
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "0.86.4",
|
||||
"version": "0.86.5",
|
||||
"main": "./index.js",
|
||||
"exports": {
|
||||
"./globals.d.ts": "./src/globals.d.ts"
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Do not edit, auto-generated by @pezkuwi/dev
|
||||
|
||||
export const packageInfo = { name: '@pezkuwi/dev-ts', path: 'auto', type: 'auto', version: '0.86.4' };
|
||||
export const packageInfo = { name: '@pezkuwi/dev-ts', path: 'auto', type: 'auto', version: '0.86.5' };
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "0.86.4",
|
||||
"version": "0.86.5",
|
||||
"bin": {
|
||||
"pezkuwi-ci-ghact-build": "./scripts/pezkuwi-ci-ghact-build.mjs",
|
||||
"pezkuwi-ci-ghact-docs": "./scripts/pezkuwi-ci-ghact-docs.mjs",
|
||||
@@ -52,8 +52,8 @@
|
||||
"dependencies": {
|
||||
"@eslint/compat": "^2.1.1",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@pezkuwi/dev-test": "^0.86.4",
|
||||
"@pezkuwi/dev-ts": "^0.86.4",
|
||||
"@pezkuwi/dev-test": "^0.86.5",
|
||||
"@pezkuwi/dev-ts": "^0.86.5",
|
||||
"@rollup/plugin-alias": "^5.1.1",
|
||||
"@rollup/plugin-commonjs": "^29.0.3",
|
||||
"@rollup/plugin-dynamic-import-vars": "^2.1.5",
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
// Do not edit, auto-generated by @pezkuwi/dev
|
||||
|
||||
export const packageInfo = { name: '@pezkuwi/dev', path: 'auto', type: 'auto', version: '0.86.4' };
|
||||
export const packageInfo = { name: '@pezkuwi/dev', path: 'auto', type: 'auto', version: '0.86.5' };
|
||||
@@ -1189,7 +1189,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@pezkuwi/dev-test@npm:^0.86.4, @pezkuwi/dev-test@workspace:packages/dev-test":
|
||||
"@pezkuwi/dev-test@npm:^0.86.5, @pezkuwi/dev-test@workspace:packages/dev-test":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@pezkuwi/dev-test@workspace:packages/dev-test"
|
||||
dependencies:
|
||||
@@ -1205,7 +1205,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@pezkuwi/dev-ts@npm:^0.86.4, @pezkuwi/dev-ts@workspace:packages/dev-ts":
|
||||
"@pezkuwi/dev-ts@npm:^0.86.5, @pezkuwi/dev-ts@workspace:packages/dev-ts":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@pezkuwi/dev-ts@workspace:packages/dev-ts"
|
||||
dependencies:
|
||||
@@ -1221,8 +1221,8 @@ __metadata:
|
||||
dependencies:
|
||||
"@eslint/compat": "npm:^2.1.1"
|
||||
"@eslint/js": "npm:^10.0.1"
|
||||
"@pezkuwi/dev-test": "npm:^0.86.4"
|
||||
"@pezkuwi/dev-ts": "npm:^0.86.4"
|
||||
"@pezkuwi/dev-test": "npm:^0.86.5"
|
||||
"@pezkuwi/dev-ts": "npm:^0.86.5"
|
||||
"@rollup/plugin-alias": "npm:^5.1.1"
|
||||
"@rollup/plugin-commonjs": "npm:^29.0.3"
|
||||
"@rollup/plugin-dynamic-import-vars": "npm:^2.1.5"
|
||||
|
||||
Reference in new issue
Block a user