mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-07 07:59:26 +02:00
[Test] Added custom equality matchers (#6157)
* Added rudimentary test matchers for `toEqualArrayUnsorted` and `toHaveTypes` Might port the rest at a later date * Actually run the effing setup matchers file + fixed ls lint to not be angy * added dev dep * Update .ls-lint.yml * Update .ls-lint.yml --------- Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Co-authored-by: Amani H. <109637146+xsn34kzx@users.noreply.github.com>
This commit is contained in:
parent
1b8082a177
commit
f3854abc16
@ -11,14 +11,14 @@ _cfg: &cfg
|
|||||||
|
|
||||||
ls:
|
ls:
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
src:
|
src: &src
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
.dir: kebab-case | regex:@types
|
.dir: kebab-case | regex:@types
|
||||||
.js: exists:0
|
.js: exists:0
|
||||||
src/system/version-migration/versions:
|
src/system/version-migration/versions:
|
||||||
.ts: snake_case
|
.ts: snake_case
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
|
test: *src
|
||||||
ignore:
|
ignore:
|
||||||
- node_modules
|
- node_modules
|
||||||
- .vscode
|
- .vscode
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^22.16.3",
|
"@types/node": "^22.16.3",
|
||||||
"@vitest/coverage-istanbul": "^3.2.4",
|
"@vitest/coverage-istanbul": "^3.2.4",
|
||||||
|
"@vitest/expect": "^3.2.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"dependency-cruiser": "^16.10.4",
|
"dependency-cruiser": "^16.10.4",
|
||||||
"inquirer": "^12.7.0",
|
"inquirer": "^12.7.0",
|
||||||
|
@ -57,6 +57,9 @@ importers:
|
|||||||
'@vitest/coverage-istanbul':
|
'@vitest/coverage-istanbul':
|
||||||
specifier: ^3.2.4
|
specifier: ^3.2.4
|
||||||
version: 3.2.4(vitest@3.2.4(@types/node@22.16.3)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.3)(typescript@5.8.3))(yaml@2.8.0))
|
version: 3.2.4(vitest@3.2.4(@types/node@22.16.3)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.3)(typescript@5.8.3))(yaml@2.8.0))
|
||||||
|
'@vitest/expect':
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4
|
||||||
chalk:
|
chalk:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: 5.4.1
|
version: 5.4.1
|
||||||
|
26
test/@types/vitest.d.ts
vendored
Normal file
26
test/@types/vitest.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { Pokemon } from "#field/pokemon";
|
||||||
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import type { expect } from "vitest";
|
||||||
|
import { toHaveTypesOptions } from "#test/test-utils/matchers/to-have-types";
|
||||||
|
|
||||||
|
declare module "vitest" {
|
||||||
|
interface Assertion {
|
||||||
|
/**
|
||||||
|
* Matcher to check if an array contains EXACTLY the given items (in any order).
|
||||||
|
*
|
||||||
|
* Different from {@linkcode expect.arrayContaining} as the latter only requires the array contain
|
||||||
|
* _at least_ the listed items.
|
||||||
|
*
|
||||||
|
* @param expected - The expected contents of the array, in any order.
|
||||||
|
* @see {@linkcode expect.arrayContaining}
|
||||||
|
*/
|
||||||
|
toEqualArrayUnsorted<E>(expected: E[]): void;
|
||||||
|
/**
|
||||||
|
* Matcher to check if a {@linkcode Pokemon}'s current typing includes the given types.
|
||||||
|
*
|
||||||
|
* @param expected - The expected types (in any order).
|
||||||
|
* @param options - The options passed to the matcher.
|
||||||
|
*/
|
||||||
|
toHaveTypes(expected: PokemonType[], options?: toHaveTypesOptions): void;
|
||||||
|
}
|
||||||
|
}
|
14
test/matchers.setup.ts
Normal file
14
test/matchers.setup.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { toEqualArrayUnsorted } from "#test/test-utils/matchers/to-equal-array-unsorted";
|
||||||
|
import { toHaveTypes } from "#test/test-utils/matchers/to-have-types";
|
||||||
|
import { expect } from "vitest";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module
|
||||||
|
* Setup file for custom matchers.
|
||||||
|
* Make sure to define the call signatures in `test/@types/vitest.d.ts` too!
|
||||||
|
*/
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
toEqualArrayUnsorted,
|
||||||
|
toHaveTypes,
|
||||||
|
});
|
43
test/test-utils/matchers/to-equal-array-unsorted.ts
Normal file
43
test/test-utils/matchers/to-equal-array-unsorted.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matcher to check if an array contains exactly the given items, disregarding order.
|
||||||
|
* @param received - The object to check. Should be an array of elements.
|
||||||
|
* @returns The result of the matching
|
||||||
|
*/
|
||||||
|
export function toEqualArrayUnsorted(this: MatcherState, received: unknown, expected: unknown): SyncExpectationResult {
|
||||||
|
if (!Array.isArray(received)) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected an array, but got ${this.utils.stringify(received)}!`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(expected)) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected to recieve an array, but got ${this.utils.stringify(expected)}!`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (received.length !== expected.length) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected to recieve array of length ${received.length}, but got ${expected.length}!`,
|
||||||
|
actual: received,
|
||||||
|
expected,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const gotSorted = received.slice().sort();
|
||||||
|
const wantSorted = expected.slice().sort();
|
||||||
|
const pass = this.equals(gotSorted, wantSorted, [...this.customTesters, this.utils.iterableEquality]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pass: this.isNot !== pass,
|
||||||
|
message: () =>
|
||||||
|
`Expected ${this.utils.stringify(received)} to exactly equal ${this.utils.stringify(expected)} without order!`,
|
||||||
|
actual: gotSorted,
|
||||||
|
expected: wantSorted,
|
||||||
|
};
|
||||||
|
}
|
64
test/test-utils/matchers/to-have-types.ts
Normal file
64
test/test-utils/matchers/to-have-types.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import { Pokemon } from "#field/pokemon";
|
||||||
|
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
||||||
|
|
||||||
|
export interface toHaveTypesOptions {
|
||||||
|
/**
|
||||||
|
* Whether to enforce exact matches (`true`) or superset matches (`false`).
|
||||||
|
* @defaultValue `true`
|
||||||
|
*/
|
||||||
|
exact?: boolean;
|
||||||
|
/**
|
||||||
|
* Optional arguments to pass to {@linkcode Pokemon.getTypes}.
|
||||||
|
*/
|
||||||
|
args?: Parameters<(typeof Pokemon.prototype)["getTypes"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matcher to check if an array contains exactly the given items, disregarding order.
|
||||||
|
* @param received - The object to check. Should be an array of one or more {@linkcode PokemonType}s.
|
||||||
|
* @param options - The {@linkcode toHaveTypesOptions | options} for this matcher
|
||||||
|
* @returns The result of the matching
|
||||||
|
*/
|
||||||
|
export function toHaveTypes(
|
||||||
|
this: MatcherState,
|
||||||
|
received: unknown,
|
||||||
|
expected: unknown,
|
||||||
|
options: toHaveTypesOptions = {},
|
||||||
|
): SyncExpectationResult {
|
||||||
|
if (!(received instanceof Pokemon)) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected a Pokemon, but got ${this.utils.stringify(received)}!`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(expected) || expected.length === 0) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected to recieve an array with length >=1, but got ${this.utils.stringify(expected)}!`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expected.every((t): t is PokemonType => t in PokemonType)) {
|
||||||
|
return {
|
||||||
|
pass: this.isNot,
|
||||||
|
message: () => `Expected to recieve array of PokemonTypes but got ${this.utils.stringify(expected)}!`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const gotSorted = pkmnTypeToStr(received.getTypes(...(options.args ?? [])));
|
||||||
|
const wantSorted = pkmnTypeToStr(expected.slice());
|
||||||
|
const pass = this.equals(gotSorted, wantSorted, [...this.customTesters, this.utils.iterableEquality]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pass: this.isNot !== pass,
|
||||||
|
message: () => `Expected ${received.name} to have types ${this.utils.stringify(wantSorted)}, but got ${gotSorted}!`,
|
||||||
|
actual: gotSorted,
|
||||||
|
expected: wantSorted,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function pkmnTypeToStr(p: PokemonType[]): string[] {
|
||||||
|
return p.sort().map(type => PokemonType[type]);
|
||||||
|
}
|
@ -9,7 +9,7 @@ export default defineProject(({ mode }) => ({
|
|||||||
TZ: "UTC",
|
TZ: "UTC",
|
||||||
},
|
},
|
||||||
testTimeout: 20000,
|
testTimeout: 20000,
|
||||||
setupFiles: ["./test/font-face.setup.ts", "./test/vitest.setup.ts"],
|
setupFiles: ["./test/font-face.setup.ts", "./test/vitest.setup.ts", "./test/matchers.setup.ts"],
|
||||||
sequence: {
|
sequence: {
|
||||||
sequencer: MySequencer,
|
sequencer: MySequencer,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user