v0.71.0: admin panel — users table, login/sessions, generic DB CRUD modal
CI / build + unit + e2e (pull_request) Failing after 13m35s
CI / build + unit + e2e (pull_request) Failing after 13m35s
This commit is contained in:
+55
-1
@@ -3,12 +3,17 @@ import { describe, expect, it } from 'vitest';
|
||||
import { openApiSpec } from './openapi';
|
||||
|
||||
describe('OpenAPI spec', () => {
|
||||
it('documents exactly the twelve public endpoints (4 read + 8 player actions)', () => {
|
||||
it('documents exactly the seventeen public endpoints (6 read + 8 player actions + 2 auth + 1 admin CRUD)', () => {
|
||||
expect(Object.keys(openApiSpec.paths).sort()).toEqual([
|
||||
'/api/admin/tables', // v0.71.0 — admin panel
|
||||
'/api/admin/tables/{name}/rows', // v0.71.0 — GET+PUT+POST+DELETE on one path
|
||||
'/api/airports',
|
||||
'/api/events', // v0.57.0 (ISS-129) — SSE state stream
|
||||
'/api/login', // v0.71.0 — admin panel auth
|
||||
'/api/logout', // v0.71.0
|
||||
'/api/market/buy-plane',
|
||||
'/api/market/sell-plane',
|
||||
'/api/me', // v0.71.0
|
||||
'/api/packages/{id}/abandon',
|
||||
'/api/packages/{id}/load',
|
||||
'/api/planes/{planeId}/fly',
|
||||
@@ -242,4 +247,53 @@ describe('OpenAPI spec', () => {
|
||||
expect(sell.required).toEqual(['planeId']);
|
||||
expect(sell.properties.planeId.type).toBe('string');
|
||||
});
|
||||
|
||||
it('documents the v0.71.0 admin-panel endpoints: auth + guarded DB CRUD', () => {
|
||||
const paths = openApiSpec.paths as Record<string, Record<string, { responses: Record<string, unknown>; requestBody?: unknown; parameters?: Array<{ name: string }> }>>;
|
||||
|
||||
// Error codes per endpoint (401/403 on every admin route — the guard runs before input).
|
||||
const codes = (p: string, m: string) => Object.keys(paths[p][m].responses).sort();
|
||||
expect(codes('/api/login', 'post')).toEqual(['200', '400', '401']);
|
||||
expect(codes('/api/logout', 'post')).toEqual(['200', '401']);
|
||||
expect(codes('/api/me', 'get')).toEqual(['200', '401']);
|
||||
expect(codes('/api/admin/tables', 'get')).toEqual(['200', '401', '403']);
|
||||
for (const m of ['get', 'put', 'post', 'delete'] as const) {
|
||||
expect(codes(`/api/admin/tables/{name}/rows`, m), `${m} rows`).toContain('401');
|
||||
expect(codes(`/api/admin/tables/{name}/rows`, m), `${m} rows`).toContain('403');
|
||||
expect(codes(`/api/admin/tables/{name}/rows`, m), `${m} rows`).toContain('404');
|
||||
}
|
||||
|
||||
// Success shapes.
|
||||
const ok = (p: string, m: string) => paths[p][m].responses['200'] as { content: Record<string, { schema: unknown }> };
|
||||
expect((ok('/api/login', 'post').content['application/json'].schema as { $ref: string }).$ref).toBe('#/components/schemas/LoginResponse');
|
||||
expect((ok('/api/me', 'get').content['application/json'].schema as { $ref: string }).$ref).toBe('#/components/schemas/SessionUser');
|
||||
const tables = ok('/api/admin/tables', 'get').content['application/json'].schema as { type: string; items: { $ref: string } };
|
||||
expect(tables.type).toBe('array');
|
||||
expect(tables.items.$ref).toBe('#/components/schemas/AdminTable');
|
||||
const rows = ok('/api/admin/tables/{name}/rows', 'get').content['application/json'].schema as { $ref: string };
|
||||
expect(rows.$ref).toBe('#/components/schemas/AdminRowsResponse');
|
||||
|
||||
// Request bodies + path parameter.
|
||||
const bodyRef = (p: string, m: string) =>
|
||||
((paths[p][m].requestBody ?? {}) as { content?: Record<string, { schema: { $ref: string } }> }).content?.['application/json']
|
||||
?.schema.$ref;
|
||||
expect(bodyRef('/api/login', 'post')).toBe('#/components/schemas/LoginRequest');
|
||||
expect(bodyRef('/api/admin/tables/{name}/rows', 'put')).toBe('#/components/schemas/UpdateRowRequest');
|
||||
expect(bodyRef('/api/admin/tables/{name}/rows', 'post')).toBe('#/components/schemas/InsertRowRequest');
|
||||
for (const m of ['get', 'put', 'post', 'delete'] as const) {
|
||||
expect(paths['/api/admin/tables/{name}/rows'][m].parameters?.map((x) => x.name)).toContain('name');
|
||||
}
|
||||
|
||||
// Request schema shapes.
|
||||
const login = openApiSpec.components.schemas.LoginRequest;
|
||||
expect(login.required).toEqual(['username', 'password']);
|
||||
expect(login.properties.username.type).toBe('string');
|
||||
expect(login.properties.password.type).toBe('string');
|
||||
const sessionUser = openApiSpec.components.schemas.SessionUser;
|
||||
expect(sessionUser.required.sort()).toEqual(['admin', 'username']);
|
||||
expect(sessionUser.properties.admin.type).toBe('boolean');
|
||||
const updateRow = openApiSpec.components.schemas.UpdateRowRequest;
|
||||
expect(updateRow.required).toEqual(['rowid', 'values']);
|
||||
expect(updateRow.properties.rowid.type).toBe('integer');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user