Files
STCourses/packages/feature-import/test/util.test.ts
T

42 lines
1.9 KiB
TypeScript

import { expect, test } from "bun:test";
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { decodeEntities, naturalSort, slugify, uniqueId } from "../src/util/text";
import { run } from "../src/util/exec";
import { readRawManifest, writeManifest } from "../src/util/manifest";
test("slugify folds accents and falls back", () => {
expect(slugify("Mastering Docker Essentials - Hands-on DevOps!")).toBe("mastering-docker-essentials-hands-on-devops");
expect(slugify("Café Ünïcode")).toBe("cafe-unicode");
expect(slugify("日本語")).toBe("course");
});
test("uniqueId appends a counter", () => {
expect(uniqueId("a", (x) => x === "a" || x === "a-2")).toBe("a-3");
expect(uniqueId("a", () => false)).toBe("a");
});
test("decodeEntities handles named and numeric entities", () => {
expect(decodeEntities("you&#039;ll &amp; &lt;b&gt; &quot;x&quot; &#x41;")).toBe(`you'll & <b> "x" A`);
});
test("naturalSort orders numbers numerically", () => {
expect(naturalSort(["10 b.mp4", "2 a.mp4", "1 z.mp4"])).toEqual(["1 z.mp4", "2 a.mp4", "10 b.mp4"]);
});
test("run reports stderr on failure", async () => {
expect(await run(["echo", "hi"])).toContain("hi");
await expect(run(["sh", "-c", "echo oops >&2; exit 3"])).rejects.toThrow(/oops/);
});
test("writeManifest validates and round-trips", async () => {
const dir = await mkdtemp(join(tmpdir(), "stc-m-"));
await mkdir(join(dir, "c"));
const m = { schema: 1, id: "x", title: "T: with colon", visibility: "restricted", modules: [{ id: "m1", title: "S08 - Foo", lessons: [] }] };
await writeManifest(join(dir, "c"), m);
expect((await readRawManifest(join(dir, "c")) as any).modules[0].title).toBe("S08 - Foo");
await expect(writeManifest(join(dir, "c"), { ...m, id: "BAD ID" })).rejects.toThrow(/id/);
await writeFile(join(dir, "c", "marker"), "");
});