Setting the file. One moment. Audio Meta Test · Media Use · heygen-com/hyperframes · Skills Docs⋯
scripts/11 files
(opens in a new tab)
audio/scripts/lib/audio-meta.test.mjs
JavaScript·136 lines·4 KB
from
"node:os"
;
13import { join } from "node:path";
14import { spawnSync } from "node:child_process";
15import { fileURLToPath } from "node:url";
16import { openAudioMeta } from "./audio-meta.mjs";
17
18function fixture(t) {
19 const dir = mkdtempSync(join(tmpdir(), "audio-meta-"));
20 t.after(() => rmSync(dir, { recursive: true, force: true }));
21 return dir;
22}
23
24test("updates the read file from byte zero, truncates, and retains its mode", (t) => {
25 const path = join(fixture(t), "meta.json");
26 writeFileSync(path, JSON.stringify({ voices: ["long existing voice metadata"] }), {
27 mode: 0o600,
28 });
29 const originalMode = statSync(path).mode;
30 const handle = openAudioMeta(path);
31 assert.deepEqual(handle.value, { voices: ["long existing voice metadata"] });
32 handle.write({ voices: ["声"] });
33 assert.equal(readFileSync(path, "utf8"), JSON.stringify({ voices: ["声"] }, null, 2));
34 assert.equal(statSync(path).mode, originalMode);
35});
36
37test("pathname replacement cannot redirect the existing-file write", (t) => {
38 const dir = fixture(t);
39 const path = join(dir, "meta.json");
40 const moved = join(dir, "original.json");
41 writeFileSync(path, "{}");
42 const handle = openAudioMeta(path);
43 renameSync(path, moved);
44 writeFileSync(path, "replacement must survive");
45 handle.write({ voices: [] });
46 assert.equal(readFileSync(path, "utf8"), "replacement must survive");
47 assert.deepEqual(JSON.parse(readFileSync(moved, "utf8")), { voices: [] });
48});
49
50test("existing symlink outputs retain their original target even after retargeting", (t) => {
51 const dir = fixture(t);
52 const path = join(dir, "meta.json");
53 const target = join(dir, "target.json");
54 const victim = join(dir, "victim.json");
55 writeFileSync(target, "{}");
56 writeFileSync(victim, "untouched");
57 symlinkSync(target, path);
58 const handle = openAudioMeta(path);
59 rmSync(path);
60 symlinkSync(victim, path);
61 handle.write({ bgm: null });
62 assert.equal(readFileSync(victim, "utf8"), "untouched");
63 assert.deepEqual(JSON.parse(readFileSync(target, "utf8")), { bgm: null });
64});
65
66test("missing output is created only when saved", (t) => {
67 const path = join(fixture(t), "meta.json");
68 const handle = openAudioMeta(path);
69 assert.deepEqual(handle.value, {});
70 assert.throws(() => statSync(path), { code: "ENOENT" });
71 handle.write({ sfx: [] });
72 assert.deepEqual(JSON.parse(readFileSync(path, "utf8")), { sfx: [] });
73});
74
75for (const replacement of ["file", "symlink"]) {
76 test(`new output does not overwrite a racing ${replacement}`, (t) => {
77 const dir = fixture(t);
78 const path = join(dir, "meta.json");
79 const victim = join(dir, "victim.json");
80 const handle = openAudioMeta(path);
81 writeFileSync(victim, "untouched");
82 if (replacement === "symlink") symlinkSync(victim, path);
83 else writeFileSync(path, "untouched");
84 assert.throws(() => handle.write({}), { code: "EEXIST" });
85 assert.equal(readFileSync(path, "utf8"), "untouched");
86 assert.equal(readFileSync(victim, "utf8"), "untouched");
87 });
88}
89
90test("malformed merge base remains an error without changing bytes", (t) => {
91 const path = join(fixture(t), "meta.json");
92 writeFileSync(path, "bad json");
93 assert.throws(() => openAudioMeta(path), SyntaxError);
94 assert.equal(readFileSync(path, "utf8"), "bad json");
95});
96
97test("CLI partial run retains unselected voices, BGM and SFX", (t) => {
98 const dir = fixture(t);
99 const path = join(dir, "meta.json");
100 const request = join(dir, "request.json");
101 const previous = {
102 voices: [{ id: "a", duration_s: 2 }],
103 bgm: { path: "bgm.wav" },
104 sfx: [{ name: "click" }],
105 tts_provider: "kokoro",
106 voice_id: "voice-a",
107 };
108 writeFileSync(path, JSON.stringify(previous));
109 writeFileSync(request, "{}");
110 const result = spawnSync(
111 process.execPath,
112 [
113 fileURLToPath(new URL("../audio.mjs", import.meta.url)),
114 "--request",
115 request,
116 "--hyperframes",
117 dir,
118 "--out",
119 path,
120 "--only",
121 "none",
122 ],
123 {
124 encoding: "utf8",
125 env: {
126 ...process.env,
127 HEYGEN_CONFIG_DIR: dir,
128 HEYGEN_API_KEY: "",
129 HYPERFRAMES_API_KEY: "",
130 },
131 },
132 );
133 assert.equal(result.status, 0, result.stderr);
134 const actual = JSON.parse(readFileSync(path, "utf8"));
135 for (const key of Object.keys(previous)) assert.deepEqual(actual[key], previous[key]);
136});