Files
KeelrLeek 8ede6a8adf Phase 1: preview contracts and pure session core, 61 tests
src/lib/preview/ — framework-free ESM modules, per design §12–14:
- contracts.js: versioned manifest/item/source-ref factories; signed
  URLs structurally excluded from manifests; Apple identity first-class.
- lease.js: discriminated MediaLease union; computeSafeForMs derives
  lifetimes provider-clock-first with fallback/contradiction handling
  (margins are ADRs backed by Phase 0 soak evidence).
- redact.js: URL redaction (host+hash+exp only) and the HTTPS + exact
  host allowlist gate applied to initial URLs and every redirect.
- manifest.js: artist (rank order, exact-id dedupe), album (disc/track
  sort, context inheritance) and fixture builders — pure, no fetching.
- session.js: reducer with session/generation guards on every async
  action; keyed active item with derived playable indices/cursor;
  auto-advance under fresh generations; close is terminal.
- resolver.js: PreviewResolver contract + scripted fixture resolver
  with classified failures (stale_lease/not_found/network/…).
- transport.js: transport seam + deterministic fake (manual ticks).
- focus.js: revision gateway (all main-player entry points; focus-
  internal tag) and the coordinator — acquisition only via a
  generation-bound silence ack, restore only with revisions unchanged.

tests/preview/*.test.mjs run via `npm test` (node --test): 61 passing,
covering the full Phase 1 list in IMPLEMENTATION-PLAN §6 including the
exit gate: stale lease/play events are inert, no restoration after any
simulated main command, and no component renders anywhere.
2026-07-22 18:29:03 -05:00

123 lines
4.7 KiB
JavaScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { AVAILABILITY, isValidManifest } from "../../src/lib/preview/contracts.js";
import { buildArtistManifest, buildAlbumManifest, buildFixtureManifest } from "../../src/lib/preview/manifest.js";
const T0 = 1_700_000_000_000;
const catalogTrack = (id, over = {}) => ({
id,
title: `Track ${id}`,
artist: "Röyksopp",
album: "Melody A.M.",
album_id: 9,
cover: `cover-${id}`,
duration_secs: 219,
preview: `https://cdnt-preview.dzcdn.net/x-${id}.mp3?hdnea=exp=1784761537~hmac=aa`,
track_no: 1,
disk_number: 1,
unreleased: false,
...over,
});
test("artist manifest: rank order kept, exact provider-id dupes collapse", () => {
const m = buildArtistManifest({
artist: { id: 480, name: "Röyksopp", picture: "pic" },
popularTracks: [catalogTrack(1), catalogTrack(2), catalogTrack(1), catalogTrack(3)],
createdAtMs: T0,
});
assert.equal(m.items.length, 3); // dupe of id 1 collapsed
assert.deepEqual(m.items.map((i) => i.sources[0].providerTrackId), ["1", "2", "3"]);
assert.deepEqual(m.items.map((i) => i.sourceOrdinal), [0, 1, 2]);
assert.equal(m.context.kind, "artist");
assert.equal(m.context.sourceTrackCount, 4); // source count is truthful
assert.ok(isValidManifest(m));
});
test("artist manifest: same title, different provider ids do NOT collapse", () => {
const m = buildArtistManifest({
artist: { id: 480, name: "Röyksopp" },
popularTracks: [catalogTrack(1, { title: "Same" }), catalogTrack(2, { title: "Same" })],
createdAtMs: T0,
});
assert.equal(m.items.length, 2);
});
test("availability from catalog rows: preview/empty/unreleased", () => {
const m = buildArtistManifest({
artist: { id: 1, name: "A" },
popularTracks: [
catalogTrack(1),
catalogTrack(2, { preview: "" }),
catalogTrack(3, { preview: undefined }),
catalogTrack(4, { unreleased: true }),
],
createdAtMs: T0,
});
assert.deepEqual(
m.items.map((i) => i.initialAvailability),
[AVAILABILITY.AVAILABLE, AVAILABILITY.NOT_PROVIDED, AVAILABILITY.NOT_PROVIDED, AVAILABILITY.UNRELEASED]
);
// unreleased rows lose their mutating actions
assert.equal(m.items[3].actions.playFull, false);
assert.equal(m.items[3].actions.save, false);
});
test("no signed URL survives into the manifest", () => {
const m = buildArtistManifest({
artist: { id: 1, name: "A" },
popularTracks: [catalogTrack(1)],
createdAtMs: T0,
});
const json = JSON.stringify(m);
assert.ok(!json.includes("hdnea"), "signed URL leaked into manifest");
assert.ok(!json.includes("cdnt-preview"), "media host leaked into manifest");
});
test("album manifest: disc/track sort with stable fallback + context inheritance", () => {
const m = buildAlbumManifest({
album: { id: 77, title: "The Wall", artist: "Pink Floyd", cover: "wall.jpg" },
tracks: [
catalogTrack(21, { disk_number: 2, track_no: 1, album: "", album_id: null, cover: null }),
catalogTrack(11, { disk_number: 1, track_no: 1 }),
catalogTrack(12, { disk_number: 1, track_no: 2 }),
catalogTrack(13, { disk_number: null, track_no: null }), // sorts by response order within disc 1
],
createdAtMs: T0,
});
assert.deepEqual(m.items.map((i) => i.sources[0].providerTrackId), ["13", "11", "12", "21"]);
const disc2 = m.items[3];
assert.equal(disc2.album, "The Wall"); // inherited
assert.equal(disc2.albumId, "77");
assert.equal(disc2.artwork, "wall.jpg");
assert.equal(m.context.sourceTrackCount, 4);
});
test("fixture manifest: playlist duplicates keep distinct sessionKeys, shared recordingKey", () => {
const m = buildFixtureManifest({
kind: "playlist",
rows: [
{ providerTrackId: "9", title: "Song" },
{ providerTrackId: "8", title: "Other" },
{ providerTrackId: "9", title: "Song" }, // duplicate occurrence
],
createdAtMs: T0,
});
assert.equal(m.items.length, 3);
assert.notEqual(m.items[0].sessionKey, m.items[2].sessionKey);
assert.equal(m.items[0].recordingKey, m.items[2].recordingKey);
assert.ok(isValidManifest(m));
});
test("fixture manifest: apple identity is a first-class source ref", () => {
const m = buildFixtureManifest({
rows: [{ provider: "apple", providerTrackId: "ap-123", isrc: "USX9P1234567", matchConfidence: "isrc", title: "X" }],
createdAtMs: T0,
});
const src = m.items[0].sources[0];
assert.equal(src.provider, "apple");
assert.equal(src.providerTrackId, "ap-123");
assert.equal(src.matchConfidence, "isrc");
});