/** * ICD Test Runner — Smoke Tier * Read-only GET tests for every endpoint domain. */ (function () { 'use strict'; var T = window.ICD; if (!T) return; T.runSmoke = async function () { // -- Health -- await T.test('smoke', 'utility', 'GET /health', async function () { var d = await T.apiGet('/health'); T.assert(d.status === 'ok', 'expected status "ok", got "' + d.status + '"'); }); // -- Public Settings -- await T.test('smoke', 'admin', 'GET /settings/public', async function () { var d = await T.apiGet('/settings/public'); T.assertHasKey(d, 'policies', 'public_settings'); T.assert(typeof d.policies === 'object', 'policies should be object'); }); // -- Profile -- await T.test('smoke', 'profile', 'GET /profile', async function () { 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 -- await T.test('smoke', 'profile', 'GET /settings (user)', async function () { var d = await T.apiGet('/settings'); T.assertHasKey(d, 'settings', 'user_settings'); }); // -- Models -- await T.test('smoke', 'models', 'GET /models/enabled', async function () { var d = await T.apiGet('/models/enabled'); T.assertHasKey(d, 'data', '/models/enabled'); T.assert(Array.isArray(d.data), 'data should be array'); if (d.data.length > 0) { T.assertShape(d.data[0], T.S.modelEnabled, 'data[0]'); } }); await T.test('smoke', 'models', 'GET /models/preferences', async function () { var d = await T.apiGet('/models/preferences'); T.assertHasKey(d, 'data', '/models/preferences'); T.assert(Array.isArray(d.data), 'data should be array'); if (d.data.length > 0) { T.assertShape(d.data[0], T.S.modelPreference, 'data[0]'); } }); // -- Surfaces -- await T.test('smoke', 'surfaces', 'GET /surfaces', async function () { var d = await T.apiGet('/surfaces'); T.assertHasKey(d, 'surfaces', '/surfaces'); T.assertArrayOf(d.surfaces, T.S.surfaceNav, 'surfaces'); // Our own surface should be in the list var found = d.surfaces.some(function (s) { return s.id === 'icd-test-runner'; }); T.assert(found, 'icd-test-runner not found in surfaces list'); }); // -- Channels -- await T.test('smoke', 'channels', 'GET /channels', async function () { var d = await T.apiGet('/channels'); // Paginated envelope or { data: [...] } var arr = d.data || d.channels; T.assert(Array.isArray(arr), 'expected data array from /channels'); }); // -- Personas -- await T.test('smoke', 'personas', 'GET /personas', async function () { var d = await T.apiGet('/personas'); T.assertHasKey(d, 'data', '/personas'); T.assert(Array.isArray(d.data), 'personas should be array'); }); // -- Persona Groups -- await T.test('smoke', 'personas', 'GET /persona-groups', async function () { var d = await T.apiGet('/persona-groups'); T.assertHasKey(d, 'data', '/persona-groups'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Knowledge Bases -- await T.test('smoke', 'knowledge', 'GET /knowledge-bases', async function () { var d = await T.apiGet('/knowledge-bases'); T.assertHasKey(d, 'data', '/knowledge-bases'); T.assert(Array.isArray(d.data), 'data should be array'); }); await T.test('smoke', 'knowledge', 'GET /knowledge-bases-discoverable', async function () { var d = await T.apiGet('/knowledge-bases-discoverable'); T.assertHasKey(d, 'data', '/kb-discoverable'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Notes -- await T.test('smoke', 'notes', 'GET /notes', async function () { var d = await T.apiGet('/notes'); // Paginated or { data: [...] } var arr = d.data || d.notes; T.assert(Array.isArray(arr), 'expected array from /notes'); }); await T.test('smoke', 'notes', 'GET /notes/folders', async function () { var d = await T.apiGet('/notes/folders'); T.assertHasKey(d, 'folders', '/notes/folders'); T.assert(Array.isArray(d.folders), 'folders should be array'); }); await T.test('smoke', 'notes', 'GET /notes/graph', async function () { var d = await T.apiGet('/notes/graph'); T.assertHasKey(d, 'nodes', '/notes/graph'); T.assertHasKey(d, 'edges', '/notes/graph'); T.assert(Array.isArray(d.nodes), 'nodes should be array'); T.assert(Array.isArray(d.edges), 'edges should be array'); }); // -- Projects -- await T.test('smoke', 'projects', 'GET /projects', async function () { var d = await T.apiGet('/projects'); T.assertHasKey(d, 'data', '/projects'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Memories -- await T.test('smoke', 'memory', 'GET /memories', async function () { var d = await T.apiGet('/memories'); T.assertHasKey(d, 'data', '/memories'); T.assert(Array.isArray(d.data), 'data should be array'); }); await T.test('smoke', 'memory', 'GET /memories/count', async function () { var d = await T.apiGet('/memories/count'); T.assertHasKey(d, 'active', '/memories/count'); T.assertHasKey(d, 'pending', '/memories/count'); T.assert(typeof d.active === 'number', 'active should be number'); T.assert(typeof d.pending === 'number', 'pending should be number'); }); // -- Notifications -- await T.test('smoke', 'notifications', 'GET /notifications', async function () { 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'); }); await T.test('smoke', 'notifications', 'GET /notifications/unread-count', async function () { 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'); }); await T.test('smoke', 'notifications', 'GET /notifications/preferences', async function () { var d = await T.apiGet('/notifications/preferences'); T.assertHasKey(d, 'data', '/notifications/preferences'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Extensions -- await T.test('smoke', 'extensions', 'GET /extensions', async function () { var d = await T.apiGet('/extensions'); T.assertHasKey(d, 'data', '/extensions'); T.assert(Array.isArray(d.data), 'extensions should be array'); }); await T.test('smoke', 'extensions', 'GET /extensions/tools', async function () { var d = await T.apiGet('/extensions/tools'); T.assertHasKey(d, 'data', '/extensions/tools'); T.assert(Array.isArray(d.data), 'tools should be array'); }); // -- Tools -- await T.test('smoke', 'channels', 'GET /tools', async function () { var d = await T.apiGet('/tools'); T.assertHasKey(d, 'tools', '/tools'); T.assert(Array.isArray(d.tools), 'tools should be array'); }); // -- Provider Configs (BYOK) -- await T.test('smoke', 'providers', 'GET /api-configs', async function () { var d = await T.apiGet('/api-configs'); T.assertHasKey(d, 'configs', '/api-configs'); T.assert(Array.isArray(d.configs), 'configs should be array'); }); // -- Teams -- await T.test('smoke', 'teams', 'GET /teams/mine', async function () { var d = await T.apiGet('/teams/mine'); T.assertHasKey(d, 'data', '/teams/mine'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Groups -- await T.test('smoke', 'teams', 'GET /groups/mine', async function () { var d = await T.apiGet('/groups/mine'); T.assertHasKey(d, 'data', '/groups/mine'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Tasks -- await T.test('smoke', 'tasks', 'GET /tasks', async function () { var d = await T.apiGet('/tasks'); T.assertHasKey(d, 'data', '/tasks'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Workspaces -- await T.test('smoke', 'workspaces', 'GET /workspaces', async function () { var d = await T.apiGet('/workspaces'); T.assertHasKey(d, 'data', '/workspaces'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Folders -- await T.test('smoke', 'channels', 'GET /folders', async function () { var d = await T.apiGet('/folders'); // May be { data: [...] } or { folders: [...] } var arr = d.data || d.folders; T.assert(arr === undefined || Array.isArray(arr), 'expected array from /folders'); }); // -- Files -- await T.test('smoke', 'channels', 'GET /files', async function () { var d = await T.apiGet('/files'); T.assertHasKey(d, 'files', '/files'); T.assert(Array.isArray(d.files), 'files should be array'); T.assert(typeof d.total === 'number', 'expected total count'); }); // -- Usage -- await T.test('smoke', 'admin', 'GET /usage', async function () { var d = await T.apiGet('/usage'); // personal usage — may have totals, results T.assert(typeof d === 'object', 'expected object from /usage'); }); // -- Workflow Assignments -- await T.test('smoke', 'workflows', 'GET /workflow-assignments/mine', async function () { var d = await T.apiGet('/workflow-assignments/mine'); // May be { data: [...] } or { assignments: [...] } var arr = d.data || d.assignments; T.assert(arr === undefined || Array.isArray(arr), 'expected array from /workflow-assignments/mine'); }); // -- Workflows -- await T.test('smoke', 'workflows', 'GET /workflows', async function () { var d = await T.apiGet('/workflows'); T.assertHasKey(d, 'data', '/workflows'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Git Credentials -- await T.test('smoke', 'workspaces', 'GET /git-credentials', async function () { var d = await T.apiGet('/git-credentials'); T.assertHasKey(d, 'data', '/git-credentials'); T.assert(Array.isArray(d.data), 'data should be array'); }); // -- Presence -- await T.test('smoke', 'channels', 'POST /presence/heartbeat', async function () { var d = await T.apiPost('/presence/heartbeat', {}); T.assert(d.ok === true, 'expected { ok: true }'); }); await T.test('smoke', 'channels', 'GET /presence (query)', async function () { var d = await T.apiGet('/presence?users=' + encodeURIComponent(T.user.id)); T.assertHasKey(d, 'presence', '/presence'); T.assert(typeof d.presence === 'object', 'presence should be object'); // After heartbeat, our own user should be online if (d.presence[T.user.id]) { T.assert(d.presence[T.user.id] === 'online', 'expected self online after heartbeat'); } }); // -- Admin routes (only if admin) -- if (T.user.role === 'admin') { await T.test('smoke', 'admin', 'GET /admin/stats', async function () { var d = await T.apiGet('/admin/stats'); T.assertHasKey(d, 'users', '/admin/stats'); T.assertHasKey(d, 'channels', '/admin/stats'); T.assertHasKey(d, 'messages', '/admin/stats'); }); await T.test('smoke', 'admin', 'GET /admin/users', async function () { var d = await T.apiGet('/admin/users'); T.assertHasKey(d, 'users', '/admin/users'); T.assert(Array.isArray(d.users), 'users should be array'); }); await T.test('smoke', 'admin', 'GET /admin/settings', async function () { var d = await T.apiGet('/admin/settings'); T.assert(typeof d === 'object', 'expected object'); }); await T.test('smoke', 'admin', 'GET /admin/configs', async function () { var d = await T.apiGet('/admin/configs'); T.assertHasKey(d, 'configs', '/admin/configs'); T.assert(Array.isArray(d.configs), 'configs should be array'); }); await T.test('smoke', 'admin', 'GET /admin/models', async function () { var d = await T.apiGet('/admin/models'); T.assertHasKey(d, 'models', '/admin/models'); T.assert(Array.isArray(d.models), 'models should be array'); }); await T.test('smoke', 'admin', 'GET /admin/personas', async function () { var d = await T.apiGet('/admin/personas'); T.assertHasKey(d, 'data', '/admin/personas'); }); await T.test('smoke', 'admin', 'GET /admin/teams', async function () { var d = await T.apiGet('/admin/teams'); T.assertHasKey(d, 'data', '/admin/teams'); }); await T.test('smoke', 'admin', 'GET /admin/groups', async function () { var d = await T.apiGet('/admin/groups'); T.assertHasKey(d, 'data', '/admin/groups'); }); await T.test('smoke', 'admin', 'GET /admin/surfaces', async function () { var d = await T.apiGet('/admin/surfaces'); T.assertHasKey(d, 'surfaces', '/admin/surfaces'); T.assert(Array.isArray(d.surfaces), 'surfaces should be array'); if (d.surfaces.length > 0) { T.assertShape(d.surfaces[0], T.S.surfaceAdmin, 'surfaces[0]'); } }); await T.test('smoke', 'admin', 'GET /admin/providers/health', async function () { var d = await T.apiGet('/admin/providers/health'); T.assertHasKey(d, 'data', '/admin/providers/health'); }); await T.test('smoke', 'admin', 'GET /admin/capability-overrides', async function () { var d = await T.apiGet('/admin/capability-overrides'); T.assertHasKey(d, 'data', '/admin/capability-overrides'); }); await T.test('smoke', 'admin', 'GET /admin/routing/policies', async function () { var d = await T.apiGet('/admin/routing/policies'); T.assertHasKey(d, 'data', '/admin/routing/policies'); }); await T.test('smoke', 'admin', 'GET /admin/permissions', async function () { var d = await T.apiGet('/admin/permissions'); T.assertHasKey(d, 'permissions', '/admin/permissions'); }); await T.test('smoke', 'admin', 'GET /admin/roles', async function () { var d = await T.apiGet('/admin/roles'); // Returns a raw JSONMap of role configs (e.g. { chat: {...}, summary: {...} }) T.assert(typeof d === 'object' && d !== null, 'expected object'); }); await T.test('smoke', 'admin', 'GET /admin/vault/status', async function () { var d = await T.apiGet('/admin/vault/status'); T.assert(typeof d === 'object', 'expected object'); }); await T.test('smoke', 'admin', 'GET /admin/storage/status', async function () { var d = await T.apiGet('/admin/storage/status'); T.assert(typeof d === 'object', 'expected object'); }); await T.test('smoke', 'admin', 'GET /admin/audit', async function () { 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'); }); await T.test('smoke', 'admin', 'GET /admin/audit/actions', async function () { var d = await T.apiGet('/admin/audit/actions'); T.assertHasKey(d, 'actions', '/admin/audit/actions'); }); await T.test('smoke', 'admin', 'GET /admin/usage', async function () { var d = await T.apiGet('/admin/usage'); T.assert(typeof d === 'object', 'expected object'); }); await T.test('smoke', 'admin', 'GET /admin/pricing', async function () { var d = await T.apiGet('/admin/pricing'); // Returns a bare array (no envelope) T.assert(Array.isArray(d), '/admin/pricing should return array'); }); await T.test('smoke', 'admin', 'GET /admin/provider-types', async function () { var d = await T.apiGet('/admin/provider-types'); T.assertHasKey(d, 'data', '/admin/provider-types'); T.assert(Array.isArray(d.data), 'data should be array'); }); await T.test('smoke', 'admin', 'GET /admin/tasks', async function () { var d = await T.apiGet('/admin/tasks'); T.assertHasKey(d, 'data', '/admin/tasks'); T.assert(Array.isArray(d.data), 'data should be array'); }); await T.test('smoke', 'admin', 'GET /admin/projects', async function () { var d = await T.apiGet('/admin/projects'); T.assertHasKey(d, 'data', '/admin/projects'); }); await T.test('smoke', 'admin', 'GET /admin/channels/archived', async function () { var d = await T.apiGet('/admin/channels/archived'); T.assertHasKey(d, 'channels', '/admin/channels/archived'); T.assert(Array.isArray(d.channels), 'channels should be array'); T.assertHasKey(d, 'total', '/admin/channels/archived'); T.assertHasKey(d, 'retention_mode', '/admin/channels/archived'); }); await T.test('smoke', 'admin', 'GET /admin/storage/orphans', async function () { var d = await T.apiGet('/admin/storage/orphans'); T.assertHasKey(d, 'count', '/admin/storage/orphans'); }); await T.test('smoke', 'admin', 'GET /admin/settings/:key (banner)', async function () { 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"'); }); await T.test('smoke', 'admin', 'GET /admin/storage/extraction', async function () { var d = await T.apiGet('/admin/storage/extraction'); T.assert(typeof d === 'object', 'expected object'); }); await T.test('smoke', 'memory', 'GET /admin/memories/pending', async function () { var d = await T.apiGet('/admin/memories/pending'); T.assertHasKey(d, 'data', '/admin/memories/pending'); T.assert(Array.isArray(d.data), 'data should be array'); }); } }; })();