Tests verify the get→call→save wiring and error propagation for each use case. The 15 formulaic use cases share a test file; rollInitiative and rollAllInitiative have dedicated suites covering their multi-step logic (creature lookup, modifier calculation, iteration, early return). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
import type { Encounter, PlayerCharacter } from "@initiative/domain";
|
|
import { isDomainError } from "@initiative/domain";
|
|
import type { EncounterStore, PlayerCharacterStore } from "../ports.js";
|
|
|
|
export function requireSaved<T>(value: T | null): T {
|
|
if (value === null) throw new Error("Expected store.saved to be non-null");
|
|
return value;
|
|
}
|
|
|
|
export function expectSuccess<T>(
|
|
result: T,
|
|
): asserts result is Exclude<T, { kind: "domain-error" }> {
|
|
if (isDomainError(result)) {
|
|
throw new Error(`Expected success, got domain error: ${result.message}`);
|
|
}
|
|
}
|
|
|
|
export function expectError(result: unknown): asserts result is {
|
|
kind: "domain-error";
|
|
code: string;
|
|
message: string;
|
|
} {
|
|
if (!isDomainError(result)) {
|
|
throw new Error("Expected domain error");
|
|
}
|
|
}
|
|
|
|
export function stubEncounterStore(
|
|
initial: Encounter,
|
|
): EncounterStore & { saved: Encounter | null } {
|
|
const stub = {
|
|
saved: null as Encounter | null,
|
|
get: () => initial,
|
|
save: (e: Encounter) => {
|
|
stub.saved = e;
|
|
stub.get = () => e;
|
|
},
|
|
};
|
|
return stub;
|
|
}
|
|
|
|
export function stubPlayerCharacterStore(
|
|
initial: readonly PlayerCharacter[],
|
|
): PlayerCharacterStore & { saved: readonly PlayerCharacter[] | null } {
|
|
const stub = {
|
|
saved: null as readonly PlayerCharacter[] | null,
|
|
getAll: () => [...initial],
|
|
save: (characters: PlayerCharacter[]) => {
|
|
stub.saved = characters;
|
|
stub.getAll = () => [...characters];
|
|
},
|
|
};
|
|
return stub;
|
|
}
|