test(e2e): Playwright Smoketests gegen kochwas-dev (remote)
Automatisierte End-to-End-Tests gegen ein deployed Environment. Loest
die manuellen MCP-Playwright-Runs ab. 42 Tests in 9 Files:
- homepage: H1, Sektionen, Sort-Tabs, Console-Errors
- search: lokaler Treffer, Web-Fallback, Empty-State, Deep-Link
- profile: Switcher, Auswahl-Persistenz, Favoriten-Section, Guard-Dialog
- recipe-detail: Header, Portionen-Scaling (4->6), Favorit-Toggle,
Rating-Persistenz ueber Reload, Gekocht-Counter, Wunschliste-Toggle
- comments: eigenen erstellen+loeschen via UI, fremder hat kein Delete
- wishlist: Seite, Sort-Tabs, Badge-Sync, requireProfile-Custom-Message
- preview: Guard ohne ?url=, echte URL parst, unparsbare zeigt error-box
- admin: alle 4 Subrouten + /admin redirect
- api-errors: parsePositiveIntParam (4x Invalid id), validateBody (4x
Invalid body + issues), 404, Sanity /health /profiles /domains
Architektur:
- Separate playwright.remote.config.ts (getrennt von local preview)
- workers: 1 + afterEach API-Cleanup (rating, favorite, wishlist, comments)
- Hardcoded Recipe-ID 66 + Profile 1/2/3 — stabile Dev-DB-Seeds
- E2E_REMOTE_URL ueberschreibt die Ziel-URL
Ausfuehrung: npm run test:e2e:remote
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 12:14:04 +02:00
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
|
import { setActiveProfile, HENDRIK_ID } from './fixtures/profile';
|
|
|
|
|
import { cleanupE2EComments, deleteComment } from './fixtures/api-cleanup';
|
|
|
|
|
|
|
|
|
|
const RECIPE_ID = 66;
|
|
|
|
|
|
|
|
|
|
test.describe('Kommentare', () => {
|
|
|
|
|
test.beforeEach(async ({ page, request }) => {
|
|
|
|
|
await setActiveProfile(page, HENDRIK_ID);
|
|
|
|
|
// Stray E2E-Kommentare aus abgebrochenen Runs wegraeumen.
|
|
|
|
|
await cleanupE2EComments(request, RECIPE_ID, HENDRIK_ID);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.afterEach(async ({ request }) => {
|
|
|
|
|
await cleanupE2EComments(request, RECIPE_ID, HENDRIK_ID);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('Kommentar erstellen, Delete-Button erscheint, Loeschen via UI', async ({
|
|
|
|
|
page
|
|
|
|
|
}) => {
|
|
|
|
|
const unique = `E2E ${Date.now()}`;
|
|
|
|
|
await page.goto(`/recipes/${RECIPE_ID}`);
|
|
|
|
|
|
|
|
|
|
await page.getByRole('textbox').filter({ hasText: '' }).last().fill(unique);
|
|
|
|
|
await page.getByRole('button', { name: 'Kommentar speichern' }).click();
|
|
|
|
|
|
|
|
|
|
// Neuer Kommentar sichtbar
|
|
|
|
|
await expect(page.getByText(unique)).toBeVisible({ timeout: 5000 });
|
|
|
|
|
|
|
|
|
|
// Delete-Button NUR beim eigenen Kommentar
|
|
|
|
|
const delBtn = page.getByRole('button', { name: 'Kommentar löschen' });
|
|
|
|
|
await expect(delBtn).toBeVisible();
|
|
|
|
|
|
|
|
|
|
await delBtn.click();
|
2026-04-19 12:21:36 +02:00
|
|
|
// ConfirmDialog "Kommentar loeschen?" mit Loeschen-Button.
|
|
|
|
|
// Es gibt mehrere "Löschen"-Buttons auf der Seite (Rezept-Delete,
|
|
|
|
|
// Kommentar-Trash, Dialog-Bestaetigung) — deshalb Locator auf den
|
|
|
|
|
// Dialog einschraenken.
|
|
|
|
|
const dialog = page.getByRole('dialog', { name: /Kommentar löschen/i });
|
|
|
|
|
await expect(dialog).toBeVisible();
|
|
|
|
|
await dialog.getByRole('button', { name: 'Löschen' }).click();
|
test(e2e): Playwright Smoketests gegen kochwas-dev (remote)
Automatisierte End-to-End-Tests gegen ein deployed Environment. Loest
die manuellen MCP-Playwright-Runs ab. 42 Tests in 9 Files:
- homepage: H1, Sektionen, Sort-Tabs, Console-Errors
- search: lokaler Treffer, Web-Fallback, Empty-State, Deep-Link
- profile: Switcher, Auswahl-Persistenz, Favoriten-Section, Guard-Dialog
- recipe-detail: Header, Portionen-Scaling (4->6), Favorit-Toggle,
Rating-Persistenz ueber Reload, Gekocht-Counter, Wunschliste-Toggle
- comments: eigenen erstellen+loeschen via UI, fremder hat kein Delete
- wishlist: Seite, Sort-Tabs, Badge-Sync, requireProfile-Custom-Message
- preview: Guard ohne ?url=, echte URL parst, unparsbare zeigt error-box
- admin: alle 4 Subrouten + /admin redirect
- api-errors: parsePositiveIntParam (4x Invalid id), validateBody (4x
Invalid body + issues), 404, Sanity /health /profiles /domains
Architektur:
- Separate playwright.remote.config.ts (getrennt von local preview)
- workers: 1 + afterEach API-Cleanup (rating, favorite, wishlist, comments)
- Hardcoded Recipe-ID 66 + Profile 1/2/3 — stabile Dev-DB-Seeds
- E2E_REMOTE_URL ueberschreibt die Ziel-URL
Ausfuehrung: npm run test:e2e:remote
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 12:14:04 +02:00
|
|
|
|
|
|
|
|
await expect(page.getByText(unique)).not.toBeVisible({ timeout: 5000 });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('Fremder Kommentar zeigt KEINEN Delete-Button fuers aktuelle Profil', async ({
|
|
|
|
|
page,
|
|
|
|
|
request
|
|
|
|
|
}) => {
|
|
|
|
|
// Wir legen den Kommentar fuer ein anderes Profil (Leana, id=3) per API an.
|
|
|
|
|
const text = `E2E fremd ${Date.now()}`;
|
|
|
|
|
const res = await request.post(`/api/recipes/${RECIPE_ID}/comments`, {
|
|
|
|
|
data: { profile_id: 3, text }
|
|
|
|
|
});
|
|
|
|
|
expect(res.status()).toBe(201);
|
|
|
|
|
const { id } = (await res.json()) as { id: number };
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await page.goto(`/recipes/${RECIPE_ID}`);
|
|
|
|
|
const item = page
|
|
|
|
|
.locator('.comments li')
|
|
|
|
|
.filter({ hasText: text });
|
|
|
|
|
await expect(item).toBeVisible();
|
|
|
|
|
await expect(
|
|
|
|
|
item.getByRole('button', { name: 'Kommentar löschen' })
|
|
|
|
|
).toHaveCount(0);
|
|
|
|
|
} finally {
|
|
|
|
|
await deleteComment(request, RECIPE_ID, id);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|