50 lines
2.1 KiB
TypeScript
50 lines
2.1 KiB
TypeScript
import { test, expect, beforeEach, afterEach } from "bun:test";
|
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { addSong, readManifest, songDir } from "../../src/ref/manifest.ts";
|
|
|
|
let root = "";
|
|
beforeEach(async () => { root = await mkdtemp(join(tmpdir(), "ref-")); });
|
|
afterEach(async () => { await rm(root, { recursive: true, force: true }); });
|
|
|
|
const base = { id: "s1", title: "Song", audio: "a.flac", midi: "a.mid", capo: {} };
|
|
|
|
test("readManifest on empty root returns []", async () => {
|
|
expect(await readManifest(root)).toEqual([]);
|
|
});
|
|
|
|
test("addSong writes songs.json with given roles", async () => {
|
|
const e = await addSong({ ...base, roles: { Gtr: "guitar", Crowd: null } }, root);
|
|
expect(e.roles).toEqual({ Gtr: "guitar", Crowd: null });
|
|
expect(await Bun.file(join(root, "songs.json")).exists()).toBe(true);
|
|
expect(await readManifest(root)).toEqual([e]);
|
|
});
|
|
|
|
test("addSong guesses roles from the midi, keyed by track name", async () => {
|
|
const ascii = (x: string) => [...x].map((c) => c.charCodeAt(0));
|
|
const trk = (n: string, prog: number) => {
|
|
const body = [0, 0xff, 3, n.length, ...ascii(n), 0, 0xc0, prog, 0, 0x90, 60, 90, 0x60, 0x80, 60, 0, 0, 0xff, 0x2f, 0];
|
|
return [...ascii("MTrk"), 0, 0, 0, body.length, ...body];
|
|
};
|
|
const mid = new Uint8Array([...ascii("MThd"), 0, 0, 0, 6, 0, 1, 0, 2, 0x01, 0xe0, ...trk("Acoustic Guitar ", 25), ...trk("Brass", 61)]);
|
|
const midi = join(root, "in.mid");
|
|
await Bun.write(midi, mid);
|
|
const e = await addSong({ ...base, midi }, root);
|
|
expect(e.roles).toEqual({ "Acoustic Guitar ": "guitar", Brass: null });
|
|
});
|
|
|
|
test("addSong rejects duplicate ids", async () => {
|
|
await addSong({ ...base, roles: {} }, root);
|
|
await expect(addSong({ ...base, roles: {} }, root)).rejects.toThrow(/duplicate|exists/i);
|
|
expect(await readManifest(root)).toHaveLength(1);
|
|
});
|
|
|
|
test("rejects unsafe ids", async () => {
|
|
await expect(addSong({ ...base, id: "../x", roles: {} }, root)).rejects.toThrow();
|
|
});
|
|
|
|
test("songDir", () => {
|
|
expect(songDir("s1", root)).toBe(join(root, "s1"));
|
|
});
|