import assert from "node:assert/strict"; import { test } from "node:test"; import { mapPlaylist, mapTrack, runListPlaylistsCommand, runSearchCommand } from "../src/search.js"; import type { CliDeps } from "../src/cli.js"; import type { SpotifyPlaylist, SpotifyTrack } from "../src/types.js"; function createDeps(): { deps: CliDeps; stdout: () => string; stderr: () => string } { let stdout = ""; let stderr = ""; return { deps: { stdout: { write: (chunk: string) => { stdout += chunk; return true; } }, stderr: { write: (chunk: string) => { stderr += chunk; return true; } } }, stdout: () => stdout, stderr: () => stderr }; } const track: SpotifyTrack = { id: "track-id", uri: "spotify:track:track-id", name: "Karma Police", artists: [{ name: "Radiohead" }], album: { name: "OK Computer" }, external_urls: { spotify: "https://open.spotify.com/track/track-id" } }; const playlist: SpotifyPlaylist = { id: "playlist-id", uri: "spotify:playlist:playlist-id", name: "Private Mix", public: false, owner: { id: "owner-id", display_name: "Owner" }, external_urls: { spotify: "https://open.spotify.com/playlist/playlist-id" } }; test("maps raw track to flattened output DTO", () => { assert.deepEqual(mapTrack(track), { id: "track-id", uri: "spotify:track:track-id", name: "Karma Police", artists: ["Radiohead"], album: "OK Computer", externalUrl: "https://open.spotify.com/track/track-id" }); }); test("search command clamps limit and writes JSON", async () => { const io = createDeps(); let observedLimit = 0; const code = await runSearchCommand( { command: "search", positional: ["Karma", "Police"], json: true, public: false, limit: "99" }, io.deps, { searchTracks: async (_query, limit) => { observedLimit = limit; return [track]; } } ); assert.equal(code, 0); assert.equal(observedLimit, 10); assert.equal(JSON.parse(io.stdout()).tracks[0].externalUrl, "https://open.spotify.com/track/track-id"); assert.equal(io.stderr(), ""); }); test("maps playlist to flattened output DTO", () => { assert.deepEqual(mapPlaylist(playlist), { id: "playlist-id", name: "Private Mix", public: false, owner: "Owner", externalUrl: "https://open.spotify.com/playlist/playlist-id" }); }); test("list playlists command clamps limit and writes human output", async () => { const io = createDeps(); let observed = { limit: 0, offset: -1 }; const code = await runListPlaylistsCommand( { command: "list-playlists", positional: [], json: false, public: false, limit: "200", offset: "-5" }, io.deps, { listPlaylists: async (limit, offset) => { observed = { limit, offset }; return [playlist]; } } ); assert.equal(code, 0); assert.deepEqual(observed, { limit: 50, offset: 0 }); assert.match(io.stdout(), /playlist-id \\| private \\| Owner \\| Private Mix/); });