78 lines
3.6 KiB
JavaScript
78 lines
3.6 KiB
JavaScript
import { expect, test } from '@playwright/test';
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.route('**/api/v1/public/**', async (route) => {
|
|
const path = new URL(route.request().url()).pathname;
|
|
if (path.includes('/lookups/')) return route.fulfill({ json: { data: [] } });
|
|
if (path.endsWith('/search')) return route.fulfill({ json: { data: {
|
|
items: [{ id: 'listing-1', productName: 'Pikachu ex', askingPriceMinor: 2500, status: 'AVAILABLE' }],
|
|
pagination: { page: 1, limit: 20, total: 1, totalPages: 1 },
|
|
} } });
|
|
if (path.endsWith('/missing')) return route.fulfill({ status: 404, json: {} });
|
|
return route.fulfill({ json: { data: {
|
|
id: 'listing-1', name: 'Pikachu ex', productName: 'Pikachu ex', askingPriceMinor: 2500,
|
|
status: 'AVAILABLE', images: [], sellerDisplayName: 'Pika Collectibles',
|
|
sellerContactEmail: 'collector@example.test',
|
|
} } });
|
|
});
|
|
});
|
|
|
|
test('keyboard navigation retains catalog filters, titles and entry focus', async ({ page }) => {
|
|
await page.goto('/?q=Pikachu&status=AVAILABLE');
|
|
await expect(page).toHaveTitle('Catalog | Pokémon Inventory');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
const search = page.getByRole('searchbox', { name: 'Search the catalog' });
|
|
await page.keyboard.press('Tab');
|
|
await expect(search).toBeFocused();
|
|
await search.fill('Pikachu ex');
|
|
await expect(page).toHaveURL(/q=Pikachu(?:\+|%20)ex/);
|
|
await expect(search).toBeFocused();
|
|
const catalogUrl = page.url();
|
|
const card = page.getByRole('link', { name: /Pikachu ex/ });
|
|
await card.focus();
|
|
await page.keyboard.press('Enter');
|
|
await expect(page).toHaveTitle('Pikachu ex | Pokémon Inventory');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
await page.keyboard.press('Tab');
|
|
const back = page.getByRole('link', { name: 'Back to catalog' });
|
|
await expect(back).toBeFocused();
|
|
await page.keyboard.press('Enter');
|
|
await expect(page).toHaveURL(catalogUrl);
|
|
await expect(search).toHaveValue('Pikachu ex');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
await page.goBack();
|
|
await expect(page).toHaveTitle('Pikachu ex | Pokémon Inventory');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
await page.goBack();
|
|
await expect(page).toHaveURL(catalogUrl);
|
|
await expect(search).toHaveValue('Pikachu ex');
|
|
});
|
|
|
|
test('direct product and unavailable pages have titles, focus and safe return links', async ({ page }) => {
|
|
await page.goto('/products/pikachu?from=https://example.test');
|
|
await expect(page).toHaveTitle('Pikachu ex | Pokémon Inventory');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
await expect(page.getByRole('link', { name: 'Back to catalog' })).toHaveAttribute('href', '/');
|
|
await page.goto('/listings/missing');
|
|
await expect(page).toHaveTitle('Listing not found. | Pokémon Inventory');
|
|
await expect(page.getByRole('alert')).toHaveText('Listing not found.');
|
|
await expect(page.getByRole('main')).toBeFocused();
|
|
});
|
|
|
|
test('late detail results do not steal focus from the return link', async ({ page }) => {
|
|
let release;
|
|
const responseReady = new Promise((resolve) => { release = resolve; });
|
|
await page.route('**/api/v1/public/products/slow', async (route) => {
|
|
await responseReady;
|
|
await route.fulfill({ json: { data: { name: 'Slow Pikachu', images: [] } } });
|
|
});
|
|
await page.goto('/products/slow');
|
|
await expect(page.getByRole('status')).toHaveText('Loading product...');
|
|
await page.keyboard.press('Tab');
|
|
const back = page.getByRole('link', { name: 'Back to catalog' });
|
|
await expect(back).toBeFocused();
|
|
release();
|
|
await expect(page).toHaveTitle('Slow Pikachu | Pokémon Inventory');
|
|
await expect(back).toBeFocused();
|
|
});
|