test(ops): verify Docker persistence, browser workflows and document deployment

This commit is contained in:
OpenCode committed 2026-10-24 15:43:37 +02:00
1 parent a58516e424
commit 8fa63415f1
35 files changed
+1105

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
import { test, expect } from '@playwright/test';
import { readFile } from 'node:fs/promises';
import { exportRecipes } from '../../src/lib/import';
import { pasta } from '../fixtures';
test('admin creates and edits recipes with recoverable drafts and image upload', async ({
page,
}) => {
await page.goto('/admin');
await page.getByRole('textbox', { name: 'Benutzername' }).fill('testadmin');
await page.getByLabel('Passwort', { exact: true }).fill(process.env.TEST_PASSWORD!);
await page.getByRole('button', { name: 'Anmelden', exact: true }).click();
await expect(page.getByRole('heading', { name: 'Hallo, testadmin.' })).toBeVisible();
await page.getByRole('link', { name: 'Neues Rezept' }).click();
await page
.getByRole('textbox', { name: 'Rezepttitel', exact: true })
.fill('Browser-Küchenrezept');
await page
.getByRole('textbox', { name: 'Beschreibung', exact: true })
.fill('Ein echtes Rezept aus dem grafischen Editor.');
page.on('dialog', (d) => d.accept());
await page.reload();
await expect(page.getByRole('textbox', { name: 'Rezepttitel', exact: true })).toHaveValue(
'Browser-Küchenrezept',
);
await page.getByLabel('Titelbild hochladen').setInputFiles('public/images/garden.jpg');
await expect(page.getByRole('img', { name: 'Titelbild', exact: true })).toBeVisible();
await page.getByRole('checkbox', { name: /Rezept veröffentlichen/ }).check();
await page.getByRole('button', { name: 'Zutaten', exact: true }).click();
await page.getByRole('textbox', { name: 'Zutat 1', exact: true }).fill('Kartoffeln');
await page.getByRole('spinbutton', { name: 'Menge 1', exact: true }).fill('400');
await page.getByRole('button', { name: 'Zutat hinzufügen' }).click();
await page.getByRole('textbox', { name: 'Zutat 2', exact: true }).fill('Salz');
await page.getByRole('combobox', { name: 'Einheit 2', exact: true }).selectOption('');
await page.getByRole('button', { name: 'Zubereitung', exact: true }).click();
await page.getByRole('textbox', { name: 'Schritttitel 1' }).fill('Kartoffeln kochen');
await page.getByRole('textbox', { name: 'Anleitung 1' }).fill('In Salzwasser weich kochen.');
await page.getByRole('button', { name: 'Kartoffeln', exact: true }).click();
await page.getByRole('button', { name: 'Timer hinzufügen' }).click();
await page.getByRole('button', { name: 'Live-Vorschau', exact: true }).click();
await expect(page.locator('.editor-preview')).toContainText('400 g Kartoffeln');
await page.screenshot({ path: 'docs/screenshots/editor-desktop.png', fullPage: true });
await page.getByRole('button', { name: 'Rezept speichern' }).click();
await expect(page).toHaveURL(/\/admin\/rezepte\/[a-f0-9-]{36}$/);
await page.getByRole('button', { name: 'Das Rezept', exact: true }).click();
await page
.getByRole('textbox', { name: 'Rezepttitel', exact: true })
.fill('Browser-Küchenrezept verbessert');
await page.getByRole('button', { name: 'Rezept speichern' }).click();
await expect(page.getByRole('status')).toContainText('erfolgreich gespeichert');
await page.goto('/admin');
await expect(
page.getByRole('heading', { name: 'Browser-Küchenrezept verbessert' }),
).toBeVisible();
const downloadPromise = page.waitForEvent('download');
await page
.getByRole('link', { name: 'Browser-Küchenrezept verbessert als JSON exportieren' })
.click();
const download = await downloadPromise;
const data = JSON.parse(await readFile((await download.path())!, 'utf8'));
expect(data.recipes[0].title).toBe('Browser-Küchenrezept verbessert');
await page.getByRole('button', { name: 'Browser-Küchenrezept verbessert löschen' }).click();
await page.getByRole('button', { name: 'Endgültig löschen' }).click();
await expect(page.getByRole('heading', { name: 'Browser-Küchenrezept verbessert' })).toHaveCount(
0,
);
await page.getByRole('button', { name: 'Abmelden' }).click();
await expect(page.getByRole('heading', { name: 'Willkommen zurück.' })).toBeVisible();
});
test('JSON and XML import with a real preview, duplicate prevention and export', async ({
page,
}) => {
await page.goto('/admin');
await page.getByLabel('Benutzername').fill('testadmin');
await page.getByLabel('Passwort', { exact: true }).fill(process.env.TEST_PASSWORD!);
await page.getByRole('button', { name: 'Anmelden', exact: true }).click();
for (const format of ['json', 'xml'] as const) {
await page.getByRole('button', { name: 'Importieren', exact: true }).click();
await page.getByLabel('Importformat').selectOption(format);
const recipe = {
...pasta,
id: undefined,
title: `Importierte ${format.toUpperCase()} Pasta`,
published: false,
};
await page.getByLabel('Rezeptdaten').fill(exportRecipes([recipe], format));
await page.getByRole('button', { name: 'Importvorschau prüfen' }).click();
await expect(page.locator('.import-preview')).toContainText(recipe.title);
await expect(page.locator('.import-preview')).toContainText('200 g Pasta');
await page.getByRole('button', { name: '1 Rezept(e) jetzt importieren' }).click();
await expect(page.getByRole('heading', { name: recipe.title })).toBeVisible();
}
await page.getByRole('button', { name: 'Importieren', exact: true }).click();
await page.getByLabel('Rezeptdaten').fill(exportRecipes([pasta], 'json'));
await page.getByRole('button', { name: 'Importvorschau prüfen' }).click();
await expect(page.getByText('Duplikat – Import gesperrt')).toBeVisible();
await expect(page.getByRole('button', { name: '1 Rezept(e) jetzt importieren' })).toBeDisabled();
});