import { test, expect, type Page } from '@playwright/test'; import { setupTest, uploadFiles, ensureDocumentsListed, clickDocumentLink, expectViewerForFile, uploadAndDisplay, playTTSAndWaitForASecond, expectProcessingTransition, } from './helpers'; // Single-spec helpers kept local to avoid cluttering shared helpers: async function navigateToPdfPageViaNavigator(page: Page, targetPage: number) { // Navigator popover shows "X / Y" const navTrigger = page.getByRole('button', { name: /\d+\s*\/\s*\d+/ }); await expect(navTrigger).toBeVisible({ timeout: 10000 }); await navTrigger.click(); const input = page.getByLabel('Page number'); await expect(input).toBeVisible({ timeout: 10000 }); await input.fill(String(targetPage)); await input.press('Enter'); } async function countRenderedPdfPages(page: Page): Promise { return await page.locator('.react-pdf__Page').count(); } async function triggerViewportResize(page: Page, width: number, height: number) { await page.setViewportSize({ width, height }); } test.describe('Document link navigation by type', () => { test.beforeEach(async ({ page }, testInfo) => { await setupTest(page, testInfo); }); test('navigates to /pdf, /epub, /html and renders correct viewers', async ({ page }) => { test.setTimeout(120_000); // Upload documents await uploadFiles(page, 'sample.pdf', 'sample.epub', 'sample.txt'); // Ensure links exist await ensureDocumentsListed(page, ['sample.pdf', 'sample.epub', 'sample.txt']); // PDF await clickDocumentLink(page, 'sample.pdf'); await expectViewerForFile(page, 'sample.pdf'); await page.goBack(); // EPUB await clickDocumentLink(page, 'sample.epub'); await expectViewerForFile(page, 'sample.epub'); await page.goBack(); // TXT (HTML viewer) await clickDocumentLink(page, 'sample.txt'); await expectViewerForFile(page, 'sample.txt'); }); }); test.describe('PDF view modes and Navigator', () => { test.beforeEach(async ({ page }, testInfo) => { await setupTest(page, testInfo); }); test('restores the active PDF text highlight after narrowing the viewport', async ({ page }) => { test.setTimeout(120_000); await playTTSAndWaitForASecond(page, 'sample.pdf'); const textLayer = page.locator('.react-pdf__Page__textContent'); const textHighlight = page.locator('.pdf-text-highlight-overlay'); await expect(textLayer).toHaveCount(1); await expect(textLayer.locator('span')).not.toHaveCount(0); await expect(textHighlight).not.toHaveCount(0); await triggerViewportResize(page, 615, 796); await expect(textLayer).toHaveCount(1); await expect(textLayer.locator('span')).not.toHaveCount(0); await expect(textHighlight).not.toHaveCount(0); }); test('switches Single/Dual/Scroll modes and uses Navigator to change page', async ({ page }) => { test.setTimeout(120_000); // Open PDF viewer await uploadAndDisplay(page, 'sample.pdf'); // Open document settings (page-level settings) await page.getByRole('button', { name: 'Open settings' }).click(); // Page mode now uses pill-style radios; switch from Single Page to Two Pages await page.getByRole('radiogroup', { name: 'Page mode' }).getByRole('radio', { name: 'Two Pages' }).click(); await page.getByRole('button', { name: 'Close' }).click(); // Expect dual-page rendering (sample.pdf has >= 2 pages) const dualCount = await countRenderedPdfPages(page); expect(dualCount).toBeGreaterThanOrEqual(2); // Switch to Continuous Scroll await page.getByRole('button', { name: 'Open settings' }).click(); await page.getByRole('radiogroup', { name: 'Page mode' }).getByRole('radio', { name: 'Continuous Scroll' }).click(); await page.getByRole('button', { name: 'Close' }).click(); // Expect continuous scroll renders at least as many pages as dual mode const scrollCount = await countRenderedPdfPages(page); expect(scrollCount).toBeGreaterThanOrEqual(dualCount); // Use Navigator to go to a page (clamps to last if too large) await navigateToPdfPageViaNavigator(page, 999); // Navigator jump is configured to pause; ensure Play is visible then resume await expect(page.getByRole('button', { name: 'Play' })).toBeVisible({ timeout: 10000 }); await page.getByRole('button', { name: 'Play' }).click(); await expectProcessingTransition(page); }); }); test.describe('EPUB resize pauses TTS', () => { test.beforeEach(async ({ page }, testInfo) => { await setupTest(page, testInfo); }); test('resizing viewport pauses playback and play resumes after', async ({ page }) => { // Start playback on EPUB await playTTSAndWaitForASecond(page, 'sample.epub'); // Trigger a significant viewport resize to fire useEPUBResize await triggerViewportResize(page, 1200, 900); await page.waitForTimeout(750); // allow resize flag to propagate await triggerViewportResize(page, 900, 700); await page.waitForTimeout(750); // After resize, playback should have paused (Play button visible) const playButton = page.getByRole('button', { name: 'Play' }); await expect(playButton).toBeVisible({ timeout: 15000 }); await expect(playButton).toBeEnabled({ timeout: 15000 }); // Resume playback and ensure processing -> playing await playButton.click(); await expectProcessingTransition(page); }); });