'use strict'; /** * Integration tests: Feature flag gates (requireFeature middleware). * Toggles app_settings directly in DB. Checks that disabled feature = 404, * enabled feature = 401 (route exists, auth required, not feature-blocked). */ const { describe, it, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { db, inject, getToken, cleanup } = require('./setup'); after(() => cleanup()); /** * Helper: set a feature flag in app_settings. * @param {string} name e.g. 'pet', 'biochem' * @param {boolean} enabled */ function setFeature(name, enabled) { db.prepare( "INSERT OR REPLACE INTO app_settings (key, value) VALUES (?, ?)" ).run(`feature_${name}_enabled`, enabled ? '1' : '0'); } describe('Feature Flag Gates', () => { let adminToken; before(async () => { const a = await getToken('admin'); adminToken = a.token; }); // ── 1. /api/pet disabled → 404 ─────────────────────────────────────────── it('GET /api/pet returns 404 when pet feature is disabled', async () => { setFeature('pet', false); const res = await inject('GET', '/api/pet', null, adminToken); assert.equal(res.status, 404, `expected 404 when pet disabled, got ${res.status}`); }); // ── 2. /api/pet enabled → 401 (route works, auth required, not feature-blocked) it('GET /api/pet returns 401 (not 404) when pet feature is enabled and no token', async () => { setFeature('pet', true); const res = await inject('GET', '/api/pet', null, null); // Feature not disabled, so middleware passes. Auth fails → 401. assert.equal(res.status, 401, `expected 401 when pet enabled but no token, got ${res.status}`); }); // ── 3. /api/biochem/elements disabled → 404 ───────────────────────────── it('GET /api/biochem/elements returns 404 when biochem feature is disabled', async () => { setFeature('biochem', false); const res = await inject('GET', '/api/biochem/elements', null, adminToken); assert.equal(res.status, 404, `expected 404 when biochem disabled, got ${res.status}`); }); // ── 4. /api/biochem/elements enabled → 200 (authenticated admin) it('GET /api/biochem/elements is accessible when biochem feature is enabled', async () => { setFeature('biochem', true); const res = await inject('GET', '/api/biochem/elements', null, adminToken); // Feature not disabled; admin is authenticated → should get data (200) not feature-block (404) assert.notEqual(res.status, 404, `expected feature to be accessible (not 404), got ${res.status}`); assert.ok(res.status < 500, `unexpected server error: ${res.status}`); }); // ── 5. Feature toggle via admin API also works ──────────────────────────── it('admin PATCH /api/admin/features can disable pet, then re-enable', async () => { // Enable first const enableRes = await inject('PATCH', '/api/admin/features', { pet: true }, adminToken); assert.equal(enableRes.status, 200, `expected 200, got ${enableRes.status}`); // Check feature is accessible (auth required, no token → 401, not 404) const accessible = await inject('GET', '/api/pet', null, null); assert.equal(accessible.status, 401, `expected 401 (feature on), got ${accessible.status}`); // Disable via admin API const disableRes = await inject('PATCH', '/api/admin/features', { pet: false }, adminToken); assert.equal(disableRes.status, 200); // Now should be 404 const blocked = await inject('GET', '/api/pet', null, adminToken); assert.equal(blocked.status, 404, `expected 404 after disabling pet, got ${blocked.status}`); // Re-enable for other tests await inject('PATCH', '/api/admin/features', { pet: true }, adminToken); }); });