From 2f2442e5a2057b45d8036e13a4a84982612fef44 Mon Sep 17 00:00:00 2001 From: Richard Roberson Date: Sun, 2 Mar 2025 23:40:55 -0700 Subject: [PATCH] Refactor tests: update Play/Pause functionality and document upload tests; replace e2e.spec.ts with helper functions --- playwright.config.ts | 2 +- tests/e2e.spec.ts | 126 ------------------------------------------- tests/helpers.ts | 79 +++++++++++++++++++++++++++ tests/play.spec.ts | 32 +++++++++++ tests/upload.spec.ts | 32 +++++++++++ 5 files changed, 144 insertions(+), 127 deletions(-) delete mode 100644 tests/e2e.spec.ts create mode 100644 tests/helpers.ts create mode 100644 tests/play.spec.ts create mode 100644 tests/upload.spec.ts diff --git a/playwright.config.ts b/playwright.config.ts index 1b5edfb..3529846 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -31,7 +31,7 @@ export default defineConfig({ baseURL: 'http://localhost:3003', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: 'retain-on-first-failure', screenshot: 'only-on-failure', }, diff --git a/tests/e2e.spec.ts b/tests/e2e.spec.ts deleted file mode 100644 index 4d3efa6..0000000 --- a/tests/e2e.spec.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { test, expect, Page } from '@playwright/test'; - -const DIR = './public/'; - -// Upload a sample epub or pdf -async function uploadFile(page: Page, filePath: string) { - await page.waitForSelector('input[type=file]', { timeout: 10000 }); - await page.setInputFiles('input[type=file]', `${DIR}${filePath}`); -} - -async function uploadAndDisplay(page: Page, fileName: string) { - // Upload the file - await uploadFile(page, fileName); - - // Wait for link with document-link class - const size = fileName.endsWith('.pdf') ? '0.02 MB' : '0.33 MB'; - await page.getByRole('link', { name: `${fileName} ${size}` }).click(); - - // Wait for the document to load - if (fileName.endsWith('.pdf')) { - await page.waitForSelector('.react-pdf__Document', { timeout: 10000 }); - } - else if (fileName.endsWith('.epub')) { - await page.waitForSelector('.epub-container', { timeout: 10000 }); - } -} - -async function waitAndClickPlay(page: Page) { - // Wait for play button selector without disabled attribute - await expect(page.getByRole('button', { name: 'Play' })).toBeVisible(); - // Play the TTS by clicking the button - await page.getByRole('button', { name: 'Play' }).click(); - - // Expect for buttons to be disabled - await expect(page.locator('button[aria-label="Skip forward"][disabled]')).toBeVisible(); - await expect(page.locator('button[aria-label="Skip backward"][disabled]')).toBeVisible(); - - // Wait for the TTS to stop processing - await Promise.all([ - page.waitForSelector('button[aria-label="Skip forward"]:not([disabled])', { timeout: 45000 }), - page.waitForSelector('button[aria-label="Skip backward"]:not([disabled])', { timeout: 45000 }), - ]); - - await page.waitForFunction(() => { - return navigator.mediaSession?.playbackState === 'playing'; - }); -} - -async function playTTSAndWaitForASecond(page: Page, fileName: string) { - // Upload and display the document - await uploadAndDisplay(page, fileName); - // Wait for play button selector without disabled attribute - await waitAndClickPlay(page); - // play for 1s - await page.waitForTimeout(1000); -} - -test.describe('Document flow', () => { - test.beforeEach(async ({ page }) => { - // Navigate to the home page before each test - await page.goto('/'); - await page.waitForLoadState('networkidle'); - - // Click the "done" button to dismiss the welcome message - await page.getByText('Done').click(); - }); - - // Basic upload tests can run in parallel - test.describe('Basic document tests', () => { - test('upload a PDF document', async ({ page }) => { - // Upload the file - await uploadFile(page, 'sample.pdf'); - - // Verify upload success - await expect(page.getByText('sample.pdf')).toBeVisible({ timeout: 10000 }); - }); - - test('upload a EPUB document', async ({ page }) => { - // Upload the file - await uploadFile(page, 'sample.epub'); - // Verify upload success - await expect(page.getByText('sample.epub')).toBeVisible({ timeout: 10000 }); - }); - - test('display a PDF document', async ({ page }) => { - // Upload and display the PDF document - await uploadAndDisplay(page, 'sample.pdf'); - - // Verify PDF viewer is displayed - await expect(page.locator('.react-pdf__Document')).toBeVisible(); - await expect(page.locator('.react-pdf__Page')).toBeVisible(); - await expect(page.getByText('Sample PDF')).toBeVisible(); - }); - - test('display an EPUB document', async ({ page }) => { - // Upload and display the EPUB document - await uploadAndDisplay(page, 'sample.epub'); - // Verify EPUB viewer is displayed - await expect(page.locator('.epub-container')).toBeVisible({ timeout: 10000 }); - await expect(page.getByRole('button', { name: '‹' })).toBeVisible(); - await expect(page.getByRole('button', { name: '›' })).toBeVisible(); - }); - }); - - // TTS tests run with limited concurrency - test.describe('TTS functionality', () => { - test.describe.configure({ mode: 'serial' }); - test('play and pause TTS for a PDF document', async ({ page }) => { - // Play TTS for the PDF document - await playTTSAndWaitForASecond(page, 'sample.pdf'); - // Click pause to stop playback - await page.getByRole('button', { name: 'Pause' }).click(); - // Check for play button to be visible - await expect(page.getByRole('button', { name: 'Play' })).toBeVisible({ timeout: 10000 }); - }); - - test('play and pause TTS for an EPUB document', async ({ page }) => { - // Play TTS for the EPUB document - await playTTSAndWaitForASecond(page, 'sample.epub'); - // Click pause to stop playback - await page.getByRole('button', { name: 'Pause' }).click(); - // Check for play button to be visible - await expect(page.getByRole('button', { name: 'Play' })).toBeVisible({ timeout: 10000 }); - }); - }); -}); diff --git a/tests/helpers.ts b/tests/helpers.ts new file mode 100644 index 0000000..daf48f6 --- /dev/null +++ b/tests/helpers.ts @@ -0,0 +1,79 @@ +import { Page, expect } from '@playwright/test'; + +const DIR = './public/'; + +/** + * Upload a sample epub or pdf + */ +export async function uploadFile(page: Page, filePath: string) { + await page.waitForSelector('input[type=file]', { timeout: 10000 }); + await page.setInputFiles('input[type=file]', `${DIR}${filePath}`); +} + +/** + * Upload and display a document + */ +export async function uploadAndDisplay(page: Page, fileName: string) { + // Upload the file + await uploadFile(page, fileName); + + // Wait for link with document-link class + const size = fileName.endsWith('.pdf') ? '0.02 MB' : '0.33 MB'; + await page.getByRole('link', { name: `${fileName} ${size}` }).click(); + + // Wait for the document to load + if (fileName.endsWith('.pdf')) { + await page.waitForSelector('.react-pdf__Document', { timeout: 10000 }); + } + else if (fileName.endsWith('.epub')) { + await page.waitForSelector('.epub-container', { timeout: 10000 }); + } +} + +/** + * Wait for the play button to be clickable and click it + */ +export async function waitAndClickPlay(page: Page) { + // Wait for play button selector without disabled attribute + await expect(page.getByRole('button', { name: 'Play' })).toBeVisible(); + // Play the TTS by clicking the button + await page.getByRole('button', { name: 'Play' }).click(); + + // Expect for buttons to be disabled + await expect(page.locator('button[aria-label="Skip forward"][disabled]')).toBeVisible(); + await expect(page.locator('button[aria-label="Skip backward"][disabled]')).toBeVisible(); + + // Wait for the TTS to stop processing + await Promise.all([ + page.waitForSelector('button[aria-label="Skip forward"]:not([disabled])', { timeout: 45000 }), + page.waitForSelector('button[aria-label="Skip backward"]:not([disabled])', { timeout: 45000 }), + ]); + + await page.waitForFunction(() => { + return navigator.mediaSession?.playbackState === 'playing'; + }); +} + +/** + * Setup function for TTS playback tests + */ +export async function playTTSAndWaitForASecond(page: Page, fileName: string) { + // Upload and display the document + await uploadAndDisplay(page, fileName); + // Wait for play button selector without disabled attribute + await waitAndClickPlay(page); + // play for 1s + await page.waitForTimeout(1000); +} + +/** + * Common test setup function + */ +export async function setupTest(page: Page) { + // Navigate to the home page before each test + await page.goto('/'); + await page.waitForLoadState('networkidle'); + + // Click the "done" button to dismiss the welcome message + await page.getByText('Done').click(); +} \ No newline at end of file diff --git a/tests/play.spec.ts b/tests/play.spec.ts new file mode 100644 index 0000000..f82a836 --- /dev/null +++ b/tests/play.spec.ts @@ -0,0 +1,32 @@ +import { test, expect } from '@playwright/test'; +import { setupTest, playTTSAndWaitForASecond } from './helpers'; + +test.describe('Play/Pause Tests', () => { + test.beforeEach(async ({ page }) => { + await setupTest(page); + }); + + test.describe.configure({ mode: 'serial' }); + + test('plays and pauses TTS for a PDF document', async ({ page }) => { + // Play TTS for the PDF document + await playTTSAndWaitForASecond(page, 'sample.pdf'); + + // Click pause to stop playback + await page.getByRole('button', { name: 'Pause' }).click(); + + // Check for play button to be visible + await expect(page.getByRole('button', { name: 'Play' })).toBeVisible({ timeout: 10000 }); + }); + + test('plays and pauses TTS for an EPUB document', async ({ page }) => { + // Play TTS for the EPUB document + await playTTSAndWaitForASecond(page, 'sample.epub'); + + // Click pause to stop playback + await page.getByRole('button', { name: 'Pause' }).click(); + + // Check for play button to be visible + await expect(page.getByRole('button', { name: 'Play' })).toBeVisible({ timeout: 10000 }); + }); +}); \ No newline at end of file diff --git a/tests/upload.spec.ts b/tests/upload.spec.ts new file mode 100644 index 0000000..d6c7906 --- /dev/null +++ b/tests/upload.spec.ts @@ -0,0 +1,32 @@ +import { test, expect } from '@playwright/test'; +import { uploadFile, uploadAndDisplay, setupTest } from './helpers'; + +test.describe('Document Upload Tests', () => { + test.beforeEach(async ({ page }) => { + await setupTest(page); + }); + + test('uploads a PDF document', async ({ page }) => { + await uploadFile(page, 'sample.pdf'); + await expect(page.getByText('sample.pdf')).toBeVisible({ timeout: 10000 }); + }); + + test('uploads an EPUB document', async ({ page }) => { + await uploadFile(page, 'sample.epub'); + await expect(page.getByText('sample.epub')).toBeVisible({ timeout: 10000 }); + }); + + test('displays a PDF document', async ({ page }) => { + await uploadAndDisplay(page, 'sample.pdf'); + await expect(page.locator('.react-pdf__Document')).toBeVisible(); + await expect(page.locator('.react-pdf__Page')).toBeVisible(); + await expect(page.getByText('Sample PDF')).toBeVisible(); + }); + + test('displays an EPUB document', async ({ page }) => { + await uploadAndDisplay(page, 'sample.epub'); + await expect(page.locator('.epub-container')).toBeVisible({ timeout: 10000 }); + await expect(page.getByRole('button', { name: '‹' })).toBeVisible(); + await expect(page.getByRole('button', { name: '›' })).toBeVisible(); + }); +}); \ No newline at end of file