All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m4s
74 lines
3.2 KiB
TypeScript
74 lines
3.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { ArcadeImportError, parseConnectionsImport, parseConnectionsImportBatch } from "@/lib/arcade/connectionsImport";
|
|
|
|
function validPack() {
|
|
return {
|
|
schemaVersion: 1,
|
|
type: "connections",
|
|
name: "Medication Connections",
|
|
description: "Four medication groups",
|
|
settings: { groupCount: 4, itemsPerGroup: 4, allowedMistakes: 4 },
|
|
content: Array.from({ length: 4 }, (_, groupIndex) => ({
|
|
category: `Category ${groupIndex + 1}`,
|
|
items: Array.from({ length: 4 }, (_, itemIndex) => `Item ${groupIndex + 1}-${itemIndex + 1}`),
|
|
explanation: `Explanation ${groupIndex + 1}`,
|
|
})),
|
|
};
|
|
}
|
|
|
|
describe("Connections imports", () => {
|
|
it("normalizes a valid board and creates stable ids", () => {
|
|
const result = parseConnectionsImport(JSON.stringify(validPack()));
|
|
expect(result.preview.itemCount).toBe(16);
|
|
expect(result.preview.itemCount).toBe(16);
|
|
expect(result.preview.normalized.content[0].id).toBe("group-1");
|
|
expect(result.preview.normalized.content[0].items[0].id).toBe("group-1-item-1");
|
|
});
|
|
|
|
it("rejects fences and surrounding prose", () => {
|
|
expect(() => parseConnectionsImport(`\`\`\`json\n${JSON.stringify(validPack())}\n\`\`\``)).toThrow(ArcadeImportError);
|
|
expect(() => parseConnectionsImport(`Here is the pack: ${JSON.stringify(validPack())}`)).toThrow(ArcadeImportError);
|
|
});
|
|
|
|
it("rejects duplicate tiles case-insensitively", () => {
|
|
const pack = validPack();
|
|
pack.content[1].items[0] = " item 1-1 ";
|
|
expect(() => parseConnectionsImport(JSON.stringify(pack))).toThrow("Every tile must be unique");
|
|
});
|
|
|
|
it("rejects unknown keys", () => {
|
|
const pack = { ...validPack(), extra: true };
|
|
expect(() => parseConnectionsImport(JSON.stringify(pack))).toThrow("does not match schema version 1");
|
|
});
|
|
|
|
it("reports long-tile warnings without changing the content", () => {
|
|
const pack = validPack();
|
|
pack.content[0].items[0] = "This intentionally long tile contains too many words";
|
|
const result = parseConnectionsImport(JSON.stringify(pack));
|
|
expect(result.report.warnings.length).toBeGreaterThan(0);
|
|
expect(result.preview.normalized.content[0].items[0].text).toBe(pack.content[0].items[0]);
|
|
});
|
|
|
|
it("does not treat a shared generic word as a similar category", () => {
|
|
const pack = validPack();
|
|
pack.content[0].category = "ACE Inhibitors";
|
|
pack.content[1].category = "Proton Pump Inhibitors";
|
|
const result = parseConnectionsImport(JSON.stringify(pack));
|
|
expect(result.report.warnings).not.toContain(
|
|
"Categories “ACE Inhibitors” and “Proton Pump Inhibitors” may be too similar."
|
|
);
|
|
});
|
|
|
|
it("previews multiple packs from one JSON array", () => {
|
|
const first = validPack();
|
|
const second = { ...validPack(), name: "Second board" };
|
|
const result = parseConnectionsImportBatch(JSON.stringify([first, second]));
|
|
expect(result.count).toBe(2);
|
|
expect(result.packs.map((pack) => pack.name)).toEqual(["Medication Connections", "Second board"]);
|
|
});
|
|
|
|
it("limits batch imports to ten packs", () => {
|
|
const batch = Array.from({ length: 11 }, () => validPack());
|
|
expect(() => parseConnectionsImportBatch(JSON.stringify(batch))).toThrow("between 1 and 10");
|
|
});
|
|
});
|