88 lines
3.3 KiB
JavaScript
88 lines
3.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { PlayerStateClient } from "../public/player-state.js";
|
|
|
|
test("polls reuse tracks and accept edits from another browser", async () => {
|
|
const tracks = [{ title: "First" }];
|
|
const changedTracks = [{ title: "Second" }];
|
|
const responses = [
|
|
{ playlistVersion: "first", tracks, position: 0 },
|
|
{ playlistVersion: "first", tracks: null, position: 1 },
|
|
{ playlistVersion: "changed", tracks: changedTracks, position: 2 },
|
|
{ playlistVersion: "changed", tracks: null, position: 3 },
|
|
];
|
|
const paths = [];
|
|
const client = new PlayerStateClient(async (path) => {
|
|
paths.push(path);
|
|
return responses.shift();
|
|
});
|
|
assert.equal((await client.request("/api/state")).tracks, tracks);
|
|
const unchanged = await client.request("/api/state");
|
|
assert.equal(unchanged.tracks, tracks);
|
|
assert.equal(unchanged.position, 1);
|
|
assert.equal((await client.request("/api/state")).tracks, changedTracks);
|
|
assert.equal((await client.request("/api/state")).tracks, changedTracks);
|
|
assert.deepEqual(paths, [
|
|
"/api/state", "/api/state?playlistVersion=first",
|
|
"/api/state?playlistVersion=first", "/api/state?playlistVersion=changed",
|
|
]);
|
|
});
|
|
|
|
test("commands and discovery wait for polling and use its latest version", async () => {
|
|
let finishPoll;
|
|
const paths = [];
|
|
const commandBody = { index: 1 };
|
|
const client = new PlayerStateClient((path, body) => {
|
|
paths.push(path);
|
|
if (paths.length === 1) {
|
|
return new Promise((resolve) => { finishPoll = resolve; });
|
|
}
|
|
if (paths.length === 2) {
|
|
assert.equal(body, commandBody);
|
|
return { playlistVersion: "other-tab", tracks: [] };
|
|
}
|
|
return { playlistVersion: "other-tab", tracks: null };
|
|
});
|
|
const poll = client.request("/api/state");
|
|
const command = client.request("/api/command/tab-select", commandBody);
|
|
const discovery = client.request("/api/discover", {});
|
|
await Promise.resolve();
|
|
assert.deepEqual(paths, ["/api/state"]);
|
|
finishPoll({ playlistVersion: "original-tab", tracks: [{ title: "First" }] });
|
|
await poll;
|
|
assert.deepEqual((await command).tracks, []);
|
|
assert.deepEqual((await discovery).tracks, []);
|
|
assert.deepEqual(paths, [
|
|
"/api/state",
|
|
"/api/command/tab-select?playlistVersion=original-tab",
|
|
"/api/discover?playlistVersion=other-tab",
|
|
]);
|
|
});
|
|
|
|
test("a failed request leaves the queue usable", async () => {
|
|
let calls = 0;
|
|
const client = new PlayerStateClient(async () => {
|
|
if (++calls === 1) throw new Error("Offline");
|
|
return { playlistVersion: "recovered", tracks: [] };
|
|
});
|
|
await assert.rejects(client.request("/api/state"), /Offline/);
|
|
assert.deepEqual((await client.request("/api/state")).tracks, []);
|
|
});
|
|
|
|
test("mismatched omitted tracks force a full refresh instead of stale reuse", async () => {
|
|
const paths = [];
|
|
const responses = [
|
|
{ playlistVersion: "before", tracks: [{ title: "Before" }] },
|
|
{ playlistVersion: "after", tracks: null },
|
|
{ playlistVersion: "after", tracks: [] },
|
|
];
|
|
const client = new PlayerStateClient(async (path) => {
|
|
paths.push(path);
|
|
return responses.shift();
|
|
});
|
|
await client.request("/api/state");
|
|
await assert.rejects(client.request("/api/state"), /Playlist cache/);
|
|
assert.deepEqual((await client.request("/api/state")).tracks, []);
|
|
assert.equal(paths[2], "/api/state");
|
|
});
|