Sångare -> Genrer: kategorin föreslår musikgenrer med toppartister/topplåtar
All checks were successful
build-and-push / build (push) Successful in 14s

Rättelse per Björn: tredje förslags-typen ska vara genrer, inte sångare.
Gemini föreslår genrer utifrån artisterna i gillat/spelat; varje genre
får 5 toppartister (filtrerade mot biblioteket, Hämta-knapp i modalen)
och 5 topplåtar (filtrerade mot gillalistan, YT-länkar). Genrekortet
lånar första toppartistens omslag. Gamla sångar-batcher renderas
fortfarande. DetailModal generaliserad.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01824ZrvG2mDYYrmwqypLNup
This commit is contained in:
2026-08-01 02:43:53 +02:00
parent 3ae0289f44
commit 43a41b300e
11 changed files with 107 additions and 105 deletions

View File

@@ -134,37 +134,38 @@ test('run(tracks): gillade + mest spelade in i prompten, egen batch-typ', async
assert.equal(engine.lastRun('mix'), null)
})
test('run(singers): unika sångare i prompt, filtrering mot bibliotek + gillat', async () => {
test('run(genres): artister i prompt, filtrering mot bibliotek + gillat', async () => {
const { engine, fetchImpl } = setup({
geminiResponse: JSON.stringify([
{
name: 'Floor Jansen',
motivation: 'Kraftfull sopran.',
name: 'Symphonic metal',
motivation: 'Storslaget och episkt.',
topArtists: ['Powerwolf', 'Epica'],
topTracks: [
{ name: 'Gimme! Gimme! Gimme!', artist: 'ABBA' },
{ name: 'Storm', artist: 'Floor Jansen' },
],
relatedArtists: ['Powerwolf', 'Epica'],
},
]),
})
const batch = await engine.run('manuell', 'singers')
const batch = await engine.run('manuell', 'genres')
assert.match(fetchImpl.prompt, /SÅNGARE/)
assert.match(fetchImpl.prompt, /ABBA/, 'sångare ur gillat ska in i prompten')
assert.match(fetchImpl.prompt, /1000mods/, 'sångare ur spelat ska in i prompten')
assert.match(fetchImpl.prompt, /GENRER/)
assert.match(fetchImpl.prompt, /ABBA/, 'artister ur gillat ska in i prompten')
assert.match(fetchImpl.prompt, /1000mods/, 'artister ur spelat ska in i prompten')
assert.equal(batch.type, 'singers')
const s = batch.items[0]
assert.equal(s.kind, 'singer')
assert.equal(s.topTracks.length, 1, 'gillad låt (Gimme! Gimme! Gimme!) ska filtreras bort')
assert.equal(s.topTracks[0].name, 'Storm')
assert.equal(batch.type, 'genres')
const g = batch.items[0]
assert.equal(g.kind, 'genre')
assert.equal(g.topTracks.length, 1, 'gillad låt (Gimme! Gimme! Gimme!) ska filtreras bort')
assert.equal(g.topTracks[0].name, 'Storm')
assert.deepEqual(
s.relatedArtists.map((a) => a.name),
g.topArtists.map((a) => a.name),
['Epica'],
'Powerwolf finns i biblioteket och ska filtreras bort',
)
assert.equal(s.relatedArtists[0].mbid, 'mbid-x')
assert.equal(g.topArtists[0].mbid, 'mbid-x')
assert.equal(g.poster, 'http://img/s.jpg', 'genrekortet lånar första toppartistens omslag')
})
test('run utan Gemini-nyckel ger begripligt fel', async () => {