- createEmptyDocument now uploads a minimal PDF so the Transkribieren button is rendered (requires isPdf = true in DocumentTopBar) - add 'Transcribe coach — with blocks' describe: seeds a block via API, waits for blocks to settle in read mode, switches to edit, confirms 'Für Training vormerken' is visible - fix dark-theme axe test: ThemeToggle uses aria-label 'dark mode', not the previous /Farbmodus|theme/ regex Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
106 lines
3.8 KiB
TypeScript
106 lines
3.8 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import AxeBuilder from '@axe-core/playwright';
|
|
import { createEmptyDocument } from './helpers/upload-empty-document.js';
|
|
|
|
async function createBlock(
|
|
request: Parameters<typeof createEmptyDocument>[0],
|
|
docId: string
|
|
): Promise<void> {
|
|
const res = await request.post(`/api/documents/${docId}/transcription-blocks`, {
|
|
data: {
|
|
pageNumber: 1,
|
|
x: 0.1,
|
|
y: 0.1,
|
|
width: 0.3,
|
|
height: 0.1,
|
|
text: 'Liebe Mutter,',
|
|
label: null
|
|
}
|
|
});
|
|
if (!res.ok()) throw new Error(`Create block failed: ${res.status()}`);
|
|
}
|
|
|
|
function buildAxe(page: Parameters<typeof AxeBuilder>[0]['page']) {
|
|
return new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']);
|
|
}
|
|
|
|
test.describe('Transcribe coach — empty state', () => {
|
|
let docId: string;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
docId = await createEmptyDocument(request);
|
|
});
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
await request.delete(`/api/documents/${docId}`);
|
|
});
|
|
|
|
test('shows coach card (title, preamble, three step bodies, animation region)', async ({
|
|
page
|
|
}) => {
|
|
await page.goto(`/documents/${docId}`);
|
|
await page.getByRole('button', { name: 'Transkribieren' }).click();
|
|
|
|
await expect(page.getByRole('heading', { level: 2, name: /Erste Transkription/ })).toBeVisible({
|
|
timeout: 5000
|
|
});
|
|
await expect(page.getByText(/Kurrent-Erkenner lernt noch/)).toBeVisible();
|
|
await expect(page.getByText(/Rahmen ziehen/)).toBeVisible();
|
|
await expect(page.getByText(/Text eingeben/)).toBeVisible();
|
|
await expect(page.getByText(/Speichert automatisch/)).toBeVisible();
|
|
await expect(page.getByRole('img', { name: /Rahmen ziehen|Animation/i })).toBeVisible();
|
|
});
|
|
|
|
test('training footer is NOT visible on empty doc', async ({ page }) => {
|
|
await page.goto(`/documents/${docId}`);
|
|
await page.getByRole('button', { name: 'Transkribieren' }).click();
|
|
await expect(page.getByText('Für Training vormerken')).not.toBeVisible({ timeout: 3000 });
|
|
});
|
|
|
|
test('axe: panel empty state — light theme — no WCAG 2.1 AA violations', async ({ page }) => {
|
|
await page.goto(`/documents/${docId}`);
|
|
await page.getByRole('button', { name: 'Transkribieren' }).click();
|
|
await expect(page.getByRole('heading', { level: 2, name: /Erste Transkription/ })).toBeVisible({
|
|
timeout: 5000
|
|
});
|
|
|
|
const a11y = await buildAxe(page).analyze();
|
|
expect(a11y.violations, JSON.stringify(a11y.violations, null, 2)).toHaveLength(0);
|
|
});
|
|
|
|
test('axe: panel empty state — dark theme — no WCAG 2.1 AA violations', async ({ page }) => {
|
|
await page.goto(`/documents/${docId}`);
|
|
// Toggle dark theme
|
|
await page.getByRole('button', { name: /dark mode/i }).click();
|
|
await page.getByRole('button', { name: 'Transkribieren' }).click();
|
|
await expect(page.getByRole('heading', { level: 2, name: /Erste Transkription/ })).toBeVisible({
|
|
timeout: 5000
|
|
});
|
|
|
|
const a11y = await buildAxe(page).analyze();
|
|
expect(a11y.violations, JSON.stringify(a11y.violations, null, 2)).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
test.describe('Transcribe coach — with blocks', () => {
|
|
let docId: string;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
docId = await createEmptyDocument(request);
|
|
await createBlock(request, docId);
|
|
});
|
|
|
|
test.afterAll(async ({ request }) => {
|
|
await request.delete(`/api/documents/${docId}`);
|
|
});
|
|
|
|
test('training footer IS visible when at least one block exists', async ({ page }) => {
|
|
await page.goto(`/documents/${docId}`);
|
|
await page.getByRole('button', { name: 'Transkribieren' }).click();
|
|
// Wait for blocks to finish loading — block count confirms mode settled to 'read'
|
|
await expect(page.getByText(/1 Abschnitt/)).toBeVisible({ timeout: 5000 });
|
|
await page.locator('[data-testid="mode-edit"]').click();
|
|
await expect(page.getByText('Für Training vormerken')).toBeVisible({ timeout: 5000 });
|
|
});
|
|
});
|