99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { test } from "node:test";
|
|
|
|
import { importTracks, readImportSource, runImportCommand } from "../src/importers/index.js";
|
|
import type { CliDeps } from "../src/cli.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
|
|
};
|
|
}
|
|
|
|
test("auto-detects text imports by extension fallback", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "spotify-import-"));
|
|
const path = join(root, "tracks.csv");
|
|
await writeFile(path, "Radiohead - Karma Police\n");
|
|
|
|
const refs = await readImportSource(path);
|
|
|
|
assert.equal(refs[0].artist, "Radiohead");
|
|
assert.equal(refs[0].title, "Karma Police");
|
|
});
|
|
|
|
test("import creates a new private playlist for --playlist and records misses", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "spotify-import-"));
|
|
const path = join(root, "tracks.txt");
|
|
await writeFile(path, "Radiohead - Karma Police\nMissing Song\n");
|
|
let createdPublic: boolean | undefined;
|
|
let addedUris: string[] = [];
|
|
|
|
const result = await importTracks(path, { playlist: "New Mix", delayMs: 0 }, {
|
|
createPlaylist: async (_name, options) => {
|
|
createdPublic = options?.public;
|
|
return { id: "playlist-id", uri: "spotify:playlist:playlist-id", name: "New Mix", public: false, owner: { id: "owner" } };
|
|
},
|
|
searchTracks: async (query) => query.includes("Missing")
|
|
? []
|
|
: [{ id: "track-id", uri: "spotify:track:track-id", name: "Karma Police", artists: [{ name: "Radiohead" }] }],
|
|
addItemsToPlaylist: async (_playlistId, uris) => {
|
|
addedUris = uris;
|
|
return [{ snapshot_id: "snap" }];
|
|
}
|
|
});
|
|
|
|
assert.equal(createdPublic, false);
|
|
assert.deepEqual(addedUris, ["spotify:track:track-id"]);
|
|
assert.equal(result.found.length, 1);
|
|
assert.equal(result.missed.length, 1);
|
|
assert.deepEqual(result.added, { playlistId: "playlist-id", count: 1, snapshotIds: ["snap"] });
|
|
});
|
|
|
|
test("import updates explicit playlist id without creating a new playlist", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "spotify-import-"));
|
|
const path = join(root, "tracks.txt");
|
|
await writeFile(path, "Radiohead - Karma Police\n");
|
|
let created = false;
|
|
|
|
const result = await importTracks(path, { playlistId: "existing", delayMs: 0 }, {
|
|
createPlaylist: async () => {
|
|
created = true;
|
|
throw new Error("should not create");
|
|
},
|
|
searchTracks: async () => [{ id: "track-id", uri: "spotify:track:track-id", name: "Karma Police", artists: [{ name: "Radiohead" }] }],
|
|
addItemsToPlaylist: async () => [{ snapshot_id: "snap" }]
|
|
});
|
|
|
|
assert.equal(created, false);
|
|
assert.equal(result.added?.playlistId, "existing");
|
|
});
|
|
|
|
test("import command writes JSON result", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "spotify-import-"));
|
|
const path = join(root, "tracks.txt");
|
|
await writeFile(path, "Radiohead - Karma Police\n");
|
|
const io = createDeps();
|
|
|
|
await runImportCommand(
|
|
{ command: "import", positional: [path], playlistId: "existing", json: true },
|
|
io.deps,
|
|
{
|
|
createPlaylist: async () => { throw new Error("should not create"); },
|
|
searchTracks: async () => [{ id: "track-id", uri: "spotify:track:track-id", name: "Karma Police", artists: [{ name: "Radiohead" }] }],
|
|
addItemsToPlaylist: async () => [{ snapshot_id: "snap" }]
|
|
}
|
|
);
|
|
|
|
assert.equal(JSON.parse(io.stdout()).added.playlistId, "existing");
|
|
});
|