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
75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
/**
|
|
* API client for integration tests.
|
|
* Used for direct backend calls: DB verification, test reset, data assertions.
|
|
*/
|
|
const API_URL = process.env.API_URL || "http://localhost:8080"
|
|
|
|
export class ApiClient {
|
|
private token: string | null = null
|
|
|
|
async login(email: string, password: string): Promise<void> {
|
|
const res = await fetch(`${API_URL}/api/v1/auth/login`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ email, password }),
|
|
})
|
|
if (!res.ok) throw new Error(`Login failed: ${res.status}`)
|
|
const data = await res.json()
|
|
this.token = data.token
|
|
}
|
|
|
|
async resetDb(): Promise<void> {
|
|
const res = await fetch(`${API_URL}/api/v1/test/reset-db`, {
|
|
method: "POST",
|
|
headers: this.authHeaders(),
|
|
})
|
|
if (!res.ok) throw new Error(`DB reset failed: ${res.status}`)
|
|
}
|
|
|
|
async getMembers(): Promise<any> {
|
|
return this.get("/api/v1/members")
|
|
}
|
|
|
|
async getDocuments(): Promise<any> {
|
|
return this.get("/api/v1/documents")
|
|
}
|
|
|
|
async getBatches(): Promise<any> {
|
|
return this.get("/api/v1/batches")
|
|
}
|
|
|
|
async getDistributions(): Promise<any> {
|
|
return this.get("/api/v1/distributions")
|
|
}
|
|
|
|
async getBoardPositions(): Promise<any> {
|
|
return this.get("/api/v1/board")
|
|
}
|
|
|
|
private authHeaders(): Record<string, string> {
|
|
const headers: Record<string, string> = {
|
|
"Content-Type": "application/json",
|
|
}
|
|
if (this.token) headers["Authorization"] = `Bearer ${this.token}`
|
|
return headers
|
|
}
|
|
|
|
private async get(path: string): Promise<any> {
|
|
const res = await fetch(`${API_URL}${path}`, {
|
|
headers: this.authHeaders(),
|
|
})
|
|
if (!res.ok) throw new Error(`GET ${path} failed: ${res.status}`)
|
|
return res.json()
|
|
}
|
|
|
|
private async post(path: string, body?: unknown): Promise<any> {
|
|
const res = await fetch(`${API_URL}${path}`, {
|
|
method: "POST",
|
|
headers: this.authHeaders(),
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
})
|
|
if (!res.ok) throw new Error(`POST ${path} failed: ${res.status}`)
|
|
return res.json()
|
|
}
|
|
}
|