Files
Psychotoxical-psysonic/src/utils/resolveReplayGainDb.test.ts
T
Frank Stellmacher 9fac6eb490 refactor(player): E.42 — migrate playerStore re-exports to direct imports (#607)
Migrates ~74 call sites away from the playerStore re-export shims that
were kept during M0–E.41 to avoid touching 30+ imports per PR. Now
that the bigger refactor work is done, each helper goes back to its
real home:

- `initAudioListeners`, `installQueueUndoHotkey`, `flushPlayQueuePosition`
  → from their own store modules
- `getPlaybackProgressSnapshot`, `subscribePlaybackProgress`,
  `PlaybackProgressSnapshot` → from `playbackProgress`
- `resolveReplayGainDb`, `shuffleArray`, `songToTrack`
  → from `utils/*`
- `_resetQueueUndoStacksForTest`, `consumePendingQueueListScrollTop`,
  `registerQueueListScrollTopReader` → from `queueUndo`
- `PlayerState`, `Track` types → from `playerStoreTypes`

Drops the corresponding 13 re-export stubs from `playerStore.ts` and
the now-unused imports. Also drops dead section banners + per-wrapper
comments above one-line action delegates. Trims one stale "(separate
PR)" note in `transportLightActions.ts` since that follow-up landed
in E.39.

`playerStore.ts`: 180 → 112 LOC (−68). Down from Phase E's starting
3732 LOC.

`bootstrap.test.ts` mock target updated from `../store/playerStore`
to `../store/queueUndoHotkey` to keep the spy reachable after the
import change.
2026-05-12 22:46:13 +02:00

75 lines
3.1 KiB
TypeScript

/**
* Pure-helper characterization for `resolveReplayGainDb`.
*
* Picks track vs album gain based on mode + adjacent queue neighbours.
* Originally lived in `playerStore.ts`; extracted in M0 of the frontend
* refactor (2026-05-12).
*/
import type { Track } from '../store/playerStoreTypes';
import { describe, expect, it } from 'vitest';
import { resolveReplayGainDb } from './resolveReplayGainDb';
describe('resolveReplayGainDb', () => {
const t = (overrides: Partial<Track> = {}): Track => ({
id: 'x',
title: 'x',
artist: 'x',
album: 'a',
albumId: 'a-1',
duration: 100,
...overrides,
});
it('returns null when ReplayGain is disabled', () => {
const track = t({ replayGainTrackDb: -6, replayGainAlbumDb: -7 });
expect(resolveReplayGainDb(track, null, null, false, 'track')).toBeNull();
expect(resolveReplayGainDb(track, null, null, false, 'album')).toBeNull();
expect(resolveReplayGainDb(track, null, null, false, 'auto')).toBeNull();
});
it('mode=track uses the track gain', () => {
const track = t({ replayGainTrackDb: -6, replayGainAlbumDb: -7 });
expect(resolveReplayGainDb(track, null, null, true, 'track')).toBe(-6);
});
it('mode=album uses the album gain when present', () => {
const track = t({ replayGainTrackDb: -6, replayGainAlbumDb: -7 });
expect(resolveReplayGainDb(track, null, null, true, 'album')).toBe(-7);
});
it('mode=album falls back to track gain when album is missing', () => {
const track = t({ replayGainTrackDb: -6 });
expect(resolveReplayGainDb(track, null, null, true, 'album')).toBe(-6);
});
it('mode=auto picks album gain when the prev neighbour shares the albumId', () => {
const track = t({ albumId: 'shared', replayGainTrackDb: -6, replayGainAlbumDb: -8 });
const prev = t({ albumId: 'shared' });
expect(resolveReplayGainDb(track, prev, null, true, 'auto')).toBe(-8);
});
it('mode=auto picks album gain when the next neighbour shares the albumId', () => {
const track = t({ albumId: 'shared', replayGainTrackDb: -6, replayGainAlbumDb: -8 });
const next = t({ albumId: 'shared' });
expect(resolveReplayGainDb(track, null, next, true, 'auto')).toBe(-8);
});
it('mode=auto picks track gain when neither neighbour shares the albumId', () => {
const track = t({ albumId: 'a-1', replayGainTrackDb: -6, replayGainAlbumDb: -8 });
const other = t({ albumId: 'a-2' });
expect(resolveReplayGainDb(track, other, other, true, 'auto')).toBe(-6);
});
it('mode=auto treats a missing albumId as no-album-match (returns track gain)', () => {
const track = t({ albumId: '', replayGainTrackDb: -6, replayGainAlbumDb: -8 } as Track);
const prev = t({ albumId: '' } as Track);
expect(resolveReplayGainDb(track, prev, null, true, 'auto')).toBe(-6);
});
it('returns null when both gains are missing', () => {
const track = t({});
expect(resolveReplayGainDb(track, null, null, true, 'track')).toBeNull();
expect(resolveReplayGainDb(track, null, null, true, 'album')).toBeNull();
expect(resolveReplayGainDb(track, null, null, true, 'auto')).toBeNull();
});
});