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:
@@ -37,14 +37,7 @@ import {
|
||||
resolveCreatureName,
|
||||
} from "@initiative/domain";
|
||||
import { useCallback, useEffect, useReducer, useRef } from "react";
|
||||
import {
|
||||
loadEncounter,
|
||||
saveEncounter,
|
||||
} from "../persistence/encounter-storage.js";
|
||||
import {
|
||||
loadUndoRedoStacks,
|
||||
saveUndoRedoStacks,
|
||||
} from "../persistence/undo-redo-storage.js";
|
||||
import { useAdapters } from "../contexts/adapter-context.js";
|
||||
|
||||
// -- Types --
|
||||
|
||||
@@ -111,11 +104,14 @@ function deriveNextId(encounter: Encounter): number {
|
||||
return max;
|
||||
}
|
||||
|
||||
function initializeState(): EncounterState {
|
||||
const encounter = loadEncounter() ?? EMPTY_ENCOUNTER;
|
||||
function initializeState(
|
||||
loadEncounterFn: () => Encounter | null,
|
||||
loadUndoRedoFn: () => UndoRedoState,
|
||||
): EncounterState {
|
||||
const encounter = loadEncounterFn() ?? EMPTY_ENCOUNTER;
|
||||
return {
|
||||
encounter,
|
||||
undoRedoState: loadUndoRedoStacks(),
|
||||
undoRedoState: loadUndoRedoFn(),
|
||||
events: [],
|
||||
nextId: deriveNextId(encounter),
|
||||
lastCreatureId: null,
|
||||
@@ -385,7 +381,10 @@ function dispatchEncounterAction(
|
||||
// -- Hook --
|
||||
|
||||
export function useEncounter() {
|
||||
const [state, dispatch] = useReducer(encounterReducer, null, initializeState);
|
||||
const { encounterPersistence, undoRedoPersistence } = useAdapters();
|
||||
const [state, dispatch] = useReducer(encounterReducer, null, () =>
|
||||
initializeState(encounterPersistence.load, undoRedoPersistence.load),
|
||||
);
|
||||
const { encounter, undoRedoState, events } = state;
|
||||
|
||||
const encounterRef = useRef(encounter);
|
||||
@@ -394,12 +393,12 @@ export function useEncounter() {
|
||||
undoRedoRef.current = undoRedoState;
|
||||
|
||||
useEffect(() => {
|
||||
saveEncounter(encounter);
|
||||
}, [encounter]);
|
||||
encounterPersistence.save(encounter);
|
||||
}, [encounter, encounterPersistence]);
|
||||
|
||||
useEffect(() => {
|
||||
saveUndoRedoStacks(undoRedoState);
|
||||
}, [undoRedoState]);
|
||||
undoRedoPersistence.save(undoRedoState);
|
||||
}, [undoRedoState, undoRedoPersistence]);
|
||||
|
||||
// Escape hatches for useInitiativeRolls (needs raw port access)
|
||||
const makeStore = useCallback((): EncounterStore => {
|
||||
|
||||
Reference in New Issue
Block a user