143 lines
5.3 KiB
TypeScript
143 lines
5.3 KiB
TypeScript
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<number> {
|
|
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);
|
|
});
|
|
});
|