Files
psysonic/src/utils/album/deriveAlbumHeaderArtistRefs.test.ts
T
cucadmuh fb5a257735 fix(library): show album artist correctly in album grids (#1056) (#1057)
* fix(library): show album artist in album grids (#1056)

Prefer album-artist tags over track artist when building album rows from
the local index, and align grid cards with OpenSubsonic displayArtist.

* fix(library): align album artist in FTS, search, and offline paths (#1056)

Apply album-artist preference in FTS album dedupe and live search, fix
offline pin hydration order, and use albumArtistDisplayName in remaining
cheap UI/export/download call sites.

* docs(changelog): album artist grid fix for compilations (PR #1057)

* fix(library): parity guard and live-search album artist helper (#1056)

Align SQL ELSE branch with pick_album_group_artist trimming, add parity
test, and use albumArtistDisplayName in LiveSearch and MobileSearchOverlay.
2026-06-10 15:54:46 +03:00

88 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
albumArtistDisplayName,
deriveAlbumArtistRefs,
deriveAlbumHeaderArtistRefs,
} from './deriveAlbumHeaderArtistRefs';
import type { SubsonicAlbum } from '../../api/subsonicTypes';
import { makeSubsonicSong } from '@/test/helpers/factories';
const baseAlbum = (): SubsonicAlbum => ({
id: 'al-1',
name: 'Test Album',
artist: 'Joined A / B',
artistId: 'ar-first',
songCount: 2,
duration: 100,
});
describe('deriveAlbumArtistRefs', () => {
it('prefers the OpenSubsonic `artists` array when present', () => {
const album: SubsonicAlbum = {
...baseAlbum(),
artists: [{ id: 'a1', name: 'One' }, { id: 'a2', name: 'Two' }],
};
expect(deriveAlbumArtistRefs(album)).toEqual(album.artists);
});
it('uses legacy artist + artistId when no structured refs', () => {
expect(deriveAlbumArtistRefs(baseAlbum())).toEqual([{ id: 'ar-first', name: 'Joined A / B' }]);
});
it('omits id when artistId is blank', () => {
expect(deriveAlbumArtistRefs({ ...baseAlbum(), artistId: ' ', artist: 'Solo' }))
.toEqual([{ name: 'Solo' }]);
});
it('coerces a single-object OpenSubsonic artists payload', () => {
const album: SubsonicAlbum = {
...baseAlbum(),
artists: { id: 'a1', name: 'Solo' } as unknown as SubsonicAlbum['artists'],
};
expect(deriveAlbumArtistRefs(album)).toEqual([{ id: 'a1', name: 'Solo' }]);
});
it('prefers OpenSubsonic displayArtist over legacy artist', () => {
const album: SubsonicAlbum = {
...baseAlbum(),
artist: 'Groove Armada',
displayArtist: 'Underworld',
};
expect(deriveAlbumArtistRefs(album)).toEqual([{ id: 'ar-first', name: 'Underworld' }]);
expect(albumArtistDisplayName(album)).toBe('Underworld');
});
});
describe('deriveAlbumHeaderArtistRefs', () => {
it('prefers the album-level `artists` array when present', () => {
const album: SubsonicAlbum = {
...baseAlbum(),
artists: [{ id: 'a1', name: 'One' }, { id: 'a2', name: 'Two' }],
};
expect(deriveAlbumHeaderArtistRefs(album, [])).toEqual(album.artists);
});
it('falls back to the first song with `albumArtists`', () => {
const album = baseAlbum();
const songs = [
makeSubsonicSong({
albumId: album.id,
album: album.name,
albumArtists: [{ id: 'b1', name: 'Beta' }, { name: 'Gamma' }],
}),
];
expect(deriveAlbumHeaderArtistRefs(album, songs)).toEqual(songs[0].albumArtists);
});
it('uses legacy artist + artistId when no structured refs', () => {
const album = baseAlbum();
const songs = [makeSubsonicSong({ albumId: album.id, album: album.name })];
expect(deriveAlbumHeaderArtistRefs(album, songs)).toEqual([{ id: 'ar-first', name: 'Joined A / B' }]);
});
it('omits id when artistId is blank', () => {
const album: SubsonicAlbum = { ...baseAlbum(), artistId: ' ', artist: 'Solo' };
expect(deriveAlbumHeaderArtistRefs(album, [])).toEqual([{ name: 'Solo' }]);
});
});