mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 07:29:30 +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:
|
||||
<<: *cfg
|
||||
src:
|
||||
src: &src
|
||||
<<: *cfg
|
||||
.dir: kebab-case | regex:@types
|
||||
.js: exists:0
|
||||
src/system/version-migration/versions:
|
||||
.ts: snake_case
|
||||
<<: *cfg
|
||||
|
||||
test: *src
|
||||
ignore:
|
||||
- node_modules
|
||||
- .vscode
|
||||
|
@ -32,6 +32,7 @@
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^22.16.3",
|
||||
"@vitest/coverage-istanbul": "^3.2.4",
|
||||
"@vitest/expect": "^3.2.4",
|
||||
"chalk": "^5.4.1",
|
||||
"dependency-cruiser": "^16.10.4",
|
||||
"inquirer": "^12.7.0",
|
||||
|
@ -57,6 +57,9 @@ importers:
|
||||
'@vitest/coverage-istanbul':
|
||||
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))
|
||||
'@vitest/expect':
|
||||
specifier: ^3.2.4
|
||||
version: 3.2.4
|
||||
chalk:
|
||||
specifier: ^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",
|
||||
},
|
||||
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: {
|
||||
sequencer: MySequencer,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user