import { describe, expect, it, beforeEach } from 'vitest'; import { useAuthStore } from '../../store/authStore'; import { getTransitionMode, transitionFlagsFor, setTransitionMode, type TransitionMode, } from './playbackTransition'; const MODES: TransitionMode[] = ['none', 'gapless', 'crossfade', 'autodj']; describe('getTransitionMode', () => { it('maps each flag combination to its mode', () => { expect(getTransitionMode({ gaplessEnabled: false, crossfadeEnabled: false, crossfadeTrimSilence: false })).toBe('none'); expect(getTransitionMode({ gaplessEnabled: true, crossfadeEnabled: false, crossfadeTrimSilence: false })).toBe('gapless'); expect(getTransitionMode({ gaplessEnabled: false, crossfadeEnabled: true, crossfadeTrimSilence: false })).toBe('crossfade'); expect(getTransitionMode({ gaplessEnabled: false, crossfadeEnabled: true, crossfadeTrimSilence: true })).toBe('autodj'); }); it('treats trim-silence as AutoDJ only while crossfade is on', () => { // Stale trim flag with crossfade off is still "none", not AutoDJ. expect(getTransitionMode({ gaplessEnabled: false, crossfadeEnabled: false, crossfadeTrimSilence: true })).toBe('none'); }); it('is total — gapless wins if both gapless and crossfade are set', () => { expect(getTransitionMode({ gaplessEnabled: true, crossfadeEnabled: true, crossfadeTrimSilence: true })).toBe('gapless'); }); }); describe('transitionFlagsFor', () => { it('round-trips through getTransitionMode for every mode', () => { for (const mode of MODES) { expect(getTransitionMode(transitionFlagsFor(mode))).toBe(mode); } }); it('never sets more than one independent behaviour at once', () => { for (const mode of MODES) { const f = transitionFlagsFor(mode); // crossfade and gapless are the two independent toggles; trim only rides on crossfade expect(f.gaplessEnabled && f.crossfadeEnabled).toBe(false); if (f.crossfadeTrimSilence) expect(f.crossfadeEnabled).toBe(true); } }); }); describe('setTransitionMode', () => { beforeEach(() => { setTransitionMode('none'); }); it('applies the flags atomically and enforces exclusivity', () => { setTransitionMode('crossfade'); let s = useAuthStore.getState(); expect(s.crossfadeEnabled).toBe(true); expect(s.crossfadeTrimSilence).toBe(false); expect(s.gaplessEnabled).toBe(false); setTransitionMode('autodj'); s = useAuthStore.getState(); expect(s.crossfadeEnabled).toBe(true); expect(s.crossfadeTrimSilence).toBe(true); expect(s.gaplessEnabled).toBe(false); setTransitionMode('gapless'); s = useAuthStore.getState(); expect(s.gaplessEnabled).toBe(true); expect(s.crossfadeEnabled).toBe(false); expect(s.crossfadeTrimSilence).toBe(false); setTransitionMode('none'); s = useAuthStore.getState(); expect(s.gaplessEnabled).toBe(false); expect(s.crossfadeEnabled).toBe(false); expect(s.crossfadeTrimSilence).toBe(false); }); it('preserves crossfadeSecs when switching between crossfade and autodj', () => { useAuthStore.getState().setCrossfadeSecs(7); setTransitionMode('crossfade'); setTransitionMode('autodj'); setTransitionMode('crossfade'); expect(useAuthStore.getState().crossfadeSecs).toBe(7); }); });