Added toHaveKey matcher + fixed imports

This commit is contained in:
Bertie690 2025-09-15 17:35:28 -04:00 committed by Sirz Benjie
parent 207808f37d
commit abe6dc4483
No known key found for this signature in database
GPG Key ID: 4A524B4D196C759E
4 changed files with 73 additions and 10 deletions

View File

@ -1,7 +1,7 @@
import "vitest";
import type { Phase } from "#app/phase";
import type Overrides from "#app/overrides";
import type { Phase } from "#app/phase";
import type { ArenaTag } from "#data/arena-tag";
import type { TerrainType } from "#data/terrain";
import type { AbilityId } from "#enums/ability-id";
@ -14,6 +14,7 @@ import type { PositionalTagType } from "#enums/positional-tag-type";
import type { BattleStat, EffectiveStat } from "#enums/stat";
import type { WeatherType } from "#enums/weather-type";
import type { toHaveArenaTagOptions } from "#test/test-utils/matchers/to-have-arena-tag";
import type { toHaveBattlerTagOptions } from "#test/test-utils/matchers/to-have-battler-tag";
import type { toHaveEffectiveStatOptions } from "#test/test-utils/matchers/to-have-effective-stat";
import type { toHavePositionalTagOptions } from "#test/test-utils/matchers/to-have-positional-tag";
import type { expectedStatusType } from "#test/test-utils/matchers/to-have-status-effect";
@ -23,7 +24,6 @@ import type { TurnMove } from "#types/turn-move";
import type { AtLeastOne } from "#types/type-helpers";
import type { toDmgValue } from "#utils/common";
import type { expect } from "vitest";
import type { toHaveBattlerTagOptions } from "#test/test-utils/matchers/to-have-battler-tag";
declare module "vitest" {
interface Assertion<T> {
@ -40,17 +40,33 @@ declare module "vitest" {
*/
toEqualArrayUnsorted(expected: T[]): void;
/**
* Check whether a {@linkcode Map} contains the given key, disregarding its value.
* @param expectedKey - The key whose inclusion is being checked
* @privateRemarks
* While this functionality _could_ be simulated by writing
* `expect(x.get(y)).toBeDefined()` or
* `expect(x).toContain[y, expect.anything()]`,
* this is still preferred due to being more ergonomic and provides better error messsages.
*/
toHaveKey<E>(expectedKey: E): void;
// #endregion Generic Matchers
// #region GameManager Matchers
/**
* Check if the {@linkcode GameManager} has shown the given message at least once in the current battle.
* @param expectedMessage - The expected message
* Check if the {@linkcode GameManager} has shown the given message at least once in the current test case.
* @param expectedMessage - The expected message to be displayed
* @remarks
* Strings consumed by this function should _always_ be produced by a call to `i18n.t`
* to avoid hardcoding text into test files.
*/
toHaveShownMessage(expectedMessage: string): void;
/**
* @param expectedPhase - The expected {@linkcode PhaseString}
* Check if the currently-running {@linkcode Phase} is of the given type.
* @param expectedPhase - The expected {@linkcode PhaseString | name of the phase}
*/
toBeAtPhase(expectedPhase: PhaseString): void;
// #endregion GameManager Matchers

View File

@ -7,6 +7,7 @@ import { toHaveEffectiveStat } from "#test/test-utils/matchers/to-have-effective
import { toHaveFainted } from "#test/test-utils/matchers/to-have-fainted";
import { toHaveFullHp } from "#test/test-utils/matchers/to-have-full-hp";
import { toHaveHp } from "#test/test-utils/matchers/to-have-hp";
import { toHaveKey } from "#test/test-utils/matchers/to-have-key";
import { toHavePositionalTag } from "#test/test-utils/matchers/to-have-positional-tag";
import { toHaveShownMessage } from "#test/test-utils/matchers/to-have-shown-message";
import { toHaveStatStage } from "#test/test-utils/matchers/to-have-stat-stage";
@ -19,13 +20,15 @@ import { toHaveUsedPP } from "#test/test-utils/matchers/to-have-used-pp";
import { toHaveWeather } from "#test/test-utils/matchers/to-have-weather";
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,
toHaveKey,
toHaveShownMessage,
toBeAtPhase,
toHaveWeather,

View File

@ -40,10 +40,7 @@ export class ModifierHelper extends GameManagerHelper {
* @returns `this`
*/
testCheck(modifier: ModifierTypeKeys, expectToBePreset: boolean): this {
if (expectToBePreset) {
expect(itemPoolChecks.get(modifier)).toBeTruthy();
}
expect(itemPoolChecks.get(modifier)).toBeFalsy();
(expectToBePreset ? expect(itemPoolChecks) : expect(itemPoolChecks).not).toHaveKey(modifier);
return this;
}

View File

@ -0,0 +1,47 @@
import { getOnelineDiffStr } from "#test/test-utils/string-utils";
import { receivedStr } from "#test/test-utils/test-utils";
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
/**
* Matcher that checks if a {@linkcode Map} contains the given key, regardless of its value.
* @param received - The received value. Should be a Map
* @param expectedKey - The key whose inclusion in the map is being checked
* @returns Whether the matcher passed
*/
export function toHaveKey(this: MatcherState, received: unknown, expectedKey: unknown): SyncExpectationResult {
if (!(received instanceof Map)) {
return {
pass: this.isNot,
message: () => `Expected to receive a Map, but got ${receivedStr(received)}!`,
};
}
if (received.size === 0) {
return {
pass: false,
message: () => "Expected to receive a non-empty Map, but received map was empty!",
expected: expectedKey,
actual: received,
};
}
const keys = [...received.values()];
const pass = this.equals(keys, expectedKey, [
...this.customTesters,
this.utils.iterableEquality,
this.utils.subsetEquality,
]);
const actualStr = getOnelineDiffStr.call(this, received);
const expectedStr = getOnelineDiffStr.call(this, expectedKey);
return {
pass,
message: () =>
pass
? `Expected ${actualStr} to NOT have the key ${expectedStr}, but it did!`
: `Expected ${actualStr} to have the key ${expectedStr}, but it didn't!`,
expected: expectedKey,
actual: keys,
};
}