From 652a4c8008f7d2a80b51c2db94ffa05c27bdb04c Mon Sep 17 00:00:00 2001 From: eumalin Date: Tue, 19 May 2026 10:51:45 -0400 Subject: [PATCH 1/2] Add Playwright tests --- pt/web/firebird/tests/restricted_view.spec.js | 45 +++++++++++++++++++ pt/web/firebird/tests/search.spec.js | 44 ++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 pt/web/firebird/tests/restricted_view.spec.js create mode 100644 pt/web/firebird/tests/search.spec.js diff --git a/pt/web/firebird/tests/restricted_view.spec.js b/pt/web/firebird/tests/restricted_view.spec.js new file mode 100644 index 000000000..bef919acb --- /dev/null +++ b/pt/web/firebird/tests/restricted_view.spec.js @@ -0,0 +1,45 @@ +import { expect, test } from '@playwright/test'; + +// These tests run as an anonymous (not-logged-in) user. +// The auth specs cover the same items under authenticated access. +test.describe('restricted view', () => { + test.describe('ic_currently_held', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/cgi/pt?id=test.ic_currently_held'); + }); + + test('shows "not available online" warning', async ({ page }) => { + await expect(page.getByText('not available online')).toBeVisible(); + }); + + test('shows "Limited - search only" label', async ({ page }) => { + await expect(page.getByText('Limited - search only')).toBeVisible(); + }); + + test('does not render any page scan images', async ({ page }) => { + await expect(page.getByRole('figure')).toHaveCount(0); + }); + + test('does not render the reader toolbar', async ({ page }) => { + await expect(page.locator('.view--toolbar')).toHaveCount(0); + }); + + test('shows a search form so users can still search the text', async ({ page }) => { + await expect(page.locator('#input-search-text')).toBeVisible(); + }); + }); + + test.describe('ic_not_held', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/cgi/pt?id=test.ic_not_held'); + }); + + test('shows "not available online" warning', async ({ page }) => { + await expect(page.getByText('not available online')).toBeVisible(); + }); + + test('does not render any page scan images', async ({ page }) => { + await expect(page.getByRole('figure')).toHaveCount(0); + }); + }); +}); diff --git a/pt/web/firebird/tests/search.spec.js b/pt/web/firebird/tests/search.spec.js new file mode 100644 index 000000000..21c0fec73 --- /dev/null +++ b/pt/web/firebird/tests/search.spec.js @@ -0,0 +1,44 @@ +import { expect, test } from '@playwright/test'; + +test.describe('search in this text', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/cgi/pt?id=test.pd_open'); + await page.getByRole('button', { name: 'Allow all cookies' }).click(); + const panelButton = page.getByRole('button', { name: 'Search in This Text' }); + await panelButton.click(); + await expect(panelButton).toHaveAttribute('aria-expanded', 'true'); + }); + + test('search input is visible when panel is open', async ({ page }) => { + await expect(page.locator('#input-search-text')).toBeVisible(); + }); + + test('submitting a query updates the URL with q1 param', async ({ page }) => { + await page.locator('#input-search-text').fill('the'); + await page.getByRole('button', { name: 'Submit search' }).click(); + await expect(page).toHaveURL(/q1=the/); + }); + + test('search shows a result count message', async ({ page }) => { + await page.locator('#input-search-text').fill('the'); + await page.getByRole('button', { name: 'Submit search' }).click(); + // .alert-primary is the search status div; other .alert elements on the page are -warning/-danger/-light + await expect(page.locator('.alert-primary')).toBeVisible({ timeout: 10_000 }); + await expect(page.locator('.alert-primary')).toContainText(/results/i); + }); + + test('clearing search removes the q1 param from URL', async ({ page }) => { + await page.locator('#input-search-text').fill('the'); + await page.getByRole('button', { name: 'Submit search' }).click(); + await expect(page.locator('.alert-primary')).toBeVisible({ timeout: 10_000 }); + + await page.getByRole('button', { name: 'Clear search' }).click(); + await expect(page).not.toHaveURL(/q1=the/); + await expect(page.locator('#input-search-text')).toHaveValue(''); + }); + + test('loading the page with q1 param pre-fills the search input', async ({ page }) => { + await page.goto('/cgi/pt?id=test.pd_open&q1=hello'); + await expect(page.locator('#input-search-text')).toHaveValue('hello'); + }); +}); From c6af466a2d1e7b4f840d37637ab935891d7d6414 Mon Sep 17 00:00:00 2001 From: eumalin Date: Wed, 20 May 2026 16:33:28 -0400 Subject: [PATCH 2/2] use more idiomatic selectors --- pt/web/firebird/tests/restricted_view.spec.js | 2 +- pt/web/firebird/tests/search.spec.js | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/pt/web/firebird/tests/restricted_view.spec.js b/pt/web/firebird/tests/restricted_view.spec.js index bef919acb..0715974dd 100644 --- a/pt/web/firebird/tests/restricted_view.spec.js +++ b/pt/web/firebird/tests/restricted_view.spec.js @@ -25,7 +25,7 @@ test.describe('restricted view', () => { }); test('shows a search form so users can still search the text', async ({ page }) => { - await expect(page.locator('#input-search-text')).toBeVisible(); + await expect(page.getByLabel('Search in this text')).toBeVisible(); }); }); diff --git a/pt/web/firebird/tests/search.spec.js b/pt/web/firebird/tests/search.spec.js index 21c0fec73..f80e14afa 100644 --- a/pt/web/firebird/tests/search.spec.js +++ b/pt/web/firebird/tests/search.spec.js @@ -10,35 +10,33 @@ test.describe('search in this text', () => { }); test('search input is visible when panel is open', async ({ page }) => { - await expect(page.locator('#input-search-text')).toBeVisible(); + await expect(page.getByLabel('Search in this text')).toBeVisible(); }); test('submitting a query updates the URL with q1 param', async ({ page }) => { - await page.locator('#input-search-text').fill('the'); + await page.getByLabel('Search in this text').fill('the'); await page.getByRole('button', { name: 'Submit search' }).click(); await expect(page).toHaveURL(/q1=the/); }); test('search shows a result count message', async ({ page }) => { - await page.locator('#input-search-text').fill('the'); + await page.getByLabel('Search in this text').fill('the'); await page.getByRole('button', { name: 'Submit search' }).click(); - // .alert-primary is the search status div; other .alert elements on the page are -warning/-danger/-light - await expect(page.locator('.alert-primary')).toBeVisible({ timeout: 10_000 }); - await expect(page.locator('.alert-primary')).toContainText(/results/i); + await expect(page.getByText(/results.*for/i)).toBeVisible({ timeout: 10_000 }); }); test('clearing search removes the q1 param from URL', async ({ page }) => { - await page.locator('#input-search-text').fill('the'); + await page.getByLabel('Search in this text').fill('the'); await page.getByRole('button', { name: 'Submit search' }).click(); - await expect(page.locator('.alert-primary')).toBeVisible({ timeout: 10_000 }); + await expect(page.getByText(/results.*for/i)).toBeVisible({ timeout: 10_000 }); await page.getByRole('button', { name: 'Clear search' }).click(); await expect(page).not.toHaveURL(/q1=the/); - await expect(page.locator('#input-search-text')).toHaveValue(''); + await expect(page.getByLabel('Search in this text')).toHaveValue(''); }); test('loading the page with q1 param pre-fills the search input', async ({ page }) => { await page.goto('/cgi/pt?id=test.pd_open&q1=hello'); - await expect(page.locator('#input-search-text')).toHaveValue('hello'); + await expect(page.getByLabel('Search in this text')).toHaveValue('hello'); }); });