Branding: bulk rename across 50+ files (Go, JS, CSS, HTML, YAML, JSON, shell scripts). Fix Helm chart description and git repo URLs. Fix test helper taglines. Admin surface: strip 14 gutted tabs (providers, models, personas, roles, knowledge, memory, tasks, health, routing, capabilities, channels, dashboard, usage, stats). Collapse to 4 categories: People, Workflows, System, Monitoring. Settings surface: strip 11 gutted tabs (models, personas, providers, roles, knowledge, memory, usage, workflows, tasks, data, gitkeys). Keep: general, appearance, profile, teams, connections, notifications. Team-admin surface: strip 5 gutted tabs (personas, providers, knowledge, tasks, usage). Keep: members, groups, connections, workflows, settings, activity. Components: delete chat-pane/ (13 files, 1938 lines) and notes-pane/ (10 files, 2381 lines). main.go: remove stale Health.Prune maintenance goroutine. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
151 lines
6.5 KiB
JavaScript
151 lines
6.5 KiB
JavaScript
/**
|
|
* ICD Test Runner — CRUD: Editor Package (v0.31.0)
|
|
* Tests the editor .pkg lifecycle: install → surface accessible →
|
|
* settings → export/import round-trip → core removal verification.
|
|
* Uses T.crud.buildTestZip() from _helpers.js.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
var T = window.ICD;
|
|
if (!T) return;
|
|
if (!T.crud) T.crud = {};
|
|
|
|
var buildTestZip = T.crud.buildTestZip;
|
|
|
|
T.crud.editorPackage = async function (testTag) {
|
|
|
|
if (T.user.role !== 'admin') return;
|
|
|
|
// ── edpkg: Editor package install + lifecycle ──
|
|
|
|
var editorPkgId = null;
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: POST /admin/packages/install (editor .pkg)', async function () {
|
|
var manifest = JSON.stringify({
|
|
id: 'editor',
|
|
title: 'Editor',
|
|
type: 'full',
|
|
version: '0.31.0',
|
|
tier: 'browser',
|
|
author: 'Switchboard Core',
|
|
description: 'Code editor with workspace management',
|
|
route: '/s/editor',
|
|
layout: 'editor',
|
|
permissions: [],
|
|
settings: [
|
|
{ key: 'font_size', label: 'Font Size', type: 'number', 'default': 13 },
|
|
{ key: 'tab_size', label: 'Tab Size', type: 'number', 'default': 4 },
|
|
{ key: 'word_wrap', label: 'Word Wrap', type: 'boolean', 'default': false }
|
|
]
|
|
});
|
|
var zipBlob = buildTestZip({
|
|
'manifest.json': manifest,
|
|
'js/main.js': '// editor package entry point\nconsole.log("[EditorPkg] loaded");',
|
|
'css/main.css': '.surface-editor { display: flex; }'
|
|
});
|
|
|
|
var d = await T.apiUpload('/admin/packages/install', zipBlob, 'editor.pkg');
|
|
T.assert(d.id === 'editor', 'package id should be "editor", got: ' + d.id);
|
|
editorPkgId = d.id;
|
|
|
|
T.registerCleanup(async function () {
|
|
if (editorPkgId) {
|
|
var token = await T.getAuthToken();
|
|
return T.authFetch(token, 'DELETE', '/admin/packages/' + editorPkgId);
|
|
}
|
|
});
|
|
});
|
|
|
|
if (!editorPkgId) return;
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: GET /admin/packages/:id (verify type full)', async function () {
|
|
var d = await T.apiGet('/admin/packages/' + editorPkgId);
|
|
T.assertShape(d, T.S.extension, 'editor package');
|
|
T.assert(d.type === 'full', 'type should be "full", got: ' + d.type);
|
|
T.assert(d.tier === 'browser', 'tier should be "browser", got: ' + d.tier);
|
|
T.assert(d.source === 'extension', 'source should be "extension", got: ' + d.source);
|
|
T.assert(d.enabled === true, 'newly installed package should be enabled');
|
|
T.assert(d.version === '0.31.0', 'version mismatch');
|
|
});
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: GET /admin/surfaces (editor in list)', async function () {
|
|
var d = await T.apiGet('/admin/surfaces');
|
|
T.assertHasKey(d, 'data', '/admin/surfaces');
|
|
var found = d.data.some(function (s) { return s.id === 'editor'; });
|
|
T.assert(found, 'editor package should appear in surfaces list');
|
|
});
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: core /editor removed (404)', async function () {
|
|
// The old /editor route should no longer exist — it was removed in CS1.
|
|
// We test by checking the surfaces list for a core editor entry.
|
|
var d = await T.apiGet('/admin/surfaces');
|
|
var surfaces = d.data || [];
|
|
var coreEditor = surfaces.find(function (s) { return s.id === 'editor' && s.source === 'core'; });
|
|
T.assert(!coreEditor, 'no core editor surface should exist — editor is now a package');
|
|
});
|
|
|
|
// ── Settings ──
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: GET /admin/packages/:id/settings', async function () {
|
|
var d = await T.apiGet('/admin/packages/' + editorPkgId + '/settings');
|
|
// Settings endpoint returns the current settings (or defaults)
|
|
T.assert(typeof d === 'object', 'settings should be an object');
|
|
});
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: PUT /admin/packages/:id/settings', async function () {
|
|
var settings = { font_size: 16, tab_size: 2, word_wrap: true };
|
|
var d = await T.apiPut('/admin/packages/' + editorPkgId + '/settings', settings);
|
|
T.assert(d._status === 200 || d._status === 204 || !d._status, 'settings PUT should succeed');
|
|
|
|
// Verify persistence
|
|
var check = await T.apiGet('/admin/packages/' + editorPkgId + '/settings');
|
|
var vals = check.values || {};
|
|
T.assert(vals.font_size === 16, 'font_size should persist as 16');
|
|
});
|
|
|
|
// ── Export/Import Round-Trip ──
|
|
|
|
var exportBlob = null;
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: GET /admin/packages/:id/export', async function () {
|
|
var token = await T.getAuthToken();
|
|
var resp = await fetch(T.base + '/api/v1/admin/packages/' + editorPkgId + '/export', {
|
|
headers: { 'Authorization': 'Bearer ' + token }
|
|
});
|
|
T.assert(resp.ok, 'export should return 200, got: ' + resp.status);
|
|
exportBlob = await resp.blob();
|
|
T.assert(exportBlob.size > 0, 'export blob should not be empty');
|
|
});
|
|
|
|
if (exportBlob) {
|
|
await T.test('crud', 'editorPackage', 'edpkg: DELETE + re-import round-trip', async function () {
|
|
// Delete the editor package
|
|
var token = await T.getAuthToken();
|
|
var delResp = await T.authFetch(token, 'DELETE', '/admin/packages/' + editorPkgId);
|
|
T.assert(!delResp._status || delResp._status < 300, 'delete should succeed');
|
|
|
|
// Re-import from exported blob
|
|
var d = await T.apiUpload('/admin/packages/install', exportBlob, 'editor.pkg');
|
|
T.assert(d.id === 'editor', 'reimported package id should be "editor"');
|
|
|
|
// Verify it's back
|
|
var check = await T.apiGet('/admin/packages/' + editorPkgId);
|
|
T.assert(check.id === 'editor', 'reimported editor should be readable');
|
|
T.assert(check.type === 'full', 'reimported type should be "full"');
|
|
});
|
|
}
|
|
|
|
// ── Extension Nav ──
|
|
|
|
await T.test('crud', 'editorPackage', 'edpkg: editor in extension nav items', async function () {
|
|
// When installed, editor should appear in the surfaces list as an extension surface
|
|
var d = await T.apiGet('/admin/surfaces');
|
|
var surfaces = d.data || [];
|
|
var editorSurface = surfaces.find(function (s) { return s.id === 'editor'; });
|
|
T.assert(editorSurface, 'editor should be in surfaces list');
|
|
T.assert(editorSurface.source === 'extension', 'editor source should be "extension"');
|
|
T.assert(editorSurface.enabled === true, 'editor should be enabled');
|
|
});
|
|
};
|
|
})();
|