Milstolpe 2+3: ikon, sök (artist/album/låt) och Hämta-till-Lidarr
All checks were successful
build-and-push / build (push) Successful in 16s
All checks were successful
build-and-push / build (push) Successful in 16s
- Ikon: SVG-favicon (indigo-gradient + balknot), används i topbar, login och som favicon - GET /api/search: artister/album via Lidarrs metadata-API (funkar även när musicbrainz.org är nere), låtar via MusicBrainz recording-sök; 503 med svenskt felmeddelande när källan inte svarar - POST /api/add: slår upp via lidarr:<mbid>, artist läggs bevakad med searchForMissingAlbums, album bevakat med searchForNewAlbum (artisten följer med obevakad), låtar mappas till album/artist; 'already' när det redan finns - Söksida med Jellyseerr-lik kortgrid: poster/fallback, typ-badge, Hämta-knapp med busy/klar/finns-lägen; sökfältet i topbaren aktivt - 7 nya tester (mappning + rutter med stubbat Lidarr), totalt 11 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01824ZrvG2mDYYrmwqypLNup
This commit is contained in:
147
backend/test/search.test.js
Normal file
147
backend/test/search.test.js
Normal file
@@ -0,0 +1,147 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { buildApp } from '../src/app.js'
|
||||
import { mapLidarrSearch } from '../src/mapping.js'
|
||||
|
||||
const config = {
|
||||
appPassword: 'testlösen',
|
||||
sessionSecret: 'x'.repeat(32),
|
||||
lidarr: { url: 'http://stub', apiKey: 'k', qualityProfileId: 3, metadataProfileId: 1, rootFolder: '/music' },
|
||||
jellyfin: { url: '', apiKey: '' },
|
||||
gemini: { apiKey: '', model: '' },
|
||||
}
|
||||
|
||||
const powerwolf = {
|
||||
foreignArtistId: 'mbid-artist-1',
|
||||
artistName: 'Powerwolf',
|
||||
disambiguation: 'tysk powermetal',
|
||||
images: [{ coverType: 'poster', remoteUrl: 'http://img/poster.jpg' }],
|
||||
}
|
||||
|
||||
const album = {
|
||||
foreignAlbumId: 'mbid-album-1',
|
||||
title: 'The Sacrament of Sin',
|
||||
releaseDate: '2018-07-20',
|
||||
images: [],
|
||||
artist: { ...powerwolf },
|
||||
}
|
||||
|
||||
async function loggedIn(app) {
|
||||
const login = await app.inject({ method: 'POST', url: '/api/login', payload: { password: 'testlösen' } })
|
||||
return login.headers['set-cookie']
|
||||
}
|
||||
|
||||
test('mapLidarrSearch formar artist- och albumkort', () => {
|
||||
const results = [{ artist: powerwolf }, { album }]
|
||||
const artists = mapLidarrSearch(results, 'artist')
|
||||
assert.equal(artists.length, 1)
|
||||
assert.deepEqual(artists[0], {
|
||||
kind: 'artist',
|
||||
name: 'Powerwolf',
|
||||
secondary: 'tysk powermetal',
|
||||
year: '',
|
||||
mbid: 'mbid-artist-1',
|
||||
poster: 'http://img/poster.jpg',
|
||||
inLibrary: false,
|
||||
})
|
||||
const albums = mapLidarrSearch(results, 'album')
|
||||
assert.equal(albums[0].year, '2018')
|
||||
assert.equal(albums[0].secondary, 'Powerwolf')
|
||||
})
|
||||
|
||||
test('GET /api/search kräver inloggning', async () => {
|
||||
const app = buildApp(config, { lidarr: {}, musicbrainz: {} })
|
||||
const res = await app.inject({ method: 'GET', url: '/api/search?q=powerwolf' })
|
||||
assert.equal(res.statusCode, 401)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
test('GET /api/search returnerar mappade träffar', async () => {
|
||||
const app = buildApp(config, {
|
||||
lidarr: { search: async () => [{ artist: powerwolf }] },
|
||||
musicbrainz: {},
|
||||
})
|
||||
const cookie = await loggedIn(app)
|
||||
const res = await app.inject({ method: 'GET', url: '/api/search?q=powerwolf&type=artist', headers: { cookie } })
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(res.json()[0].name, 'Powerwolf')
|
||||
await app.close()
|
||||
})
|
||||
|
||||
test('GET /api/search ger 503 när källan är nere', async () => {
|
||||
const app = buildApp(config, {
|
||||
lidarr: { search: async () => { throw new Error('nere') } },
|
||||
musicbrainz: {},
|
||||
})
|
||||
const cookie = await loggedIn(app)
|
||||
const res = await app.inject({ method: 'GET', url: '/api/search?q=x&type=artist', headers: { cookie } })
|
||||
assert.equal(res.statusCode, 503)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
test('POST /api/add lägger till artist med profiler och bevakning', async () => {
|
||||
let sent = null
|
||||
const app = buildApp(config, {
|
||||
lidarr: {
|
||||
search: async (term) => {
|
||||
assert.equal(term, 'lidarr:mbid-artist-1')
|
||||
return [{ artist: { ...powerwolf } }]
|
||||
},
|
||||
addArtist: async (payload) => { sent = payload; return { id: 7 } },
|
||||
},
|
||||
musicbrainz: {},
|
||||
})
|
||||
const cookie = await loggedIn(app)
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/add',
|
||||
headers: { cookie },
|
||||
payload: { kind: 'artist', mbid: 'mbid-artist-1' },
|
||||
})
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.deepEqual(res.json(), { ok: true, already: false })
|
||||
assert.equal(sent.qualityProfileId, 3)
|
||||
assert.equal(sent.rootFolderPath, '/music')
|
||||
assert.equal(sent.monitored, true)
|
||||
assert.equal(sent.addOptions.searchForMissingAlbums, true)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
test('POST /api/add med låt går via albumet', async () => {
|
||||
let sent = null
|
||||
const app = buildApp(config, {
|
||||
lidarr: {
|
||||
search: async () => [{ album: { ...album } }],
|
||||
addAlbum: async (payload) => { sent = payload; return { id: 9 } },
|
||||
},
|
||||
musicbrainz: {},
|
||||
})
|
||||
const cookie = await loggedIn(app)
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/add',
|
||||
headers: { cookie },
|
||||
payload: { kind: 'track', mbid: 'rec-1', artistMbid: 'mbid-artist-1', albumMbid: 'mbid-album-1' },
|
||||
})
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(sent.monitored, true)
|
||||
assert.equal(sent.artist.rootFolderPath, '/music')
|
||||
assert.equal(sent.addOptions.searchForNewAlbum, true)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
test('POST /api/add svarar already för befintlig artist', async () => {
|
||||
const app = buildApp(config, {
|
||||
lidarr: { search: async () => [{ artist: { ...powerwolf, id: 12 } }] },
|
||||
musicbrainz: {},
|
||||
})
|
||||
const cookie = await loggedIn(app)
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/add',
|
||||
headers: { cookie },
|
||||
payload: { kind: 'artist', mbid: 'mbid-artist-1' },
|
||||
})
|
||||
assert.deepEqual(res.json(), { ok: true, already: true })
|
||||
await app.close()
|
||||
})
|
||||
Reference in New Issue
Block a user