From df8d1dc8c7de2e50604505ea5a2eb861a3fccc16 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Sun, 3 Aug 2025 16:13:10 -0400 Subject: [PATCH] More semantic changes --- test/@types/vitest.d.ts | 47 +++++++------------ .../matchers/to-have-ability-applied.ts | 2 +- test/test-utils/matchers/to-have-arena-tag.ts | 4 +- .../matchers/to-have-effective-stat.ts | 2 +- test/test-utils/matchers/to-have-fainted.ts | 2 +- test/test-utils/matchers/to-have-full-hp.ts | 2 +- test/test-utils/matchers/to-have-hp.ts | 2 +- .../test-utils/matchers/to-have-stat-stage.ts | 4 +- .../matchers/to-have-status-effect.ts | 2 +- .../matchers/to-have-taken-damage.ts | 2 +- test/test-utils/matchers/to-have-terrain.ts | 4 +- test/test-utils/matchers/to-have-types.ts | 26 ++++++---- test/test-utils/matchers/to-have-used-move.ts | 14 +++--- test/test-utils/matchers/to-have-used-pp.ts | 10 ++-- test/test-utils/string-utils.ts | 6 ++- 15 files changed, 64 insertions(+), 65 deletions(-) diff --git a/test/@types/vitest.d.ts b/test/@types/vitest.d.ts index 4af28bb6414..086675da78d 100644 --- a/test/@types/vitest.d.ts +++ b/test/@types/vitest.d.ts @@ -24,7 +24,7 @@ import type { PokemonMove } from "#moves/pokemon-move"; import type { OneOther } from "#test/@types/test-helpers"; declare module "vitest" { - interface Assertion { + interface Assertion { /** * Check whether an array contains EXACTLY the given items (in any order). * @@ -34,38 +34,28 @@ declare module "vitest" { * @param expected - The expected contents of the array, in any order * @see {@linkcode expect.arrayContaining} */ - toEqualArrayUnsorted(expected: E[]): void; + toEqualArrayUnsorted(expected: T[]): void; /** * Check whether a {@linkcode Pokemon}'s current typing includes the given types. - * - * @param expected - The expected types (in any order) + * @param expectedTypes - The expected {@linkcode PokemonType}s to check against; must have length `>0` * @param options - The {@linkcode toHaveTypesOptions | options} passed to the matcher */ - toHaveTypes(expected: [PokemonType, ...PokemonType[]], options?: toHaveTypesOptions): void; - /** - * Check whether a {@linkcode Pokemon}'s current typing includes the given types. - * - * @param expected - The expected types (in any order) - * @param options - The {@linkcode toHaveTypesOptions | options} passed to the matcher - */ - toHaveTypes(expected: PokemonType[], options?: toHaveTypesOptions): void; + toHaveTypes(expectedTypes: PokemonType[], options?: toHaveTypesOptions): void; /** - * Matcher to check the contents of a {@linkcode Pokemon}'s move history. - * - * @param expectedValue - The expected value; can be a {@linkcode MoveId} or a partially filled {@linkcode TurnMove} - * containing the desired properties to check + * Check whether a {@linkcode Pokemon} has used a move matching the given criteria. + * @param expectedMove - The {@linkcode MoveId} the Pokemon is expected to have used, + * or a partially filled {@linkcode TurnMove} containing the desired properties to check * @param index - The index of the move history entry to check, in order from most recent to least recent. * Default `0` (last used move) * @see {@linkcode Pokemon.getLastXMoves} */ - toHaveUsedMove(expected: MoveId | AtLeastOne, index?: number): void; + toHaveUsedMove(expectedMove: MoveId | AtLeastOne, index?: number): void; /** * Check whether a {@linkcode Pokemon}'s effective stat is as expected * (checked after all stat value modifications). - * * @param stat - The {@linkcode EffectiveStat} to check * @param expectedValue - The expected value of {@linkcode stat} * @param options - The {@linkcode toHaveEffectiveStatOptions | options} passed to the matcher @@ -95,15 +85,13 @@ declare module "vitest" { /** * Check whether the current {@linkcode Arena} contains the given {@linkcode ArenaTag}. - * - * @param expectedType - A partially-filled {@linkcode ArenaTag} containing the desired properties + * @param expectedTag - A partially-filled {@linkcode ArenaTag} containing the desired properties */ toHaveArenaTag( - expectedType: OneOther & { tagType: T }, // intersection required to preserve T + expectedTag: OneOther & { tagType: T }, // intersection required to preserve T ): void; /** * Check whether the current {@linkcode Arena} contains the given {@linkcode ArenaTag}. - * * @param expectedType - The {@linkcode ArenaTagType} of the desired tag * @param side - The {@linkcode ArenaTagSide | side of the field} the tag should affect, or * {@linkcode ArenaTagSide.BOTH} to check both sides; @@ -138,7 +126,7 @@ declare module "vitest" { /** * Check whether a {@linkcode Pokemon} has applied a specific {@linkcode AbilityId}. - * @param expectedAbilityId - The expected {@linkcode AbilityId} + * @param expectedAbilityId - The expected {@linkcode AbilityId} to */ toHaveAbilityApplied(expectedAbilityId: AbilityId): void; @@ -151,21 +139,20 @@ declare module "vitest" { /** * Check whether a {@linkcode Pokemon} is currently fainted (as determined by {@linkcode Pokemon.isFainted}). * @remarks - * When checking whether an enemy wild Pokemon is fainted, one must reference it in a variable _before_ the fainting effect occurs - * as otherwise the Pokemon will be GC'ed and rendered `undefined`. + * When checking whether an enemy wild Pokemon is fainted, one must store a reference to it in a variable _before_ the fainting effect occurs, + * as otherwise the Pokemon will be removed from the field and garbage collected. */ toHaveFainted(): void; /** * Check whether a {@linkcode Pokemon} has consumed the given amount of PP for one of its moves. - * @param expectedValue - The {@linkcode MoveId} of the {@linkcode PokemonMove} that should have consumed PP + * @param moveId - The {@linkcode MoveId} of the {@linkcode PokemonMove} that should have consumed PP * @param ppUsed - The numerical amount of PP that should have been consumed, * or `all` to indicate the move should be _out_ of PP * @remarks - * If the Pokemon's moveset has been set via {@linkcode Overrides.MOVESET_OVERRIDE}/{@linkcode Overrides.OPP_MOVESET_OVERRIDE}, - * does not contain {@linkcode expectedMove} - * or contains the desired move more than once, this will fail the test. + * If the Pokemon's moveset has been set via {@linkcode Overrides.MOVESET_OVERRIDE}/{@linkcode Overrides.OPP_MOVESET_OVERRIDE} + * or does not contain exactly 1 copy of {@linkcode moveId}, this will fail the test. */ - toHaveUsedPP(expectedMove: MoveId, ppUsed: number | "all"): void; + toHaveUsedPP(moveId: MoveId, ppUsed: number | "all"): void; } } diff --git a/test/test-utils/matchers/to-have-ability-applied.ts b/test/test-utils/matchers/to-have-ability-applied.ts index a3921e6371c..8ef343c6d74 100644 --- a/test/test-utils/matchers/to-have-ability-applied.ts +++ b/test/test-utils/matchers/to-have-ability-applied.ts @@ -21,7 +21,7 @@ export function toHaveAbilityApplied( ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to recieve a Pokemon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-arena-tag.ts b/test/test-utils/matchers/to-have-arena-tag.ts index 425eb046a4e..1aba0009465 100644 --- a/test/test-utils/matchers/to-have-arena-tag.ts +++ b/test/test-utils/matchers/to-have-arena-tag.ts @@ -36,8 +36,8 @@ export function toHaveArenaTag( if (!received.scene?.arena) { return { - pass: false, - message: () => `Expected GameManager.${!received.scene ? "scene" : "scene.arena"} to be defined!`, + pass: this.isNot, + message: () => `Expected GameManager.${received.scene ? "scene.arena" : "scene"} to be defined!`, }; } diff --git a/test/test-utils/matchers/to-have-effective-stat.ts b/test/test-utils/matchers/to-have-effective-stat.ts index fba285e49e7..dda6bc7e91e 100644 --- a/test/test-utils/matchers/to-have-effective-stat.ts +++ b/test/test-utils/matchers/to-have-effective-stat.ts @@ -42,7 +42,7 @@ export function toHaveEffectiveStat( ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-fainted.ts b/test/test-utils/matchers/to-have-fainted.ts index 73ca96a31b5..f3e84e7a425 100644 --- a/test/test-utils/matchers/to-have-fainted.ts +++ b/test/test-utils/matchers/to-have-fainted.ts @@ -12,7 +12,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; export function toHaveFainted(this: MatcherState, received: unknown): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-full-hp.ts b/test/test-utils/matchers/to-have-full-hp.ts index 3d7c8f9458d..893bb647283 100644 --- a/test/test-utils/matchers/to-have-full-hp.ts +++ b/test/test-utils/matchers/to-have-full-hp.ts @@ -12,7 +12,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; export function toHaveFullHp(this: MatcherState, received: unknown): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-hp.ts b/test/test-utils/matchers/to-have-hp.ts index 20d171b23ce..e6463383ac2 100644 --- a/test/test-utils/matchers/to-have-hp.ts +++ b/test/test-utils/matchers/to-have-hp.ts @@ -13,7 +13,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; export function toHaveHp(this: MatcherState, received: unknown, expectedHp: number): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-stat-stage.ts b/test/test-utils/matchers/to-have-stat-stage.ts index feecd650bef..a9ae910aece 100644 --- a/test/test-utils/matchers/to-have-stat-stage.ts +++ b/test/test-utils/matchers/to-have-stat-stage.ts @@ -23,14 +23,14 @@ export function toHaveStatStage( ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } if (expectedStage < -6 || expectedStage > 6) { return { - pass: false, + pass: this.isNot, message: () => `Expected ${expectedStage} to be within the range [-6, 6]!`, }; } diff --git a/test/test-utils/matchers/to-have-status-effect.ts b/test/test-utils/matchers/to-have-status-effect.ts index 9bcc0b5097f..fa5f0346ebd 100644 --- a/test/test-utils/matchers/to-have-status-effect.ts +++ b/test/test-utils/matchers/to-have-status-effect.ts @@ -28,7 +28,7 @@ export function toHaveStatusEffect( ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-taken-damage.ts b/test/test-utils/matchers/to-have-taken-damage.ts index 77c60ae836a..55c163a2dc7 100644 --- a/test/test-utils/matchers/to-have-taken-damage.ts +++ b/test/test-utils/matchers/to-have-taken-damage.ts @@ -24,7 +24,7 @@ export function toHaveTakenDamage( ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a Pokémon, but got ${receivedStr(received)}!`, }; } diff --git a/test/test-utils/matchers/to-have-terrain.ts b/test/test-utils/matchers/to-have-terrain.ts index 29a56ceb23b..438d72bc957 100644 --- a/test/test-utils/matchers/to-have-terrain.ts +++ b/test/test-utils/matchers/to-have-terrain.ts @@ -20,14 +20,14 @@ export function toHaveTerrain( ): SyncExpectationResult { if (!isGameManagerInstance(received)) { return { - pass: false, + pass: this.isNot, message: () => `Expected to receive a GameManager, but got ${receivedStr(received)}!`, }; } if (!received.scene?.arena) { return { - pass: false, + pass: this.isNot, message: () => `Expected GameManager.${received.scene ? "scene.arena" : "scene"} to be defined!`, }; } diff --git a/test/test-utils/matchers/to-have-types.ts b/test/test-utils/matchers/to-have-types.ts index e7aab8e7d94..d4ced6185ac 100644 --- a/test/test-utils/matchers/to-have-types.ts +++ b/test/test-utils/matchers/to-have-types.ts @@ -26,14 +26,14 @@ export interface toHaveTypesOptions { /** * Matcher that checks if a {@linkcode Pokemon}'s typing is as expected. * @param received - The object to check. Should be a {@linkcode Pokemon} - * @param expected - An array of one or more {@linkcode PokemonType}s to compare against. + * @param expectedTypes - An array of one or more {@linkcode PokemonType}s to compare against. * @param mode - The mode to perform the matching; * @returns The result of the matching */ export function toHaveTypes( this: MatcherState, received: unknown, - expected: [PokemonType, ...PokemonType[]], + expectedTypes: [PokemonType, ...PokemonType[]], { mode = "unordered", args = [] }: toHaveTypesOptions = {}, ): SyncExpectationResult { if (!isPokemonInstance(received)) { @@ -43,19 +43,27 @@ export function toHaveTypes( }; } + // Return early if no types were passed in + if (expectedTypes.length === 0) { + return { + pass: this.isNot, + message: () => "Expected to recieve a non-empty array of PokemonTypes, but got one!", + }; + } + // Avoid sorting the types if strict ordering is desired - const actualTypes = mode === "ordered" ? received.getTypes(...args) : received.getTypes(...args).toSorted(); - const expectedTypes = mode === "ordered" ? expected : expected.toSorted(); + const actualSorted = mode === "ordered" ? received.getTypes(...args) : received.getTypes(...args).toSorted(); + const expectedSorted = mode === "ordered" ? expectedTypes : expectedTypes.toSorted(); // Exact matches do not care about subset equality const matchers = mode === "superset" ? [...this.customTesters, this.utils.iterableEquality] : [...this.customTesters, this.utils.subsetEquality, this.utils.iterableEquality]; - const pass = this.equals(actualTypes, expectedTypes, matchers); + const pass = this.equals(actualSorted, expectedSorted, matchers); - const actualStr = stringifyEnumArray(PokemonType, actualTypes); - const expectedStr = stringifyEnumArray(PokemonType, expectedTypes); + const actualStr = stringifyEnumArray(PokemonType, actualSorted); + const expectedStr = stringifyEnumArray(PokemonType, expectedSorted); const pkmName = getPokemonNameWithAffix(received); return { @@ -64,7 +72,7 @@ export function toHaveTypes( pass ? `Expected ${pkmName} to NOT have types ${expectedStr}, but it did!` : `Expected ${pkmName} to have types ${expectedStr}, but got ${actualStr} instead!`, - expected: expectedTypes, - actual: actualTypes, + expected: expectedSorted, + actual: actualSorted, }; } diff --git a/test/test-utils/matchers/to-have-used-move.ts b/test/test-utils/matchers/to-have-used-move.ts index 3a3008fdf50..3697b3e0bc6 100644 --- a/test/test-utils/matchers/to-have-used-move.ts +++ b/test/test-utils/matchers/to-have-used-move.ts @@ -13,7 +13,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; /** * Matcher to check the contents of a {@linkcode Pokemon}'s move history. * @param received - The actual value received. Should be a {@linkcode Pokemon} - * @param expectedValue - The {@linkcode MoveId} the Pokemon is expected to have used, + * @param expectedMove - The {@linkcode MoveId} the Pokemon is expected to have used, * or a partially filled {@linkcode TurnMove} containing the desired properties to check * @param index - The index of the move history entry to check, in order from most recent to least recent. * Default `0` (last used move) @@ -22,7 +22,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; export function toHaveUsedMove( this: MatcherState, received: unknown, - expectedResult: MoveId | AtLeastOne, + expectedMove: MoveId | AtLeastOne, index = 0, ): SyncExpectationResult { if (!isPokemonInstance(received)) { @@ -44,26 +44,26 @@ export function toHaveUsedMove( } // Coerce to a `TurnMove` - if (typeof expectedResult === "number") { - expectedResult = { move: expectedResult }; + if (typeof expectedMove === "number") { + expectedMove = { move: expectedMove }; } const moveIndexStr = index === 0 ? "last move" : `${getOrdinal(index)} most recent move`; - const pass = this.equals(move, expectedResult, [ + const pass = this.equals(move, expectedMove, [ ...this.customTesters, this.utils.subsetEquality, this.utils.iterableEquality, ]); - const expectedStr = getOnelineDiffStr.call(this, expectedResult); + const expectedStr = getOnelineDiffStr.call(this, expectedMove); return { pass, message: () => pass ? `Expected ${pkmName}'s ${moveIndexStr} to NOT match ${expectedStr}, but it did!` : `Expected ${pkmName}'s ${moveIndexStr} to match ${expectedStr}, but it didn't!`, - expected: expectedResult, + expected: expectedMove, actual: move, }; } diff --git a/test/test-utils/matchers/to-have-used-pp.ts b/test/test-utils/matchers/to-have-used-pp.ts index ce7f5b5ea23..269d97c6ee2 100644 --- a/test/test-utils/matchers/to-have-used-pp.ts +++ b/test/test-utils/matchers/to-have-used-pp.ts @@ -13,7 +13,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; /** * Matcher to check the amount of PP consumed by a {@linkcode Pokemon}. * @param received - The actual value received. Should be a {@linkcode Pokemon} - * @param expectedValue - The {@linkcode MoveId} that should have consumed PP + * @param moveId - The {@linkcode MoveId} that should have consumed PP * @param ppUsed - The numerical amount of PP that should have been consumed, * or `all` to indicate the move should be _out_ of PP * @returns Whether the matcher passed @@ -23,7 +23,7 @@ import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; export function toHaveUsedPP( this: MatcherState, received: unknown, - expectedMove: MoveId, + moveId: MoveId, ppUsed: number | "all", ): SyncExpectationResult { if (!isPokemonInstance(received)) { @@ -43,15 +43,15 @@ export function toHaveUsedPP( } const pkmName = getPokemonNameWithAffix(received); - const moveStr = getEnumStr(MoveId, expectedMove); + const moveStr = getEnumStr(MoveId, moveId); - const movesetMoves = received.getMoveset().filter(pm => pm.moveId === expectedMove); + const movesetMoves = received.getMoveset().filter(pm => pm.moveId === moveId); if (movesetMoves.length !== 1) { return { pass: this.isNot, message: () => `Expected MoveId.${moveStr} to appear in ${pkmName}'s moveset exactly once, but got ${movesetMoves.length} times!`, - expected: expectedMove, + expected: moveId, actual: received.getMoveset(), }; } diff --git a/test/test-utils/string-utils.ts b/test/test-utils/string-utils.ts index bd3dd7c2fa9..c997356fbd6 100644 --- a/test/test-utils/string-utils.ts +++ b/test/test-utils/string-utils.ts @@ -174,10 +174,14 @@ export function getStatName(s: Stat): string { * Convert an object into a oneline diff to be shown in an error message. * @param obj - The object to return the oneline diff of * @returns The updated diff + * @example + * ```ts + * const diff = getOnelineDiffStr.call(this, obj) + * ``` */ export function getOnelineDiffStr(this: MatcherState, obj: unknown): string { return this.utils .stringify(obj, undefined, { maxLength: 35, indent: 0, printBasicPrototype: false }) .replace(/\n/g, " ") // Replace newlines with spaces - .replace(/,(\s*)}$/g, "$1}"); + .replace(/,(\s*)}$/g, "$1}"); // Trim trailing commas }