feat(align): SMF parser, role guess, reference manifest
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
67168e6103
commit
e910036e67
8 files changed
+414
-1
No files matched your search
@@ -0,0 +1,49 @@
|
||||
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"));
|
||||
});
|
||||
Reference in new issue
Block a user