fix: improve public detail keyboard access and reflow
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-10 07:48:42 -04:00
parent 94c37250d1
commit a02965de4a
15 changed files with 193 additions and 18 deletions
+26 -2
View File
@@ -26,14 +26,38 @@ export const MobileFilterDisclosure = {
await expect(toggle).toHaveAttribute('aria-expanded', 'false');
await expect(setFilter).not.toBeVisible();
await userEvent.click(toggle);
toggle.focus();
await userEvent.keyboard('{Enter}');
await expect(toggle).toHaveAttribute('aria-expanded', 'true');
await expect(setFilter).toBeVisible();
await userEvent.click(toggle);
toggle.focus();
await userEvent.keyboard(' ');
await expect(toggle).toHaveAttribute('aria-expanded', 'false');
await expect(setFilter).not.toBeVisible();
},
};
export const MobilePopulatedCatalog = {
beforeEach: () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url) => new Response(JSON.stringify({ data: String(url).includes('/search?') ? {
items: [{ id: 'collectible-1', productName: 'Charizard ex special illustration rare', askingPriceMinor: 2500, status: 'AVAILABLE' }],
pagination: { page: 1, limit: 20, total: 1, totalPages: 1 },
} : [] }), { headers: { 'content-type': 'application/json' } });
return () => { globalThis.fetch = originalFetch; };
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const listing = await canvas.findByRole('link', { name: /Charizard ex/ });
const toggle = canvas.getByRole('button', { name: /Filters/ });
toggle.focus();
await userEvent.tab();
await expect(listing).toHaveFocus();
await expect(listing).toHaveAttribute('href', '/listings/collectible-1');
await expect(document.documentElement.scrollWidth).toBeLessThanOrEqual(window.innerWidth);
},
};
@@ -19,3 +19,25 @@ export const PublicSellerDescription = {
await expect(await within(canvasElement).findByText('Independent Pokémon collector.')).toBeVisible();
},
};
export const Loading = {
beforeEach: () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = () => new Promise(() => {});
return () => { globalThis.fetch = originalFetch; };
},
play: async ({ canvasElement }) => {
await expect(within(canvasElement).getByRole('status')).toHaveTextContent('Loading');
},
};
export const Unavailable = {
beforeEach: () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = async () => new Response(JSON.stringify({ error: { message: 'This collectible is unavailable.' } }), { status: 404 });
return () => { globalThis.fetch = originalFetch; };
},
play: async ({ canvasElement }) => {
await expect(await within(canvasElement).findByRole('alert')).toHaveTextContent('Listing not found.');
await expect(within(canvasElement).getByRole('link', { name: 'Back to catalog' })).toHaveAttribute('href', '/');
},
};
+2 -2
View File
@@ -26,8 +26,8 @@ onMounted(async () => {
<RouterLink class="detail-back" :to="{ name: 'catalog' }"
>Back to catalog</RouterLink
>
<p v-if="isLoading" class="catalog-state">Loading listing...</p>
<p v-else-if="error" class="catalog-state catalog-state--error">
<p v-if="isLoading" class="catalog-state" role="status">Loading listing...</p>
<p v-else-if="error" class="catalog-state catalog-state--error" role="alert">
{{ error.message }}
</p>
<CollectibleDetail
@@ -19,3 +19,25 @@ export const PublicSellerDescription = {
await expect(await within(canvasElement).findByText('Independent Pokémon collector.')).toBeVisible();
},
};
export const Loading = {
beforeEach: () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = () => new Promise(() => {});
return () => { globalThis.fetch = originalFetch; };
},
play: async ({ canvasElement }) => {
await expect(within(canvasElement).getByRole('status')).toHaveTextContent('Loading');
},
};
export const Unavailable = {
beforeEach: () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = async () => new Response(JSON.stringify({ error: { message: 'This collectible is unavailable.' } }), { status: 404 });
return () => { globalThis.fetch = originalFetch; };
},
play: async ({ canvasElement }) => {
await expect(await within(canvasElement).findByRole('alert')).toHaveTextContent('Product not found.');
await expect(within(canvasElement).getByRole('link', { name: 'Back to catalog' })).toHaveAttribute('href', '/');
},
};
+2 -2
View File
@@ -24,8 +24,8 @@ onMounted(async () => {
<template>
<main class="detail-page">
<RouterLink class="detail-back" :to="{ name: 'catalog' }">Back to catalog</RouterLink>
<p v-if="isLoading" class="catalog-state">Loading product...</p>
<p v-else-if="error" class="catalog-state catalog-state--error">{{ error.message }}</p>
<p v-if="isLoading" class="catalog-state" role="status">Loading product...</p>
<p v-else-if="error" class="catalog-state catalog-state--error" role="alert">{{ error.message }}</p>
<CollectibleDetail
v-else-if="product"
:title="product.name"