776149e7d3
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
72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
import fs from "fs"
|
|
import path from "path"
|
|
|
|
import { expect, test as setup } from "@playwright/test"
|
|
|
|
import { SEED } from "./seed-constants"
|
|
|
|
/**
|
|
* Global setup — authenticates as admin and saves the session state
|
|
* so all authenticated tests can reuse it without logging in again.
|
|
*
|
|
* Runs as a Playwright "setup project" that other projects depend on.
|
|
*/
|
|
|
|
const authDir = path.join(__dirname, ".auth")
|
|
const authFile = path.join(authDir, "admin.json")
|
|
|
|
setup("authenticate as admin", async ({ page, context }) => {
|
|
const baseURL = process.env.BASE_URL || "http://localhost:3000"
|
|
const apiUrl = process.env.API_URL || "http://localhost:8080"
|
|
|
|
// Use seed credentials (from seed-constants), overridable via env vars
|
|
const email = process.env.TEST_ADMIN_EMAIL || SEED.admin.email
|
|
const password = process.env.TEST_ADMIN_PASSWORD || SEED.admin.password
|
|
|
|
// Ensure .auth directory exists
|
|
if (!fs.existsSync(authDir)) {
|
|
fs.mkdirSync(authDir, { recursive: true })
|
|
}
|
|
|
|
// Wait for backend health (up to 60s)
|
|
let healthy = false
|
|
for (let i = 0; i < 30; i++) {
|
|
try {
|
|
const res = await fetch(`${apiUrl}/actuator/health`)
|
|
if (res.ok) {
|
|
healthy = true
|
|
break
|
|
}
|
|
} catch {
|
|
/* retry */
|
|
}
|
|
await new Promise((r) => setTimeout(r, 2000))
|
|
}
|
|
if (!healthy) throw new Error("Backend health check failed after 60s")
|
|
|
|
// Navigate to login page
|
|
await page.goto(`${baseURL}/login`)
|
|
await page.waitForLoadState("domcontentloaded")
|
|
|
|
// Fill credentials and submit
|
|
await page.fill('input[name="email"], input[type="email"]', email)
|
|
await page.fill('input[name="password"], input[type="password"]', password)
|
|
await page.click('button[type="submit"]')
|
|
|
|
// Wait for successful redirect away from login
|
|
await page.waitForURL((url) => !url.pathname.includes("/login"), {
|
|
timeout: 15000,
|
|
})
|
|
|
|
// Wait for session cookies to settle
|
|
await page.waitForLoadState("domcontentloaded")
|
|
await page.waitForTimeout(1000)
|
|
|
|
// Verify we're authenticated (sanity check)
|
|
const url = page.url()
|
|
expect(url).not.toContain("/login")
|
|
|
|
// Save the authenticated state (cookies + localStorage)
|
|
await context.storageState({ path: authFile })
|
|
})
|