feat: preserve focus and catalog context during public navigation
Quality / test (push) Canceled after 0s
Quality / test (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user