tests: harden pdf readiness waits and extend tts/pdf timeouts
This commit is contained in:
parent
3f17874fe5
commit
e70b3619e0
8 changed files with 31 additions and 15 deletions
|
|
@ -443,7 +443,7 @@ export default function PDFViewerPage() {
|
|||
</div>
|
||||
) : null}
|
||||
{isLoading || !isParseReady || !isPdfViewerReady ? (
|
||||
<div className="absolute inset-0 z-10">
|
||||
<div className="absolute inset-0 z-10" data-testid="pdf-status-loader">
|
||||
{renderPdfStatusLoader()}
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ test.describe('Accessibility smoke', () => {
|
|||
});
|
||||
|
||||
test('TTS controls expose aria labels and are keyboard focusable', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
// TTS bar present
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ async function resetAudiobookIfPresent(page: Page, bookId?: string) {
|
|||
}
|
||||
|
||||
test('exports full MP3 audiobook for PDF using mocked 10s TTS sample', async ({ page }, testInfo) => {
|
||||
test.setTimeout(60_000);
|
||||
test.setTimeout(120_000);
|
||||
|
||||
// Ensure TTS is mocked and app is ready
|
||||
await setupTest(page, testInfo);
|
||||
|
|
@ -382,7 +382,7 @@ test('exports partial MP3 audiobook for EPUB using mocked 10s TTS sample', async
|
|||
});
|
||||
|
||||
test('exports a single MP3 audiobook PDF page via chapters menu', async ({ page }, testInfo) => {
|
||||
test.setTimeout(60_000);
|
||||
test.setTimeout(120_000);
|
||||
await setupTest(page, testInfo);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -413,6 +413,7 @@ test('exports a single MP3 audiobook PDF page via chapters menu', async ({ page
|
|||
});
|
||||
|
||||
test('resets all MP3 audiobook PDF pages', async ({ page }, testInfo) => {
|
||||
test.setTimeout(120_000);
|
||||
await setupTest(page, testInfo);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -451,7 +452,7 @@ test('resets all MP3 audiobook PDF pages', async ({ page }, testInfo) => {
|
|||
});
|
||||
|
||||
test('regenerates a single MP3 audiobook PDF page and exports full audiobook', async ({ page }, testInfo) => {
|
||||
test.setTimeout(60_000);
|
||||
test.setTimeout(120_000);
|
||||
await setupTest(page, testInfo);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -525,7 +526,7 @@ test('regenerates a single MP3 audiobook PDF page and exports full audiobook', a
|
|||
});
|
||||
|
||||
test('resumes audiobook when a chapter is missing and full download succeeds (PDF)', async ({ page }, testInfo) => {
|
||||
test.setTimeout(60_000);
|
||||
test.setTimeout(120_000);
|
||||
await setupTest(page, testInfo);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
|
|
|
|||
|
|
@ -24,17 +24,23 @@ function sha256HexOfFile(filePath: string) {
|
|||
|
||||
async function waitForPdfViewerReady(page: Page, timeout = 60000) {
|
||||
await expect(page).toHaveURL(/\/pdf\/[A-Za-z0-9._%-]+$/, { timeout: Math.min(timeout, 20000) });
|
||||
const loader = page.getByTestId('pdf-status-loader').first();
|
||||
const parseFailedBanner = page.getByText('PDF parsing failed. Retry to continue.').first();
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const parseFailed = await parseFailedBanner.isVisible().catch(() => false);
|
||||
if (parseFailed) return 'failed';
|
||||
|
||||
const documentVisible = await page.locator('.react-pdf__Document').first().isVisible().catch(() => false);
|
||||
if (documentVisible) return true;
|
||||
const pageVisible = await page.locator('.react-pdf__Page').first().isVisible().catch(() => false);
|
||||
if (pageVisible) return true;
|
||||
const canvasVisible = await page.locator('.react-pdf__Page canvas').first().isVisible().catch(() => false);
|
||||
if (canvasVisible) return true;
|
||||
return false;
|
||||
|
||||
const hasRenderedPdf = documentVisible || pageVisible || canvasVisible;
|
||||
const loaderVisible = await loader.isVisible().catch(() => false);
|
||||
if (hasRenderedPdf && !loaderVisible) return 'ready';
|
||||
return 'loading';
|
||||
}, { timeout })
|
||||
.toBe(true);
|
||||
.toBe('ready');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -396,7 +402,7 @@ export async function expectViewerForFile(page: Page, fileName: string) {
|
|||
if (lower.endsWith('.pdf') || lower.endsWith('.docx')) {
|
||||
// DOCX converts to PDF, so viewer expectations are PDF
|
||||
await expect(page).toHaveURL(/\/pdf\/[A-Za-z0-9._%-]+$/);
|
||||
await expect(page.locator('.react-pdf__Document')).toBeVisible({ timeout: 15000 });
|
||||
await waitForPdfViewerReady(page, 60000);
|
||||
return;
|
||||
}
|
||||
if (lower.endsWith('.epub')) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ test.describe('Landing and app routing', () => {
|
|||
});
|
||||
|
||||
test('documents back link returns to /app', async ({ page }, testInfo) => {
|
||||
test.setTimeout(120_000);
|
||||
await setupTest(page, testInfo);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ test.describe('Document link navigation by type', () => {
|
|||
});
|
||||
|
||||
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');
|
||||
|
||||
|
|
@ -65,10 +66,9 @@ test.describe('PDF view modes and Navigator', () => {
|
|||
});
|
||||
|
||||
test('switches Single/Dual/Scroll modes and uses Navigator to change page', async ({ page }) => {
|
||||
test.setTimeout(60_000);
|
||||
test.setTimeout(120_000);
|
||||
// Open PDF viewer
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
await expect(page.locator('.react-pdf__Document')).toBeVisible({ timeout: 15000 });
|
||||
|
||||
// Open document settings (page-level settings)
|
||||
await page.getByRole('button', { name: 'Open settings' }).click();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
test.describe.configure({ mode: 'serial', timeout: 60000 });
|
||||
|
||||
test('plays and pauses TTS for a PDF document', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
// Play TTS for the PDF document
|
||||
await playTTSAndWaitForASecond(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -61,6 +62,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
});
|
||||
|
||||
test('plays and pauses TTS for an DOCX document', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
// Play TTS for the DOCX document
|
||||
await playTTSAndWaitForASecond(page, 'sample.docx');
|
||||
|
||||
|
|
@ -77,6 +79,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
});
|
||||
|
||||
test('switches to a single voice and resumes playing', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
// Start playback
|
||||
await playTTSAndWaitForASecond(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -96,6 +99,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
});
|
||||
|
||||
test('keeps selected single voice instead of resetting to first option', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await playTTSAndWaitForASecond(page, 'sample.pdf');
|
||||
|
||||
await openVoicesMenu(page);
|
||||
|
|
@ -122,6 +126,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
});
|
||||
|
||||
if (!process.env.CI) test('selects multiple Kokoro voices and resumes playing', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
// Start playback
|
||||
await playTTSAndWaitForASecond(page, 'sample.pdf');
|
||||
|
||||
|
|
@ -142,6 +147,7 @@ test.describe('Play/Pause Tests', () => {
|
|||
});
|
||||
|
||||
test('changing TTS native speed toggles processing and returns to playing', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await playTTSAndWaitForASecond(page, 'sample.pdf');
|
||||
await changeNativeSpeedAndAssert(page, 1.5);
|
||||
await expectMediaState(page, 'playing');
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ test.describe('Document Upload Tests', () => {
|
|||
});
|
||||
|
||||
test('displays a PDF document', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await uploadAndDisplay(page, 'sample.pdf');
|
||||
await expectViewerForFile(page, 'sample.pdf');
|
||||
// Additional content checks specific to the sample PDF
|
||||
await expect(page.locator('.react-pdf__Page')).toBeVisible();
|
||||
await expect(page.getByRole('heading', { level: 1, name: 'sample.pdf' })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /1\s*\/\s*2/ })).toBeVisible();
|
||||
});
|
||||
|
|
@ -105,10 +105,10 @@ test.describe('Document Upload Tests', () => {
|
|||
});
|
||||
|
||||
test('displays a DOCX document as PDF after conversion', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
await uploadAndDisplay(page, 'sample.docx');
|
||||
await expectViewerForFile(page, 'sample.docx'); // DOCX converts to PDF
|
||||
// Keep specific content checks
|
||||
await expect(page.locator('.react-pdf__Page')).toBeVisible();
|
||||
await expect(page.getByText('Demonstration of DOCX')).toBeVisible();
|
||||
});
|
||||
|
||||
|
|
@ -119,6 +119,7 @@ test.describe('Document Upload Tests', () => {
|
|||
});
|
||||
|
||||
test('uploads PDF/EPUB/TXT and opens correct viewer for each', async ({ page }) => {
|
||||
test.setTimeout(120_000);
|
||||
// Upload multiple files
|
||||
await uploadFiles(page, 'sample.pdf', 'sample.epub', 'sample.txt');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue