103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
|
import { mkdtempSync, writeFileSync, rmSync, cpSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { NowPlayingWatcher } from "../src/nowplaying.ts";
|
|
|
|
let tmpRoot: string;
|
|
|
|
beforeEach(() => {
|
|
tmpRoot = mkdtempSync(join(tmpdir(), "denpa-np-"));
|
|
cpSync("tests/fixtures/now-playing", join(tmpRoot, "now-playing"), { recursive: true });
|
|
cpSync("tests/fixtures/library", join(tmpRoot, "library"), { recursive: true });
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tmpRoot, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("NowPlayingWatcher", () => {
|
|
it("reads initial state from disk", async () => {
|
|
const watcher = new NowPlayingWatcher({
|
|
station: "minecraft",
|
|
nowPlayingDir: join(tmpRoot, "now-playing"),
|
|
libraryDir: join(tmpRoot, "library"),
|
|
});
|
|
await watcher.start();
|
|
const state = watcher.current();
|
|
expect(state).not.toBeNull();
|
|
expect(state!.title).toBe("Sweden");
|
|
expect(state!.cover_url).toMatch(/^\/cover\?path=/);
|
|
expect(state!.up_next).toHaveLength(1);
|
|
watcher.stop();
|
|
});
|
|
|
|
it("rewrites cover_path to /cover?path=… url", async () => {
|
|
const watcher = new NowPlayingWatcher({
|
|
station: "minecraft",
|
|
nowPlayingDir: join(tmpRoot, "now-playing"),
|
|
libraryDir: join(tmpRoot, "library"),
|
|
});
|
|
await watcher.start();
|
|
expect(watcher.current()!.cover_url).toContain(
|
|
encodeURIComponent("/library/minecraft/tracks/Volume Alpha/cover.jpg"),
|
|
);
|
|
watcher.stop();
|
|
});
|
|
|
|
it("emits change events on file rewrite", async () => {
|
|
const watcher = new NowPlayingWatcher({
|
|
station: "minecraft",
|
|
nowPlayingDir: join(tmpRoot, "now-playing"),
|
|
libraryDir: join(tmpRoot, "library"),
|
|
});
|
|
await watcher.start();
|
|
|
|
let changes = 0;
|
|
watcher.on("change", () => changes++);
|
|
|
|
const newPayload = JSON.stringify({
|
|
station: "minecraft",
|
|
title: "Pigstep",
|
|
artist: "Lena Raine",
|
|
album: "Nether Update",
|
|
filename: "/library/minecraft/tracks/Nether/01. Pigstep.flac",
|
|
duration: "148",
|
|
started_at: "1730358500",
|
|
cover_path: "",
|
|
up_next: [],
|
|
});
|
|
writeFileSync(join(tmpRoot, "now-playing", "minecraft.json"), newPayload);
|
|
|
|
await new Promise((r) => setTimeout(r, 200));
|
|
expect(changes).toBeGreaterThan(0);
|
|
expect(watcher.current()!.title).toBe("Pigstep");
|
|
watcher.stop();
|
|
});
|
|
|
|
it("falls back to station cover when track cover missing", async () => {
|
|
const payload = JSON.stringify({
|
|
station: "minecraft",
|
|
title: "Untagged Track",
|
|
artist: "?",
|
|
album: "?",
|
|
filename: "/library/minecraft/tracks/UnknownAlbum/track.flac",
|
|
duration: "120",
|
|
started_at: "1730358000",
|
|
cover_path: "",
|
|
up_next: [],
|
|
});
|
|
writeFileSync(join(tmpRoot, "now-playing", "minecraft.json"), payload);
|
|
|
|
const watcher = new NowPlayingWatcher({
|
|
station: "minecraft",
|
|
nowPlayingDir: join(tmpRoot, "now-playing"),
|
|
libraryDir: join(tmpRoot, "library"),
|
|
});
|
|
await watcher.start();
|
|
expect(watcher.current()!.cover_url).toContain(
|
|
encodeURIComponent("/library/minecraft/cover.jpg"),
|
|
);
|
|
watcher.stop();
|
|
});
|
|
});
|