/** * mizan-fastapi e2e — Real Chromium → React with generated hooks → real FastAPI server. * * Mirrors examples/django-react-site/mizan.spec.ts minus channel/form tests * (those features are Django-only — FastAPI projects use native equivalents * or skip them entirely). */ import { test, expect } from '@playwright/test' const BASE = process.env.HARNESS_URL || 'http://localhost:5175' async function fixture(page: any, name: string) { await page.goto(`${BASE}#${name}`) await page.waitForSelector('[data-testid="result"], [data-testid="error-type"]', { timeout: 10000 }) } async function getResult(page: any): Promise { const el = page.locator('[data-testid="result"]') if (await el.count() > 0) return JSON.parse(await el.textContent()) return null } async function getError(page: any) { const typeEl = page.locator('[data-testid="error-type"]') if (await typeEl.count() === 0) return null return { type: await typeEl.textContent(), code: await page.locator('[data-testid="error-code"]').textContent(), message: await page.locator('[data-testid="error-message"]').textContent(), } } // ─── Function hooks ───────────────────────────────────────────────────────── test.describe('generated function hooks', () => { test('useEcho returns echoed text', async ({ page }) => { await fixture(page, 'echo') const result = await getResult(page) expect(result.message).toBe('e2e-test') }) test('useAdd returns correct sum', async ({ page }) => { await fixture(page, 'add') const result = await getResult(page) expect(result.result).toBe(42) }) test('useMultiply returns product', async ({ page }) => { await fixture(page, 'multiply') const result = await getResult(page) expect(result.product).toBe(42) }) test('usePermissionCheckFn succeeds with correct secret', async ({ page }) => { await fixture(page, 'permission-success') const result = await getResult(page) expect(result.message).toBe('access granted') }) }) // ─── Error codes ──────────────────────────────────────────────────────────── test.describe('error codes from generated hooks', () => { test('non-existent function → MizanError NOT_FOUND', async ({ page }) => { await fixture(page, 'not-found') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(error!.code).toBe('NOT_FOUND') }) test('wrong input types → MizanError VALIDATION_ERROR', async ({ page }) => { await fixture(page, 'validation-error') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(error!.code).toBe('VALIDATION_ERROR') }) test('useWhoami anonymous → auth error', async ({ page }) => { await fixture(page, 'auth-required') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(['UNAUTHORIZED', 'FORBIDDEN']).toContain(error!.code) }) test('useStaffOnly anonymous → UNAUTHORIZED', async ({ page }) => { await fixture(page, 'staff-only') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(['UNAUTHORIZED', 'FORBIDDEN']).toContain(error!.code) }) test('useSuperuserOnly anonymous → UNAUTHORIZED', async ({ page }) => { await fixture(page, 'superuser-only') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(['UNAUTHORIZED', 'FORBIDDEN']).toContain(error!.code) }) test('useVerifiedOnly anonymous → FORBIDDEN', async ({ page }) => { await fixture(page, 'verified-only') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(['UNAUTHORIZED', 'FORBIDDEN']).toContain(error!.code) }) test('useNotImplementedFn → NOT_IMPLEMENTED', async ({ page }) => { await fixture(page, 'not-implemented') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(error!.code).toBe('NOT_IMPLEMENTED') }) test('useBuggyFn → INTERNAL_ERROR', async ({ page }) => { await fixture(page, 'internal-error') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(error!.code).toBe('INTERNAL_ERROR') }) test('usePermissionCheckFn wrong secret → FORBIDDEN', async ({ page }) => { await fixture(page, 'permission-error') const error = await getError(page) expect(error!.type).toBe('MizanError') expect(error!.code).toBe('FORBIDDEN') }) }) // ─── Context hooks ────────────────────────────────────────────────────────── test.describe('generated context hooks', () => { test('useCurrentUser returns anonymous data', async ({ page }) => { await page.goto(`${BASE}#context-current-user`) await page.waitForSelector('[data-testid="result"]', { timeout: 10000 }) const result = await getResult(page) expect(result.authenticated).toBe(false) expect(result.email).toBe('') }) })