diff --git a/apps/web/e2e/upload-review.spec.ts b/apps/web/e2e/upload-review.spec.ts index 713401e..6d8dcc2 100644 --- a/apps/web/e2e/upload-review.spec.ts +++ b/apps/web/e2e/upload-review.spec.ts @@ -180,16 +180,31 @@ test('queue shows the current full destination after saving a changed source tem await expect(page.getByText('Artist/Album/Song.flac', { exact: true })).toHaveCount(0); }); -test('queue preview loads duration before play and plays signed audio', async ({ page }) => { +test('queue preview only requests audio after play', async ({ page }) => { const wav = previewWav(); - await page.route('**/api/v1/admin/uploads/files/*/stream?*', (route) => route.fulfill({ contentType: 'audio/wav', body: wav })); + let requested = 0; + let otherRequested = 0; + await page.route('**/api/v1/admin/uploads/files/*/stream?*', (route) => { + requested++; + return route.fulfill({ contentType: 'audio/wav', body: wav }); + }); + await page.route('**/api/v1/stream/mobile-preview', (route) => { + otherRequested++; + return route.fulfill({ contentType: 'audio/wav', body: wav }); + }); await setup(page, 'queue'); await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click(); const audio = page.locator('audio').first(); - await expect(audio).toHaveAttribute('preload', 'metadata'); - await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.duration)).toBe(2); + await expect(audio).toHaveAttribute('preload', 'none'); + await page.getByRole('button', { name: 'Свернуть пачку', exact: true }).click(); + await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click(); + expect(requested).toBe(0); + expect(otherRequested).toBe(0); await audio.evaluate((el: HTMLAudioElement) => el.play()); + await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.duration)).toBe(2); await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.currentTime)).toBeGreaterThan(0); + expect(requested).toBeGreaterThan(0); + expect(otherRequested).toBe(0); expect(await audio.evaluate((el: HTMLAudioElement) => el.error)).toBeNull(); }); @@ -210,6 +225,7 @@ test('queue preview explains HTTP failures and recovers on retry', async ({ page }); await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click(); const preview = page.locator('audio').first().locator('..'); + await preview.locator('audio').evaluate((el: HTMLAudioElement) => el.play().catch(() => undefined)); await expect(preview.getByRole('alert')).toHaveText('Не удалось загрузить аудио: HTTP 403.'); available = true; await preview.getByRole('button', { name: 'Повторить', exact: true }).click(); diff --git a/apps/web/src/features/uploads/AudioPreview.tsx b/apps/web/src/features/uploads/AudioPreview.tsx index 9352c98..ae636e6 100644 --- a/apps/web/src/features/uploads/AudioPreview.tsx +++ b/apps/web/src/features/uploads/AudioPreview.tsx @@ -45,10 +45,11 @@ export function AudioPreview({ url, name, active }: { url: string; name: string; setHttpStatus(null); void queryClient.invalidateQueries({ queryKey: ['admin-uploads'] }); audio.current?.load(); + void audio.current?.play().catch(() => { /* Native media errors are shown below. */ }); }; return
-