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>
108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
getAllSourceCodes,
|
|
getDefaultFetchUrl,
|
|
getSourceDisplayName,
|
|
loadBestiaryIndex,
|
|
} from "../bestiary-index-adapter.js";
|
|
|
|
describe("loadBestiaryIndex", () => {
|
|
it("returns an object with sources and creatures", () => {
|
|
const index = loadBestiaryIndex();
|
|
expect(index.sources).toBeDefined();
|
|
expect(index.creatures).toBeDefined();
|
|
expect(Array.isArray(index.creatures)).toBe(true);
|
|
});
|
|
|
|
it("creatures have the expected shape", () => {
|
|
const index = loadBestiaryIndex();
|
|
expect(index.creatures.length).toBeGreaterThan(0);
|
|
const first = index.creatures[0];
|
|
expect(first).toHaveProperty("name");
|
|
expect(first).toHaveProperty("source");
|
|
expect(first).toHaveProperty("ac");
|
|
expect(first).toHaveProperty("hp");
|
|
expect(first).toHaveProperty("dex");
|
|
expect(first).toHaveProperty("cr");
|
|
expect(first).toHaveProperty("initiativeProficiency");
|
|
expect(first).toHaveProperty("size");
|
|
expect(first).toHaveProperty("type");
|
|
});
|
|
|
|
it("returns the same cached instance on subsequent calls", () => {
|
|
const a = loadBestiaryIndex();
|
|
const b = loadBestiaryIndex();
|
|
expect(a).toBe(b);
|
|
});
|
|
|
|
it("sources is a record of source code to display name", () => {
|
|
const index = loadBestiaryIndex();
|
|
const entries = Object.entries(index.sources);
|
|
expect(entries.length).toBeGreaterThan(0);
|
|
for (const [code, name] of entries) {
|
|
expect(typeof code).toBe("string");
|
|
expect(typeof name).toBe("string");
|
|
expect(code.length).toBeGreaterThan(0);
|
|
expect(name.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("getAllSourceCodes", () => {
|
|
it("returns all keys from the index sources", () => {
|
|
const codes = getAllSourceCodes();
|
|
const index = loadBestiaryIndex();
|
|
expect(codes).toEqual(Object.keys(index.sources));
|
|
});
|
|
|
|
it("returns only strings", () => {
|
|
for (const code of getAllSourceCodes()) {
|
|
expect(typeof code).toBe("string");
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("getDefaultFetchUrl", () => {
|
|
it("returns default GitHub URL when no baseUrl provided", () => {
|
|
const url = getDefaultFetchUrl("MM");
|
|
expect(url).toBe(
|
|
"https://raw.githubusercontent.com/5etools-mirror-3/5etools-src/main/data/bestiary/bestiary-mm.json",
|
|
);
|
|
});
|
|
|
|
it("constructs URL from baseUrl with trailing slash", () => {
|
|
const url = getDefaultFetchUrl("PHB", "https://example.com/data/");
|
|
expect(url).toBe("https://example.com/data/bestiary-phb.json");
|
|
});
|
|
|
|
it("normalizes baseUrl without trailing slash", () => {
|
|
const url = getDefaultFetchUrl("PHB", "https://example.com/data");
|
|
expect(url).toBe("https://example.com/data/bestiary-phb.json");
|
|
});
|
|
|
|
it("lowercases the source code in the filename", () => {
|
|
const url = getDefaultFetchUrl("XMM");
|
|
expect(url).toContain("bestiary-xmm.json");
|
|
});
|
|
|
|
it("applies filename override for Plane Shift sources", () => {
|
|
expect(getDefaultFetchUrl("PSA")).toContain("bestiary-ps-a.json");
|
|
expect(getDefaultFetchUrl("PSD")).toContain("bestiary-ps-d.json");
|
|
expect(getDefaultFetchUrl("PSK")).toContain("bestiary-ps-k.json");
|
|
});
|
|
});
|
|
|
|
describe("getSourceDisplayName", () => {
|
|
it("returns display name for a known source", () => {
|
|
const index = loadBestiaryIndex();
|
|
const [code, expectedName] = Object.entries(index.sources)[0];
|
|
expect(getSourceDisplayName(code)).toBe(expectedName);
|
|
});
|
|
|
|
it("falls back to source code for unknown source", () => {
|
|
expect(getSourceDisplayName("UNKNOWN_SOURCE_XYZ")).toBe(
|
|
"UNKNOWN_SOURCE_XYZ",
|
|
);
|
|
});
|
|
});
|