import { Page } from '@playwright/test' /** * Shared mock helper for the /stundenplan suite. Intercepts every endpoint * the school-service proxy serves so tests stay hermetic. */ export const MOCK_TEACHER_ID = '11111111-1111-1111-1111-111111111111' export const MOCK_SUBJECT_ID = '22222222-2222-2222-2222-222222222222' export const MOCK_CLASS_ID = '33333333-3333-3333-3333-333333333333' export interface MockClass { id: string name: string grade_level: number student_count: number notes?: string created_by_user_id: string created_at: string } export interface MockOpts { classes?: MockClass[] teachers?: unknown[] subjects?: unknown[] rooms?: unknown[] periods?: unknown[] curriculum?: unknown[] assignments?: unknown[] solutions?: unknown[] lessons?: unknown[] } export async function mockSchoolApi(page: Page, opts: MockOpts = {}) { const classes = opts.classes ?? [] const teachers = opts.teachers ?? [] const subjects = opts.subjects ?? [] const rooms = opts.rooms ?? [] const periods = opts.periods ?? [] const curriculum = opts.curriculum ?? [] const assignments = opts.assignments ?? [] const solutions = opts.solutions ?? [] const lessons = opts.lessons ?? [] await page.route('**/api/school/timetable/classes', async (route) => { if (route.request().method() === 'GET') { return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(classes) }) } if (route.request().method() === 'POST') { const body = JSON.parse(route.request().postData() || '{}') const created: MockClass = { id: 'new-class-id', name: body.name, grade_level: body.grade_level, student_count: body.student_count ?? 0, notes: body.notes, created_by_user_id: 'test-user', created_at: new Date().toISOString(), } classes.push(created) return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify(created) }) } return route.fulfill({ status: 405 }) }) const staticList = (path: string, data: unknown) => page.route(`**/api/school/timetable/${path}`, async (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(data) })) await staticList('teachers', teachers) await staticList('subjects', subjects) await staticList('rooms', rooms) await staticList('periods', periods) await staticList('curriculum', curriculum) await staticList('assignments', assignments) for (const path of [ 'constraints/teacher/unavailable-day', 'constraints/teacher/unavailable-window', 'constraints/teacher/max-hours-day', 'constraints/teacher/max-hours-week', 'constraints/teacher/excluded-subject', 'constraints/teacher/excluded-room', 'constraints/subject/max-consecutive', 'constraints/subject/preferred-period', 'constraints/subject/min-day-gap', 'constraints/subject/contiguous-when-repeated', 'constraints/subject/double-lesson', 'constraints/class/max-hours-day', 'constraints/class/no-gaps', 'constraints/room/requires-type', 'constraints/room/unavailable', ]) { await staticList(path, []) } await page.route('**/api/school/timetable/solutions', async (route) => { if (route.request().method() === 'GET') { return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(solutions) }) } if (route.request().method() === 'POST') { const body = JSON.parse(route.request().postData() || '{}') const created = { id: 'new-solution-id', created_by_user_id: 'test-user', name: body.name || 'Plan', status: 'pending', hard_score: null, soft_score: null, created_at: new Date().toISOString(), } ;(solutions as unknown[]).push(created) return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify(created) }) } return route.fulfill({ status: 405 }) }) await page.route(/\/api\/school\/timetable\/solutions\/[^/]+\/lessons$/, async (route) => { return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(lessons) }) }) await page.route(/\/api\/school\/timetable\/solutions\/[^/]+$/, async (route) => { if (route.request().method() === 'DELETE') { return route.fulfill({ status: 200, contentType: 'application/json', body: '{"message":"deleted"}' }) } const url = route.request().url() const id = url.split('/').pop() ?? '' const sol = (solutions as Array<{ id: string }>).find(s => s.id === id) if (!sol) return route.fulfill({ status: 404 }) return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(sol) }) }) }