feat(spotify): implement milestone M3 api commands
This commit is contained in:
97
skills/spotify/tests/search.test.ts
Normal file
97
skills/spotify/tests/search.test.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
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/);
|
||||
});
|
||||
Reference in New Issue
Block a user