Source: human-feedback note 01KVDYV3A35B57N15CRBQDXPCH (project/reddit-spotify-linker, 2026-06-18) — "remove the musicbrainz integration and just use spotify"; a google search for "<name> bandcamp" fallback; and "would a local llm be better able to categorise these ... include instructions for running something suitable via ollama (16GB M2)". - Remove MusicBrainz entirely (viaMusicBrainz + url-rels + rate-gate; lib relUrls/mbResult). Spotify is now the only music API; it both gates by exact-name match and supplies the direct artist link. - Optional ollama LLM gate (OLLAMA_URL enables it, OLLAMA_MODEL default qwen2.5:3b) called over plain HTTP -> stays zero npm-dep. It classifies which candidates are real artists/albums (the matching-quality lever). Pure prompt/parse logic in new llm.js (unit-tested in llm.test.js); the fetch + resolveAll gate wiring live in resolver.js. - A confirmed name links to its direct Spotify page when available, else a Google search for "<name> bandcamp". New "google" primary platform rendered by the extension (styles.css blue accent + platform-aware link title in content.js). - README: drop MusicBrainz; document the two gates + a runnable local-LLM setup for a 16GB MacBook M2. AGENTS.md: flip the old "no ML/NER" standing decision per the human override. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
2.8 KiB
JavaScript
66 lines
2.8 KiB
JavaScript
// Unit tests for the resolver's pure logic (run with `node --test`). Zero-dep.
|
|
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { norm, googleSearch, pickArtist, linkResult, isSearchUrl, isHttpUrl } from "./lib.js";
|
|
|
|
test("norm lowercases, trims, NFKC-normalizes", () => {
|
|
assert.equal(norm(" Cerebral Bore "), "cerebral bore");
|
|
assert.equal(norm("DEVOURMENT"), "devourment");
|
|
});
|
|
|
|
test("pickArtist matches case-insensitively, rejects non-matches", () => {
|
|
const items = [{ name: "Cattle Decapitation" }, { name: "Cerebral Bore" }];
|
|
assert.equal(pickArtist("cerebral bore", items)?.name, "Cerebral Bore");
|
|
assert.equal(pickArtist("CATTLE DECAPITATION", items)?.name, "Cattle Decapitation");
|
|
assert.equal(pickArtist("Notarealband", items), null);
|
|
});
|
|
|
|
test("pickArtist tolerates empty / garbage input", () => {
|
|
assert.equal(pickArtist("x", null), null);
|
|
assert.equal(pickArtist("x", []), null);
|
|
assert.equal(pickArtist("x", [null, { name: "y" }]), null);
|
|
});
|
|
|
|
test("googleSearch points at a Google query for '<name> bandcamp', url-encoded", () => {
|
|
const u = googleSearch("Cerebral Bore");
|
|
assert.match(u, /^https:\/\/www\.google\.com\/search\?q=/);
|
|
assert.ok(u.includes("Cerebral%20Bore%20bandcamp"));
|
|
assert.ok(googleSearch("A&B").includes("A%26B"));
|
|
});
|
|
|
|
test("linkResult prefers a direct Spotify url, primary = spotify", () => {
|
|
const r = linkResult("Devourment", "https://open.spotify.com/artist/abc");
|
|
assert.equal(r.spotify, "https://open.spotify.com/artist/abc");
|
|
assert.deepEqual(r.primary, { platform: "spotify", url: "https://open.spotify.com/artist/abc" });
|
|
assert.equal(r.google, undefined);
|
|
});
|
|
|
|
test("linkResult falls back to Google->Bandcamp when there is no direct Spotify url", () => {
|
|
const r = linkResult("Some Local Band", null);
|
|
assert.equal(r.spotify, undefined);
|
|
assert.equal(r.primary.platform, "google");
|
|
assert.match(r.primary.url, /^https:\/\/www\.google\.com\/search\?q=/);
|
|
assert.equal(r.google, r.primary.url);
|
|
});
|
|
|
|
test("linkResult rejects non-http(s) / search Spotify urls and falls back to Google", () => {
|
|
for (const bad of ["javascript:alert(1)", "ftp://x/y", "https://open.spotify.com/search/X", "not a url"]) {
|
|
const r = linkResult("X", bad);
|
|
assert.equal(r.primary.platform, "google", `expected fallback for ${bad}`);
|
|
}
|
|
});
|
|
|
|
test("isSearchUrl detects /search urls", () => {
|
|
assert.equal(isSearchUrl("https://open.spotify.com/search/X"), true);
|
|
assert.equal(isSearchUrl("https://open.spotify.com/artist/abc"), false);
|
|
});
|
|
|
|
test("isHttpUrl accepts http/https only", () => {
|
|
assert.equal(isHttpUrl("https://x.com"), true);
|
|
assert.equal(isHttpUrl("http://x.com"), true);
|
|
assert.equal(isHttpUrl("javascript:alert(1)"), false);
|
|
assert.equal(isHttpUrl("ftp://x/y"), false);
|
|
assert.equal(isHttpUrl("not a url"), false);
|
|
assert.equal(isHttpUrl(null), false);
|
|
});
|