test: add e2e tests
This commit is contained in:
110
frontend/e2e/documents.spec.ts
Normal file
110
frontend/e2e/documents.spec.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Document management E2E tests.
|
||||
* Assumes auth setup has run (storageState is applied by playwright.config.ts).
|
||||
* Assumes the backend has at least one document in the database.
|
||||
*/
|
||||
test.describe('Document list', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('renders the search bar and document list', async ({ page }) => {
|
||||
await expect(page.getByPlaceholder('Suche in Titel, Inhalt, Ort...')).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: /Neues Dokument/i })).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/documents-home.png' });
|
||||
});
|
||||
|
||||
test('navigation bar shows active state for Dokumente', async ({ page }) => {
|
||||
const navLink = page.getByRole('navigation').getByRole('link', { name: 'Dokumente' });
|
||||
await expect(navLink).toHaveClass(/border-brand-navy/);
|
||||
});
|
||||
|
||||
test('text search filters the document list', async ({ page }) => {
|
||||
const input = page.getByPlaceholder('Suche in Titel, Inhalt, Ort...');
|
||||
await input.fill('zzz_unlikely_to_match_anything');
|
||||
// Wait for debounced navigation
|
||||
await page.waitForURL(/\?q=/);
|
||||
await expect(page.getByText('Keine Dokumente gefunden')).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/documents-search-no-results.png' });
|
||||
});
|
||||
|
||||
test('clearing the search returns all documents', async ({ page }) => {
|
||||
const input = page.getByPlaceholder('Suche in Titel, Inhalt, Ort...');
|
||||
await input.fill('xyz_unlikely');
|
||||
await page.waitForURL(/\?q=/);
|
||||
// Click the reset link
|
||||
await page.getByTitle('Filter zurücksetzen').click();
|
||||
await page.waitForURL('/');
|
||||
await expect(page).toHaveURL('/');
|
||||
await page.screenshot({ path: 'test-results/e2e/documents-reset-search.png' });
|
||||
});
|
||||
|
||||
test('advanced filters panel opens and closes', async ({ page }) => {
|
||||
const btn = page.getByRole('button', { name: /Filter/i });
|
||||
await btn.click();
|
||||
await expect(page.getByLabel('Von')).toBeVisible();
|
||||
await expect(page.getByLabel('Bis')).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/documents-filters-open.png' });
|
||||
await btn.click();
|
||||
await expect(page.getByLabel('Von')).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('date range filter triggers a new search', async ({ page }) => {
|
||||
await page.getByRole('button', { name: /Filter/i }).click();
|
||||
await page.getByLabel('Von').fill('2000-01-01');
|
||||
await page.waitForURL(/from=2000-01-01/);
|
||||
await expect(page).toHaveURL(/from=2000-01-01/);
|
||||
await page.screenshot({ path: 'test-results/e2e/documents-date-filter.png' });
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Document detail', () => {
|
||||
test('clicking a document opens the detail page', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
// Click the first document link in the list
|
||||
const firstDoc = page.locator('ul li a').first();
|
||||
const href = await firstDoc.getAttribute('href');
|
||||
await firstDoc.click();
|
||||
await expect(page).toHaveURL(href!);
|
||||
await page.screenshot({ path: 'test-results/e2e/document-detail.png' });
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('New document', () => {
|
||||
test('renders the upload form', async ({ page }) => {
|
||||
await page.goto('/documents/new');
|
||||
await expect(page.getByRole('heading', { name: /Neues Dokument/i })).toBeVisible();
|
||||
await expect(page.getByLabel('Titel')).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/document-new.png' });
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Document edit', () => {
|
||||
test('renders the edit form with pre-filled data', async ({ page }) => {
|
||||
// Navigate to home, find first document, go to its edit page
|
||||
await page.goto('/');
|
||||
const firstDocLink = page.locator('ul li a').first();
|
||||
const href = await firstDocLink.getAttribute('href');
|
||||
await page.goto(`${href}/edit`);
|
||||
await expect(page.getByRole('heading', { name: /Bearbeiten/i })).toBeVisible();
|
||||
await expect(page.getByLabel('Titel')).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/document-edit.png' });
|
||||
});
|
||||
|
||||
test('shows a validation error for an invalid date format', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const firstDocLink = page.locator('ul li a').first();
|
||||
const href = await firstDocLink.getAttribute('href');
|
||||
await page.goto(`${href}/edit`);
|
||||
const dateInput = page.getByLabel('Datum');
|
||||
await dateInput.fill('invalid');
|
||||
// Wait for the derived dateInvalid to trigger (needs user to type something that doesn't parse)
|
||||
// Type a partial date to trigger dirty+invalid
|
||||
await dateInput.fill('');
|
||||
await dateInput.pressSequentially('abc');
|
||||
await expect(page.getByText(/TT\.MM\.JJJJ/i)).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/e2e/document-edit-date-error.png' });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user