/** * ICD Test Runner — Smoke Tier * Read-only GET tests for kernel endpoints only. * Extension-specific endpoints belong in package runners, not here. */ (function () { 'use strict'; var T = window.ICD; if (!T) return; if (!window.sw || !window.sw.testing) return; sw.testing.suite('icd/smoke', async function (s) { // -- Health -- s.test('utility: GET /health', async function (t) { var d = await T.apiGet('/health'); T.assert(d.status === 'ok', 'expected status "ok", got "' + d.status + '"'); }); // -- Public Settings -- s.test('admin: GET /settings/public', async function (t) { var d = await T.apiGet('/settings/public'); T.assertHasKey(d, 'policies', 'public_settings'); T.assert(typeof d.policies === 'object', 'policies should be object'); }); // -- Profile -- s.test('profile: GET /profile', async function (t) { var d = await T.apiGet('/profile'); T.assertShape(d, T.S.profile, 'profile'); T.assert(d.username.length > 0, 'username should be non-empty'); }); // -- User Settings -- s.test('profile: GET /settings (user)', async function (t) { var d = await T.apiGet('/settings'); T.assertHasKey(d, 'settings', 'user_settings'); }); // -- Surfaces -- s.test('surfaces: GET /surfaces', async function (t) { var d = await T.apiGet('/surfaces'); T.assertHasKey(d, 'data', '/surfaces'); T.assertArrayOf(d.data, T.S.surfaceNav, 'surfaces'); // test-runners registry surface should be in the list (type "surface") var found = d.data.some(function (s) { return s.id === 'test-runners'; }); T.assert(found, 'test-runners not found in surfaces list'); // icd-test-runner is type "test-runner" — correctly excluded from /surfaces }); // -- Notifications -- s.test('notifications: GET /notifications', async function (t) { var d = await T.apiGet('/notifications'); T.assertHasKey(d, 'data', '/notifications'); T.assert(Array.isArray(d.data), 'data should be array'); T.assertHasKey(d, 'total', '/notifications'); T.assert(typeof d.total === 'number', 'total should be number'); }); s.test('notifications: GET /notifications/unread-count', async function (t) { var d = await T.apiGet('/notifications/unread-count'); T.assertHasKey(d, 'count', '/notifications/unread-count'); T.assert(typeof d.count === 'number', 'count should be number'); }); s.test('notifications: GET /notifications/preferences', async function (t) { var d = await T.apiGet('/notifications/preferences'); T.assertHasKey(d, 'data', '/notifications/preferences'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Extensions -- s.test('extensions: GET /extensions', async function (t) { var d = await T.apiGet('/extensions'); T.assertHasKey(d, 'data', '/extensions'); T.assert(Array.isArray(d.data), 'extensions should be array'); }); s.test('extensions: GET /extensions/tools', async function (t) { var d = await T.apiGet('/extensions/tools'); T.assertHasKey(d, 'data', '/extensions/tools'); T.assert(Array.isArray(d.data), 'tools should be array'); }); // -- Teams -- s.test('teams: GET /teams/mine', async function (t) { var d = await T.apiGet('/teams/mine'); T.assertHasKey(d, 'data', '/teams/mine'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Groups -- s.test('teams: GET /groups/mine', async function (t) { var d = await T.apiGet('/groups/mine'); T.assertHasKey(d, 'data', '/groups/mine'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Workflows -- s.test('workflows: GET /workflows', async function (t) { var d = await T.apiGet('/workflows'); T.assertHasKey(d, 'data', '/workflows'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Docs API -- s.test('utility: GET /docs', async function (t) { var d = await T.apiGet('/docs'); T.assertHasKey(d, 'data', '/docs'); T.assert(Array.isArray(d.data), 'docs should be array'); }); // -- Dynamic OpenAPI spec (outside /api/v1 prefix) -- s.test('utility: GET /api/docs/openapi.json', async function (t) { var token = await T.getAuthToken(); var resp = await fetch(T.base + '/api/docs/openapi.json', { headers: { 'Authorization': 'Bearer ' + token }, credentials: 'same-origin' }); T.assert(resp.ok, 'expected 200 from /api/docs/openapi.json, got ' + resp.status); var d = await resp.json(); T.assertHasKey(d, 'openapi', 'openapi spec'); T.assertHasKey(d, 'paths', 'openapi spec'); T.assertHasKey(d, 'info', 'openapi spec'); }); // -- Admin routes (only if admin) -- if (sw.isAdmin) { s.test('admin: GET /admin/stats', async function (t) { var d = await T.apiGet('/admin/stats'); T.assert(typeof d === 'object', 'expected object from /admin/stats'); }); s.test('admin: GET /admin/users', async function (t) { var d = await T.apiGet('/admin/users'); var arr = d.users || d.data; T.assert(Array.isArray(arr), 'expected array from /admin/users'); }); s.test('admin: GET /admin/settings', async function (t) { var d = await T.apiGet('/admin/settings'); T.assert(typeof d === 'object', 'expected object'); }); s.test('admin: GET /admin/settings/:key (banner)', async function (t) { var d = await T.apiGet('/admin/settings/banner'); T.assertHasKey(d, 'key', '/admin/settings/:key'); T.assertHasKey(d, 'value', '/admin/settings/:key'); T.assert(d.key === 'banner', 'key should be "banner"'); }); s.test('admin: GET /admin/teams', async function (t) { var d = await T.apiGet('/admin/teams'); T.assertHasKey(d, 'data', '/admin/teams'); }); s.test('admin: GET /admin/groups', async function (t) { var d = await T.apiGet('/admin/groups'); T.assertHasKey(d, 'data', '/admin/groups'); }); s.test('admin: GET /admin/packages', async function (t) { var d = await T.apiGet('/admin/packages'); T.assertHasKey(d, 'data', '/admin/packages'); T.assert(Array.isArray(d.data), 'surfaces should be array'); if (d.data.length > 0) { T.assertShape(d.data[0], T.S.surfaceAdmin, 'surfaces[0]'); } }); s.test('admin: GET /admin/permissions', async function (t) { var d = await T.apiGet('/admin/permissions'); T.assertHasKey(d, 'permissions', '/admin/permissions'); }); s.test('admin: GET /admin/audit', async function (t) { var d = await T.apiGet('/admin/audit'); T.assertHasKey(d, 'data', '/admin/audit'); T.assert(Array.isArray(d.data), 'data should be array'); T.assertHasKey(d, 'total', '/admin/audit'); T.assertHasKey(d, 'page', '/admin/audit'); T.assertHasKey(d, 'per_page', '/admin/audit'); }); s.test('admin: GET /admin/audit/actions', async function (t) { var d = await T.apiGet('/admin/audit/actions'); T.assertHasKey(d, 'actions', '/admin/audit/actions'); }); s.test('admin: GET /admin/metrics', async function (t) { var d = await T.apiGet('/admin/metrics'); T.assert(typeof d === 'object', 'expected object from /admin/metrics'); }); s.test('admin: GET /admin/backups', async function (t) { var d = await T.apiGet('/admin/backups'); T.assertHasKey(d, 'data', '/admin/backups'); T.assert(Array.isArray(d.data), 'backups should be array'); }); s.test('admin: GET /admin/storage/status', async function (t) { var d = await T.apiGet('/admin/storage/status'); T.assert(typeof d === 'object', 'expected object'); }); } }); })();