import assert from 'node:assert/strict' import { test } from 'node:test' import { AudioOutput } from './audio-output.js' import { parseWindowPreferences } from './window-settings.js' const devices = [{ id: 'hdmi', label: 'HDMI' }, { id: 'usb', label: 'USB' }] test('выбор сохраняется, применяется до запуска проигрывания и проверяет устройство', async () => { const applied: string[] = [] const saved: string[] = [] const output = new AudioOutput('', async () => devices, async (id) => { applied.push(id) }, (id) => { saved.push(id) }) await output.refresh() await output.select('hdmi') await output.prepare(async (id) => { applied.push(`prepare:${id}`) }) assert.deepEqual(applied, ['hdmi', 'prepare:hdmi']) assert.deepEqual(saved, ['hdmi']) assert.equal(output.selected, 'hdmi') await assert.rejects(output.select('missing'), /недоступно/) await assert.rejects(output.select({ id: 'usb' }), /недоступно/) assert.equal(output.selected, 'hdmi') }) test('ошибка переключения или сохранения возвращает прежний выход', async () => { for (const failure of ['apply', 'save']) { const applied: string[] = [] const output = new AudioOutput('hdmi', async () => devices, async (id) => { applied.push(id) if (id === 'usb' && failure === 'apply') throw new Error('switch failed') }, () => { if (failure === 'save') throw new Error('save failed') }) await output.refresh() await assert.rejects(output.select('usb'), /failed/) assert.equal(output.selected, 'hdmi') assert.deepEqual(applied, ['usb', 'hdmi']) } }) test('отключение устройства сбрасывает выбор, повторное подключение не меняет его', async () => { let available = devices const saved: string[] = [] const output = new AudioOutput('hdmi', async () => available, async () => {}, (id) => { saved.push(id) }) await output.refresh() assert.equal(output.selected, 'hdmi') available = [] await output.refresh() assert.equal(output.selected, '') assert.match(output.notice, /отключено/) assert.deepEqual(saved, ['']) available = devices await output.refresh() assert.equal(output.selected, '') await output.select('usb') assert.equal(output.notice, '') }) test('быстрые переключения и подготовка нового окна выполняются по порядку', async () => { const calls: string[] = [] let release: () => void = () => {} const held = new Promise((resolve) => { release = resolve }) const output = new AudioOutput('', async () => devices, async (id) => { calls.push(id) if (id === 'hdmi') await held }, () => {}) await output.refresh() const first = output.select('hdmi') const second = output.select('usb') const prepare = output.prepare(async (id) => { calls.push(`prepare:${id}`) }) await Promise.resolve() assert.deepEqual(calls, ['hdmi']) release() await Promise.all([first, second, prepare]) assert.deepEqual(calls, ['hdmi', 'usb', 'prepare:usb']) }) test('старые настройки совместимы, выбранный аудиовыход читается и валидируется', () => { const old = { version: 1, control: null, display: null } assert.equal(parseWindowPreferences(old).audioOutput, undefined) assert.equal(parseWindowPreferences({ ...old, audioOutput: 'hdmi' }).audioOutput, 'hdmi') assert.throws(() => parseWindowPreferences({ ...old, audioOutput: 123 })) assert.throws(() => parseWindowPreferences({ ...old, audioOutput: 'a'.repeat(1025) })) })