import test from 'node:test'; import assert from 'node:assert/strict'; import request from 'supertest'; import { createApp } from '../src/app.js'; process.env.AUTH_BYPASS = 'true'; const tenantId = '11111111-1111-4111-8111-111111111111'; const orderId = '22222222-2222-4222-8222-222222222222'; const businessId = '33333333-3333-4333-8333-333333333333'; const staffId = '44444444-4444-4444-8444-444444444444'; const assignmentId = '55555555-5555-4555-8555-555555555555'; test('GET /healthz returns healthy response', async () => { const app = createApp(); const res = await request(app).get('/healthz'); assert.equal(res.status, 200); assert.equal(res.body.ok, true); assert.equal(res.body.service, 'krow-query-api'); assert.equal(typeof res.body.requestId, 'string'); assert.equal(typeof res.headers['x-request-id'], 'string'); }); test('GET /readyz reports database not configured when no database env is present', async () => { delete process.env.DATABASE_URL; delete process.env.DB_HOST; delete process.env.DB_NAME; delete process.env.DB_USER; delete process.env.DB_PASSWORD; delete process.env.INSTANCE_CONNECTION_NAME; const app = createApp(); const res = await request(app).get('/readyz'); assert.equal(res.status, 503); assert.equal(res.body.status, 'DATABASE_NOT_CONFIGURED'); }); test.afterEach(() => { delete process.env.AUTH_BYPASS_CONTEXT; }); test('createApp fails fast in protected env when auth bypass is enabled', async () => { process.env.APP_ENV = 'staging'; process.env.AUTH_BYPASS = 'true'; assert.throws(() => createApp(), /AUTH_BYPASS must be disabled/); delete process.env.APP_ENV; process.env.AUTH_BYPASS = 'true'; }); test('GET unknown route returns not found envelope', async () => { const app = createApp(); const res = await request(app).get('/query/unknown'); assert.equal(res.status, 404); assert.equal(res.body.code, 'NOT_FOUND'); assert.equal(typeof res.body.requestId, 'string'); }); test('GET /query/tenants/:tenantId/orders returns injected query result', async () => { const app = createApp({ queryService: { listOrders: async (params) => { assert.equal(params.tenantId, tenantId); return [{ id: orderId, orderNumber: 'ORD-1001', title: 'Cafe Event Staffing', status: 'OPEN', }]; }, getOrderDetail: async () => assert.fail('getOrderDetail should not be called'), listFavoriteStaff: async () => assert.fail('listFavoriteStaff should not be called'), getStaffReviewSummary: async () => assert.fail('getStaffReviewSummary should not be called'), getAssignmentAttendance: async () => assert.fail('getAssignmentAttendance should not be called'), }, }); const res = await request(app) .get(`/query/tenants/${tenantId}/orders`) .set('Authorization', 'Bearer test-token'); assert.equal(res.status, 200); assert.equal(res.body.items.length, 1); assert.equal(res.body.items[0].id, orderId); }); test('GET /query/tenants/:tenantId/assignments/:assignmentId/attendance returns injected attendance', async () => { const app = createApp({ queryService: { listOrders: async () => assert.fail('listOrders should not be called'), getOrderDetail: async () => assert.fail('getOrderDetail should not be called'), listFavoriteStaff: async () => assert.fail('listFavoriteStaff should not be called'), getStaffReviewSummary: async () => assert.fail('getStaffReviewSummary should not be called'), getAssignmentAttendance: async (params) => { assert.equal(params.tenantId, tenantId); assert.equal(params.assignmentId, assignmentId); return { assignmentId, sessionStatus: 'OPEN', events: [], }; }, }, }); const res = await request(app) .get(`/query/tenants/${tenantId}/assignments/${assignmentId}/attendance`) .set('Authorization', 'Bearer test-token'); assert.equal(res.status, 200); assert.equal(res.body.assignmentId, assignmentId); assert.equal(res.body.sessionStatus, 'OPEN'); }); test('GET /query/tenants/:tenantId/businesses/:businessId/favorite-staff validates auth and handler wiring', async () => { const app = createApp({ queryService: { listOrders: async () => assert.fail('listOrders should not be called'), getOrderDetail: async () => assert.fail('getOrderDetail should not be called'), listFavoriteStaff: async (params) => { assert.equal(params.tenantId, tenantId); assert.equal(params.businessId, businessId); return [{ staffId, fullName: 'Ana Barista' }]; }, getStaffReviewSummary: async () => assert.fail('getStaffReviewSummary should not be called'), getAssignmentAttendance: async () => assert.fail('getAssignmentAttendance should not be called'), }, }); const res = await request(app) .get(`/query/tenants/${tenantId}/businesses/${businessId}/favorite-staff`) .set('Authorization', 'Bearer test-token'); assert.equal(res.status, 200); assert.equal(res.body.items[0].staffId, staffId); }); test('GET /query/tenants/:tenantId/orders denies mismatched tenant scope before handler execution', async () => { process.env.AUTH_BYPASS_CONTEXT = JSON.stringify({ user: { userId: 'test-user' }, tenant: { tenantId: '99999999-9999-4999-8999-999999999999', role: 'MANAGER' }, business: { businessId }, }); const app = createApp({ queryService: { listOrders: async () => assert.fail('listOrders should not be called'), getOrderDetail: async () => assert.fail('getOrderDetail should not be called'), listFavoriteStaff: async () => assert.fail('listFavoriteStaff should not be called'), getStaffReviewSummary: async () => assert.fail('getStaffReviewSummary should not be called'), getAssignmentAttendance: async () => assert.fail('getAssignmentAttendance should not be called'), }, }); const res = await request(app) .get(`/query/tenants/${tenantId}/orders`) .set('Authorization', 'Bearer test-token'); assert.equal(res.status, 403); assert.equal(res.body.code, 'FORBIDDEN'); });