Add folder game, file browser UI, and automated tests.

Introduces a localStorage-backed messy-desktop challenge with sub-steps,
drag-and-drop and Places/Back navigation, IBM Plex Mono, and a /api/health
endpoint. Adds Vitest coverage for the API and level logic plus Playwright
smoke tests.

Made-with: Cursor
This commit is contained in:
2026-04-11 18:22:50 +12:00
parent 818da20af8
commit 1957e96363
21 changed files with 1429 additions and 53 deletions

View File

@@ -0,0 +1,11 @@
import { describe, expect, it } from "vitest";
import { GET } from "~/app/api/health/route";
describe("GET /api/health", () => {
it("returns 200 and status ok", async () => {
const res = await GET();
expect(res.status).toBe(200);
await expect(res.json()).resolves.toEqual({ status: "ok" });
});
});

View File

@@ -0,0 +1,21 @@
import { describe, expect, it, vi } from "vitest";
vi.mock("~/server/auth", () => ({
auth: vi.fn(async () => null),
}));
vi.mock("~/server/db", () => ({
db: {},
}));
import { createCaller } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
describe("tRPC post.hello", () => {
it("returns a greeting for the given text", async () => {
const ctx = await createTRPCContext({ headers: new Headers() });
const caller = createCaller(ctx);
const out = await caller.post.hello({ text: "Tester" });
expect(out.greeting).toBe("Hello Tester");
});
});

52
tests/unit/levels.test.ts Normal file
View File

@@ -0,0 +1,52 @@
import { describe, expect, it } from "vitest";
import {
buildInitialFs,
isFsLevelComplete,
isQuizComplete,
isSubComplete,
QUIZ_CORRECT_ID,
} from "~/lib/folder-game/levels";
describe("isFsLevelComplete", () => {
it("level 0 completes when Games and Documents were opened", () => {
const fs = buildInitialFs(0);
expect(isFsLevelComplete(0, fs)).toBe(false);
expect(
isFsLevelComplete(0, {
...fs,
visitedFolderIds: ["fld-games", "fld-docs"],
}),
).toBe(true);
});
it("level 1 completes when files are sorted", () => {
const fs = buildInitialFs(1);
const nodes = fs.nodes.map((n) => {
if (n.id === "file-cat") return { ...n, parentId: "fld-pics" };
if (n.id === "file-hw") return { ...n, parentId: "fld-school" };
return n;
});
expect(isFsLevelComplete(1, { ...fs, nodes })).toBe(true);
});
});
describe("isSubComplete", () => {
it("level 0 sub 0 requires Games", () => {
const fs = buildInitialFs(0);
expect(isSubComplete(0, 0, fs)).toBe(false);
expect(
isSubComplete(0, 0, {
...fs,
visitedFolderIds: ["fld-games"],
}),
).toBe(true);
});
});
describe("isQuizComplete", () => {
it("accepts Documents choice", () => {
expect(isQuizComplete(QUIZ_CORRECT_ID)).toBe(true);
expect(isQuizComplete("opt-dl")).toBe(false);
});
});