test: add full-stack Playwright integration test infrastructure
Sprint 12 Phase 2: Real integration tests with seed DB - R__seed_test_data.sql (Flyway repeatable, 7 members, strains, batches, docs, board, events) - TestResetController (profile-gated per-test DB reset) - docker-compose.test.yml (self-contained, tmpfs Postgres) - Dockerfile.playwright (v1.60.0, pre-installed deps) - 13 integration spec files, 70+ test cases (@smoke + @full) - seed-constants.ts, selectors.ts, api-client.ts test helpers
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { expect, test } from "@playwright/test"
|
||||
|
||||
import { ApiClient } from "../api-client"
|
||||
import { SEED } from "../seed-constants"
|
||||
import { SEL } from "../selectors"
|
||||
|
||||
const apiClient = new ApiClient()
|
||||
|
||||
test.describe("Board Page @smoke", () => {
|
||||
test.beforeEach(async () => {
|
||||
await apiClient.login(SEED.admin.email, SEED.admin.password)
|
||||
await apiClient.resetDb()
|
||||
})
|
||||
|
||||
test("displays seed board positions", async ({ page }) => {
|
||||
await page.goto("/board")
|
||||
await expect(page.getByText(SEED.board.vorsitz.title)).toBeVisible()
|
||||
await expect(page.getByText(SEED.board.kasse.title)).toBeVisible()
|
||||
await expect(page.getByText(SEED.board.schrift.title)).toBeVisible()
|
||||
})
|
||||
|
||||
test("shows elected members on filled positions", async ({ page }) => {
|
||||
await page.goto("/board")
|
||||
await expect(page.getByText(SEED.board.vorsitz.elected)).toBeVisible()
|
||||
await expect(page.getByText(SEED.board.kasse.elected)).toBeVisible()
|
||||
})
|
||||
|
||||
test("shows vacant status for unfilled positions", async ({ page }) => {
|
||||
await page.goto("/board")
|
||||
const schriftCard = page.locator(
|
||||
SEL.board.positionCard(SEED.board.schrift.id)
|
||||
)
|
||||
await expect(schriftCard).toBeVisible()
|
||||
await expect(schriftCard.getByText(/vakant|unbesetzt/i)).toBeVisible()
|
||||
})
|
||||
|
||||
test("create position opens form and submits", async ({ page }) => {
|
||||
// Requires backend
|
||||
await page.goto("/board")
|
||||
await page.locator(SEL.board.createPositionButton).click()
|
||||
|
||||
// Fill form
|
||||
await page.getByLabel(/titel|bezeichnung/i).fill("Beisitzer/in")
|
||||
await page.getByRole("button", { name: /speichern|erstellen/i }).click()
|
||||
|
||||
// Verify new position appears
|
||||
await expect(page.getByText("Beisitzer/in")).toBeVisible()
|
||||
})
|
||||
|
||||
test("elect member to vacant position", async ({ page }) => {
|
||||
// Requires backend
|
||||
await page.goto("/board")
|
||||
|
||||
// Click elect on the vacant Schriftführung position
|
||||
const schriftCard = page.locator(
|
||||
SEL.board.positionCard(SEED.board.schrift.id)
|
||||
)
|
||||
await schriftCard.locator(SEL.board.electMemberButton).click()
|
||||
|
||||
// Select a member from dropdown/dialog
|
||||
await page.getByRole("option", { name: /Lisa Bauer/i }).click()
|
||||
await page.getByRole("button", { name: /speichern|wählen/i }).click()
|
||||
|
||||
// Verify member is now shown
|
||||
await expect(page.getByText(SEED.members.lisa.name)).toBeVisible()
|
||||
})
|
||||
|
||||
test("remove member from position shows confirmation", async ({ page }) => {
|
||||
// Requires backend
|
||||
await page.goto("/board")
|
||||
const removeBtn = page.locator(
|
||||
SEL.board.removeButton(SEED.board.vorsitz.id)
|
||||
)
|
||||
await removeBtn.click()
|
||||
|
||||
// Confirmation dialog
|
||||
await expect(
|
||||
page.locator(SEL.common.alertDialogConfirm)
|
||||
).toBeVisible()
|
||||
await page.locator(SEL.common.alertDialogConfirm).click()
|
||||
|
||||
// Member name no longer visible on that position
|
||||
const vorsitzCard = page.locator(
|
||||
SEL.board.positionCard(SEED.board.vorsitz.id)
|
||||
)
|
||||
await expect(
|
||||
vorsitzCard.getByText(SEED.board.vorsitz.elected)
|
||||
).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user