39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
/**
|
|
* Audio backend dispose regression test.
|
|
*
|
|
* The `q` (quit) action routes through `process.exit(0)`, which bypasses
|
|
* Solid's onCleanup (where useAudio's onCleanup disposes the backend). To
|
|
* keep spawned players (mpv/ffplay/afplay) from surviving the host, useAudio
|
|
* registers a `process.on("exit")` handler that synchronously disposes the
|
|
* backend. The exit handler's whole job is "kill the child process", so this
|
|
* test pins the contract directly: a backend holding a real spawned subprocess
|
|
* must have killed it once `dispose()` returns.
|
|
*
|
|
* Uses a real `Bun.spawn(["sleep", "60"])` subprocess as a stand-in for the
|
|
* player process, injected into the (private) `proc` slot of an MpvBackend —
|
|
* mpv/ffplay/afplay all share the identical kill-on-dispose pattern, so
|
|
* exercising one is enough to guard the family.
|
|
*/
|
|
import { test, expect } from "bun:test";
|
|
import { MpvBackend } from "../src/utils/audio-player";
|
|
|
|
test("MpvBackend.dispose() kills the spawned child process", async () => {
|
|
const backend = new MpvBackend();
|
|
// Inject a real long-lived subprocess as if mpv had been spawned.
|
|
const child = Bun.spawn(["sleep", "60"], {
|
|
stdout: "ignore",
|
|
stderr: "ignore",
|
|
stdin: "ignore",
|
|
});
|
|
(backend as unknown as { proc: typeof child }).proc = child;
|
|
|
|
// Sanity: the child is alive.
|
|
expect(child.killed).toBe(false);
|
|
|
|
backend.dispose();
|
|
|
|
// dispose() sent SIGTERM (proc.kill()); wait for the child to exit.
|
|
await child.exited;
|
|
expect(child.killed).toBe(true);
|
|
});
|