import { readFileSync } from 'node:fs'; import { join } from 'node:path'; import { test, expect } from '@playwright/test'; // Read at test time so the assertions track package.json automatically. const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')) as { version: string }; test('GET /api/version returns the app version from package.json', async ({ page }) => { const res = await page.request.get('/api/version'); expect(res.status()).toBe(200); expect(res.headers()['content-type']).toContain('application/json'); const body = (await res.json()) as { version: string }; expect(body.version).toBe(pkg.version); }); test('GET /api/openapi serves the spec with all nine endpoints and the package.json version', async ({ page }) => { const res = await page.request.get('/api/openapi'); expect(res.status()).toBe(200); expect(res.headers()['content-type']).toContain('application/json'); const spec = (await res.json()) as { info: { title: string; version: string }; paths: Record }; expect(spec.info.title).toBe('Flight Ops API'); expect(spec.info.version).toBe(pkg.version); // v0.8.0 adds the five player-action endpoints to the four read-only ones. expect(Object.keys(spec.paths).sort()).toEqual([ '/api/airports', '/api/contracts/{id}/accept', '/api/market/buy-plane', '/api/market/sell-plane', '/api/planes/{planeId}/dispatch', '/api/planes/{planeId}/refuel', '/api/sim', '/api/state', '/api/version', ]); });