Files
STCourses/packages/feature-studio/test/media-refs.test.ts
T

78 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { $ } from "bun";
import { gitignoreLine, isLargeMedia, LARGE_FILE_BYTES, mediaGitignore, parseMediaRefs, sha256File } from "../src/server/media-refs";
import { tempDir } from "./helpers";
describe("isLargeMedia", () => {
test("video and audio by extension, whatever the size", () => {
for (const p of ["a.mp4", "x/B.MOV", "c.webm", "d.mkv", "e.mp3", "f.m4a", "g.wav", "h.flac", "i.avi", "j.m4v"]) expect(isLargeMedia(p, 10)).toBe(true);
});
test("other files only above the size limit", () => {
expect(isLargeMedia("deck.pdf", 1000)).toBe(false);
expect(isLargeMedia("deck.pdf", LARGE_FILE_BYTES + 1)).toBe(true);
expect(isLargeMedia("lesson.md", LARGE_FILE_BYTES)).toBe(false);
});
});
describe("gitignoreLine", () => {
test("anchors and escapes", () => {
expect(gitignoreLine("media/a.mp4")).toBe("/media/a.mp4");
expect(gitignoreLine("media/[1] *?.mp4")).toBe("/media/\\[1\\] \\*\\?.mp4");
expect(gitignoreLine("a\\b.mp4")).toBe("/a\\\\b.mp4");
expect(gitignoreLine("trail.mp4 ")).toBe("/trail.mp4\\ \\ ");
});
test("refuses names a .gitignore cannot express", () => {
expect(() => gitignoreLine("a\nb.mp4")).toThrow();
expect(() => gitignoreLine("a\rb.mp4")).toThrow();
});
test("git ignores exactly the listed paths", async () => {
const dir = tempDir();
await $`git init -q ${dir}`.quiet();
const listed = ["media/01 Intro – Übersicht.mp4", "media/[draft] *star?.mp4", "#hash.mp4", "!bang.mp4", "media/trailing.mp4 ", "deep/a b/c.mkv"];
const siblings = ["media/01 Intro – Übersicht.mp4.txt", "media/d.mp4", "hash.mp4", "bang.mp4", "media/trailing.mp4", "deep/a b/c.mkv2", "sub/#hash.mp4"];
for (const p of [...listed, ...siblings]) {
mkdirSync(join(dir, p, ".."), { recursive: true });
writeFileSync(join(dir, p), "x");
}
writeFileSync(join(dir, ".gitignore"), mediaGitignore(listed, null));
const input = Buffer.from([...listed, ...siblings].join("\0") + "\0");
const r = await $`git -c core.quotepath=false check-ignore -z --no-index --stdin < ${input}`.cwd(dir).quiet().nothrow();
const ignored = r.stdout.toString().split("\0").filter(Boolean).sort();
expect(ignored).toEqual([...listed].sort());
});
test("an existing .gitignore is kept above the media block", () => {
const out = mediaGitignore(["a.mp4"], "node_modules/\n");
expect(out.startsWith("node_modules/\n")).toBe(true);
expect(out).toContain("/a.mp4\n");
expect(mediaGitignore(["a.mp4"], "dist")).toStartWith("dist\n");
});
});
test("sha256File streams the file", async () => {
const dir = tempDir();
const bytes = new Uint8Array(3 * 1024 * 1024 + 7).map((_, i) => i % 251);
writeFileSync(join(dir, "f.bin"), bytes);
expect(await sha256File(join(dir, "f.bin"))).toBe(new Bun.CryptoHasher("sha256").update(bytes).digest("hex"));
});
describe("parseMediaRefs", () => {
const sha = "a".repeat(64);
test("accepts the schema", () => {
expect(parseMediaRefs(JSON.stringify({ schema: 1, files: [{ path: "media/a.mp4", size: 3, sha256: sha }] }))).toEqual([{ path: "media/a.mp4", size: 3, sha256: sha }]);
});
test.each([
"not json", "null", "{}", JSON.stringify({ schema: 2, files: [] }),
JSON.stringify({ schema: 1, files: [{ path: "../x.mp4", size: 1, sha256: sha }] }),
JSON.stringify({ schema: 1, files: [{ path: "/abs.mp4", size: 1, sha256: sha }] }),
JSON.stringify({ schema: 1, files: [{ path: ".git/config", size: 1, sha256: sha }] }),
JSON.stringify({ schema: 1, files: [{ path: "a.mp4", size: -1, sha256: sha }] }),
JSON.stringify({ schema: 1, files: [{ path: "a.mp4", size: 1, sha256: "zz" }] }),
])("rejects %p", (text) => {
expect(parseMediaRefs(text)).toBeNull();
});
});