feat(vscode): redesign control center (#236)

* feat(vscode): redesign control center

* fix(vscode): keep launch target messaging honest
This commit is contained in:
Vasanth T
2026-04-03 19:28:25 +05:30
committed by GitHub
parent fb32e3f829
commit 6987a54a71
8 changed files with 2408 additions and 232 deletions

View File

@@ -0,0 +1,249 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const Module = require('node:module');
function createStatus(overrides = {}) {
return {
installed: true,
executable: 'openclaude',
launchCommand: 'openclaude --project-aware',
terminalName: 'OpenClaude',
shimEnabled: false,
workspaceFolder: '/workspace/openclaude/very/long/path/example-project',
workspaceSourceLabel: 'active editor workspace',
launchCwd: '/workspace/openclaude/very/long/path/example-project',
launchCwdLabel: '/workspace/openclaude/very/long/path/example-project',
canLaunchInWorkspaceRoot: true,
profileStatusLabel: 'Found',
profileStatusHint: '/workspace/openclaude/very/long/path/example-project/.openclaude-profile.json',
workspaceProfilePath: '/workspace/openclaude/very/long/path/example-project/.openclaude-profile.json',
providerState: {
label: 'Codex',
detail: 'gpt-5.4',
source: 'profile',
},
providerSourceLabel: 'saved profile',
...overrides,
};
}
function loadExtension() {
const extensionPath = require.resolve('./extension');
delete require.cache[extensionPath];
const originalLoad = Module._load;
Module._load = function patchedLoad(request, parent, isMain) {
if (request === 'vscode') {
return {
workspace: {},
window: {},
env: {},
commands: {},
Uri: { parse: value => value, file: value => value },
};
}
return originalLoad.call(this, request, parent, isMain);
};
try {
return require('./extension');
} finally {
Module._load = originalLoad;
}
}
test('renderControlCenterHtml uses the OpenClaude wordmark, status rail, and warm action hierarchy', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(createStatus(), { nonce: 'test-nonce', platform: 'win32' });
assert.match(html, /Open<span class="wordmark-accent">Claude<\/span>/);
assert.match(html, /class="status-rail"/);
assert.match(html, /\.sunset-gradient\s*\{/);
assert.match(html, /class="action-button primary" id="launch"/);
assert.match(html, /class="action-button secondary" id="launchRoot"/);
assert.match(
html,
/title="\/workspace\/openclaude\/very\/long\/path\/example-project"[^>]*>\/workspace\/openclaude\/very\/long\/path\/example-project<\//,
);
});
test('renderControlCenterHtml shows explicit disabled and empty states when workspace data is missing', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(
createStatus({
workspaceFolder: null,
workspaceSourceLabel: 'no workspace open',
launchCwd: null,
launchCwdLabel: 'VS Code default terminal cwd',
canLaunchInWorkspaceRoot: false,
profileStatusLabel: 'No workspace',
profileStatusHint: 'Open a workspace folder to detect a saved profile',
workspaceProfilePath: null,
}),
{ nonce: 'test-nonce', platform: 'linux' },
);
assert.match(
html,
/class="action-button secondary" id="launchRoot"[^>]*disabled[^>]*>[\s\S]*Open a workspace folder to enable workspace-root launch/,
);
assert.match(html, /No workspace profile yet/);
assert.match(html, /Open a workspace folder to detect a saved profile/);
assert.doesNotMatch(html, /id="openProfile"/);
});
test('OpenClaudeControlCenterProvider.getHtml supplies a nonce to the redesigned renderer', () => {
const { OpenClaudeControlCenterProvider } = loadExtension();
const provider = new OpenClaudeControlCenterProvider();
assert.doesNotThrow(() => provider.getHtml(createStatus()));
const html = provider.getHtml(createStatus());
assert.match(html, /script-src 'nonce-[^']+'/);
assert.match(html, /<script nonce="[^"]+">/);
assert.doesNotMatch(html, /nonce-undefined/);
assert.doesNotMatch(html, /<script nonce="undefined">/);
});
test('resolveLaunchTargets distinguishes project-aware launch from workspace-root launch', () => {
const { resolveLaunchTargets } = loadExtension();
assert.deepEqual(
resolveLaunchTargets({
activeFilePath: '/workspace/openclaude/src/panels/control-center.js',
workspacePath: '/workspace/openclaude',
workspaceSourceLabel: 'active editor workspace',
}),
{
projectAwareCwd: '/workspace/openclaude/src/panels',
projectAwareCwdLabel: '/workspace/openclaude/src/panels',
projectAwareSourceLabel: 'active file directory',
workspaceRootCwd: '/workspace/openclaude',
workspaceRootCwdLabel: '/workspace/openclaude',
launchActionsShareTarget: false,
launchActionsShareTargetReason: null,
},
);
});
test('resolveLaunchTargets anchors relative launch commands to the workspace root', () => {
const { resolveLaunchTargets } = loadExtension();
assert.deepEqual(
resolveLaunchTargets({
executable: './node_modules/.bin/openclaude',
activeFilePath: '/workspace/openclaude/src/panels/control-center.js',
workspacePath: '/workspace/openclaude',
workspaceSourceLabel: 'active editor workspace',
}),
{
projectAwareCwd: '/workspace/openclaude',
projectAwareCwdLabel: '/workspace/openclaude',
projectAwareSourceLabel: 'workspace root (required by relative launch command)',
workspaceRootCwd: '/workspace/openclaude',
workspaceRootCwdLabel: '/workspace/openclaude',
launchActionsShareTarget: true,
launchActionsShareTargetReason: 'relative-launch-command',
},
);
});
test('resolveLaunchTargets ignores active files outside the selected workspace', () => {
const { resolveLaunchTargets } = loadExtension();
assert.deepEqual(
resolveLaunchTargets({
executable: 'openclaude',
activeFilePath: '/tmp/notes/scratch.js',
workspacePath: '/workspace/openclaude',
workspaceSourceLabel: 'first workspace folder',
}),
{
projectAwareCwd: '/workspace/openclaude',
projectAwareCwdLabel: '/workspace/openclaude',
projectAwareSourceLabel: 'first workspace folder',
workspaceRootCwd: '/workspace/openclaude',
workspaceRootCwdLabel: '/workspace/openclaude',
launchActionsShareTarget: true,
launchActionsShareTargetReason: null,
},
);
});
test('renderControlCenterHtml restores landmark and heading semantics', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(createStatus(), { nonce: 'test-nonce', platform: 'win32' });
assert.match(html, /<main class="shell" aria-labelledby="control-center-title">/);
assert.match(html, /<header class="hero">/);
assert.match(html, /<h1 class="headline-title" id="control-center-title">/);
assert.match(html, /<section class="modules" aria-label="Control center details">/);
assert.match(html, /<h2 class="module-title" id="section-project">Project<\/h2>/);
assert.match(html, /<section class="actions-layout" aria-label="Control center actions">/);
});
test('renderControlCenterHtml explains distinct launch targets when an active file directory is available', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(
createStatus({
launchCwd: '/workspace/openclaude/src/panels',
launchCwdLabel: '/workspace/openclaude/src/panels',
launchCwdSourceLabel: 'active file directory',
workspaceRootCwd: '/workspace/openclaude',
workspaceRootCwdLabel: '/workspace/openclaude',
}),
{ nonce: 'test-nonce', platform: 'linux' },
);
assert.match(html, /Starts beside the active file · \/workspace\/openclaude\/src\/panels/);
assert.match(html, /Always starts at the workspace root · \/workspace\/openclaude/);
});
test('renderControlCenterHtml makes shared workspace-root launches explicit for relative commands', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(
createStatus({
launchCwd: '/workspace/openclaude',
launchCwdLabel: '/workspace/openclaude',
launchCwdSourceLabel: 'workspace root (required by relative launch command)',
workspaceRootCwd: '/workspace/openclaude',
workspaceRootCwdLabel: '/workspace/openclaude',
launchActionsShareTarget: true,
launchActionsShareTargetReason: 'relative-launch-command',
}),
{ nonce: 'test-nonce', platform: 'linux' },
);
assert.match(html, /Project-aware launch is anchored to the workspace root by the relative command · \/workspace\/openclaude/);
assert.match(html, /Same workspace-root target as Launch OpenClaude because the relative command resolves from the workspace root · \/workspace\/openclaude/);
});
test('renderControlCenterHtml escapes hostile text and title values', () => {
const { renderControlCenterHtml } = loadExtension();
const html = renderControlCenterHtml(
createStatus({
launchCommand: '<img src=x onerror="boom()">',
workspaceFolder: '"/><script>workspace()</script>',
workspaceSourceLabel: 'active <b>workspace</b>',
launchCwdLabel: '"><script>cwd()</script>',
profileStatusHint: '<svg onload="profile()">',
workspaceProfilePath: '"/><script>profile-path()</script>',
providerState: {
label: 'Provider "><img src=x onerror="label()">',
detail: '<script>provider-detail()</script>',
source: 'profile',
},
}),
{ nonce: 'test-nonce', platform: 'linux' },
);
assert.match(html, /&lt;img src=x onerror=&quot;boom\(\)&quot;&gt;/);
assert.match(html, /&quot;\/&gt;&lt;script&gt;workspace\(\)&lt;\/script&gt;/);
assert.match(html, /active &lt;b&gt;workspace&lt;\/b&gt;/);
assert.match(html, /&lt;svg onload=&quot;profile\(\)&quot;&gt;/);
assert.match(html, /Provider &quot;&gt;&lt;img src=x onerror=&quot;label\(\)&quot;&gt;/);
assert.match(html, /&lt;script&gt;provider-detail\(\)&lt;\/script&gt; · saved profile/);
assert.doesNotMatch(html, /<script>workspace\(\)<\/script>/);
assert.doesNotMatch(html, /<img src=x onerror="boom\(\)">/);
});