Introduce adapter injection and migrate test suite
Replace direct adapter/persistence imports with context-based injection (AdapterContext + useAdapters) so tests use in-memory implementations instead of vi.mock. Migrate component tests from context mocking to AllProviders with real hooks. Extract export/import logic from ActionBar into useEncounterExportImport hook. Add bestiary-cache and bestiary-index-adapter test suites. Raise adapter coverage thresholds (68→80 lines, 56→62 branches). 77 test files, 891 tests, all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
108
apps/web/src/__tests__/adapters/in-memory-adapters.ts
Normal file
108
apps/web/src/__tests__/adapters/in-memory-adapters.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import {
|
||||
type Creature,
|
||||
type CreatureId,
|
||||
EMPTY_UNDO_REDO_STATE,
|
||||
type Encounter,
|
||||
type PlayerCharacter,
|
||||
type UndoRedoState,
|
||||
} from "@initiative/domain";
|
||||
import type { Adapters } from "../../contexts/adapter-context.js";
|
||||
|
||||
export function createTestAdapters(options?: {
|
||||
encounter?: Encounter | null;
|
||||
undoRedoState?: UndoRedoState;
|
||||
playerCharacters?: PlayerCharacter[];
|
||||
creatures?: Map<CreatureId, Creature>;
|
||||
sources?: Map<
|
||||
string,
|
||||
{ displayName: string; creatures: Creature[]; cachedAt: number }
|
||||
>;
|
||||
}): Adapters {
|
||||
let storedEncounter = options?.encounter ?? null;
|
||||
let storedUndoRedo = options?.undoRedoState ?? EMPTY_UNDO_REDO_STATE;
|
||||
let storedPCs = options?.playerCharacters ?? [];
|
||||
const sourceStore =
|
||||
options?.sources ??
|
||||
new Map<
|
||||
string,
|
||||
{ displayName: string; creatures: Creature[]; cachedAt: number }
|
||||
>();
|
||||
|
||||
// Pre-populate sourceStore from creatures map if provided
|
||||
if (options?.creatures && !options?.sources) {
|
||||
// No-op: creatures are accessed directly from the map
|
||||
}
|
||||
|
||||
const creatureMap = options?.creatures ?? new Map<CreatureId, Creature>();
|
||||
|
||||
return {
|
||||
encounterPersistence: {
|
||||
load: () => storedEncounter,
|
||||
save: (e) => {
|
||||
storedEncounter = e;
|
||||
},
|
||||
},
|
||||
undoRedoPersistence: {
|
||||
load: () => storedUndoRedo,
|
||||
save: (state) => {
|
||||
storedUndoRedo = state;
|
||||
},
|
||||
},
|
||||
playerCharacterPersistence: {
|
||||
load: () => [...storedPCs],
|
||||
save: (pcs) => {
|
||||
storedPCs = pcs;
|
||||
},
|
||||
},
|
||||
bestiaryCache: {
|
||||
cacheSource(sourceCode, displayName, creatures) {
|
||||
sourceStore.set(sourceCode, {
|
||||
displayName,
|
||||
creatures,
|
||||
cachedAt: Date.now(),
|
||||
});
|
||||
for (const c of creatures) {
|
||||
creatureMap.set(c.id, c);
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
isSourceCached(sourceCode) {
|
||||
return Promise.resolve(sourceStore.has(sourceCode));
|
||||
},
|
||||
getCachedSources() {
|
||||
return Promise.resolve(
|
||||
[...sourceStore.entries()].map(([sourceCode, info]) => ({
|
||||
sourceCode,
|
||||
displayName: info.displayName,
|
||||
creatureCount: info.creatures.length,
|
||||
cachedAt: info.cachedAt,
|
||||
})),
|
||||
);
|
||||
},
|
||||
clearSource(sourceCode) {
|
||||
sourceStore.delete(sourceCode);
|
||||
return Promise.resolve();
|
||||
},
|
||||
clearAll() {
|
||||
sourceStore.clear();
|
||||
return Promise.resolve();
|
||||
},
|
||||
loadAllCachedCreatures() {
|
||||
return Promise.resolve(new Map(creatureMap));
|
||||
},
|
||||
},
|
||||
bestiaryIndex: {
|
||||
loadIndex: () => ({ sources: {}, creatures: [] }),
|
||||
getAllSourceCodes: () => [],
|
||||
getDefaultFetchUrl: (sourceCode, baseUrl) => {
|
||||
const filename = `bestiary-${sourceCode.toLowerCase()}.json`;
|
||||
if (baseUrl !== undefined) {
|
||||
const normalized = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
||||
return `${normalized}${filename}`;
|
||||
}
|
||||
return `https://example.com/${filename}`;
|
||||
},
|
||||
getSourceDisplayName: (sourceCode) => sourceCode,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user