83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { fetchRecipesIndex } from "./catalog";
|
|
|
|
const emptyText = { fr: "", en: "", ko: "", zh: "" };
|
|
|
|
const minimalBase = {
|
|
id: "base:x",
|
|
flavor: "savory" as const,
|
|
name: emptyText,
|
|
history: emptyText,
|
|
ingredients: [],
|
|
steps: []
|
|
};
|
|
|
|
const minimalVariant = {
|
|
id: "var:y",
|
|
baseIds: ["base:x"],
|
|
name: emptyText,
|
|
story: emptyText,
|
|
ingredients: [],
|
|
steps: []
|
|
};
|
|
|
|
describe("fetchRecipesIndex", () => {
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("loads and freezes catalog JSON", async () => {
|
|
const payload = { bases: [minimalBase], variants: [minimalVariant] };
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () =>
|
|
Promise.resolve({
|
|
ok: true,
|
|
json: async () => payload
|
|
})
|
|
)
|
|
);
|
|
|
|
const index = await fetchRecipesIndex("/custom/catalog.json");
|
|
expect(index.bases).toHaveLength(1);
|
|
expect(index.variants).toHaveLength(1);
|
|
expect(fetch).toHaveBeenCalledWith("/custom/catalog.json", {
|
|
headers: { Accept: "application/json" }
|
|
});
|
|
});
|
|
|
|
it("throws when response is not ok", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () => Promise.resolve({ ok: false, status: 503 }))
|
|
);
|
|
await expect(fetchRecipesIndex()).rejects.toThrow("503");
|
|
});
|
|
|
|
it("throws when payload is not an object", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () =>
|
|
Promise.resolve({
|
|
ok: true,
|
|
json: async () => null
|
|
})
|
|
)
|
|
);
|
|
await expect(fetchRecipesIndex()).rejects.toThrow("Invalid recipe catalog payload");
|
|
});
|
|
|
|
it("throws when bases or variants are not arrays", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () =>
|
|
Promise.resolve({
|
|
ok: true,
|
|
json: async () => ({ bases: [], variants: null })
|
|
})
|
|
)
|
|
);
|
|
await expect(fetchRecipesIndex()).rejects.toThrow("Invalid recipe catalog shape");
|
|
});
|
|
});
|