[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
114
application/state/usePluginTerminalProviders.test.ts
Normal file
114
application/state/usePluginTerminalProviders.test.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import fs from 'node:fs';
|
||||
|
||||
import type { TerminalTheme } from '../../domain/models.ts';
|
||||
import {
|
||||
applyCurrentProviderResponse,
|
||||
isPluginTerminalProviderRefreshCurrent,
|
||||
mergePluginTerminalThemeColors,
|
||||
resolvePluginTerminalTheme,
|
||||
waitForProviderResponse,
|
||||
} from './usePluginTerminalProviders.ts';
|
||||
|
||||
const baseTheme = {
|
||||
id: 'base',
|
||||
name: 'Base',
|
||||
type: 'dark',
|
||||
colors: {
|
||||
background: '#000000', foreground: '#ffffff', cursor: '#ffffff', selection: '#333333',
|
||||
black: '#000000', red: '#ff0000', green: '#00ff00', yellow: '#ffff00', blue: '#0000ff',
|
||||
magenta: '#ff00ff', cyan: '#00ffff', white: '#ffffff', brightBlack: '#777777',
|
||||
brightRed: '#ff7777', brightGreen: '#77ff77', brightYellow: '#ffff77', brightBlue: '#7777ff',
|
||||
brightMagenta: '#ff77ff', brightCyan: '#77ffff', brightWhite: '#ffffff',
|
||||
},
|
||||
} as const satisfies TerminalTheme;
|
||||
|
||||
test('terminal theme Providers merge deterministically over the host theme', () => {
|
||||
const merged = mergePluginTerminalThemeColors([
|
||||
{ background: '#102030', cursor: '#abcdef' },
|
||||
{ background: '#ffffff', foreground: '#f0f0f0' },
|
||||
]);
|
||||
assert.deepEqual(merged, {
|
||||
background: '#102030',
|
||||
cursor: '#abcdef',
|
||||
foreground: '#f0f0f0',
|
||||
});
|
||||
assert.deepEqual(resolvePluginTerminalTheme(baseTheme, merged).colors, {
|
||||
...baseTheme.colors,
|
||||
...merged,
|
||||
});
|
||||
assert.equal(resolvePluginTerminalTheme(baseTheme, {}).id, baseTheme.id);
|
||||
});
|
||||
|
||||
test('terminal components delegate Provider state to the application hook', () => {
|
||||
const terminal = fs.readFileSync(new URL('../../components/Terminal.tsx', import.meta.url), 'utf8');
|
||||
const effects = fs.readFileSync(new URL('../../components/terminal/useTerminalEffects.ts', import.meta.url), 'utf8');
|
||||
assert.match(terminal, /usePluginTerminalProviders\(/);
|
||||
assert.doesNotMatch(terminal, /getWindowPluginTerminalProviderRegistry|PluginTerminalProviderAvailability/);
|
||||
assert.doesNotMatch(effects, /getWindowPluginTerminalProviderRegistry|PluginTerminalProviderAvailability/);
|
||||
});
|
||||
|
||||
test('application-owned Provider timeout aborts and returns a stale response', async () => {
|
||||
const controller = new AbortController();
|
||||
const result = await waitForProviderResponse(new Promise(() => {}), controller, 1);
|
||||
assert.equal(controller.signal.aborted, true);
|
||||
assert.deepEqual(result, { requestId: '', stale: true, results: [] });
|
||||
});
|
||||
|
||||
test('a deferred Provider response cannot update state after the live session disconnects', async () => {
|
||||
let resolveResponse!: (value: { requestId: string; stale: boolean; results: [] }) => void;
|
||||
const response = new Promise<{ requestId: string; stale: boolean; results: [] }>((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
});
|
||||
const initial = {
|
||||
sessionId: 'session-a',
|
||||
hostId: 'host-a',
|
||||
workspaceId: 'workspace-a',
|
||||
protocol: 'ssh',
|
||||
status: 'connected',
|
||||
shellType: 'posix',
|
||||
baseTheme,
|
||||
} as const;
|
||||
let current = { ...initial } as Parameters<typeof isPluginTerminalProviderRefreshCurrent>[1];
|
||||
let applied = false;
|
||||
const pending = applyCurrentProviderResponse(
|
||||
response,
|
||||
() => isPluginTerminalProviderRefreshCurrent(initial, current),
|
||||
() => { applied = true; },
|
||||
() => { applied = true; },
|
||||
);
|
||||
current = { ...current, status: 'disconnected' };
|
||||
resolveResponse({ requestId: 'late', stale: false, results: [] });
|
||||
await pending;
|
||||
assert.equal(applied, false);
|
||||
});
|
||||
|
||||
test('session identity and shell discovery invalidate Provider output metadata', () => {
|
||||
const initial = {
|
||||
sessionId: 'session-a',
|
||||
hostId: 'host-a',
|
||||
workspaceId: 'workspace-a',
|
||||
protocol: 'ssh',
|
||||
status: 'connected',
|
||||
shellType: undefined,
|
||||
baseTheme,
|
||||
} as const;
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, { ...initial, shellType: 'posix' }), false);
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, { ...initial, sessionId: 'session-b' }), false);
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, { ...initial, hostId: 'host-b' }), false);
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, { ...initial, workspaceId: 'workspace-b' }), false);
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, { ...initial, protocol: 'telnet' }), false);
|
||||
assert.equal(isPluginTerminalProviderRefreshCurrent(initial, initial), true);
|
||||
});
|
||||
|
||||
test('a current stale Provider response clears the previous output', async () => {
|
||||
let cleared = false;
|
||||
await applyCurrentProviderResponse(
|
||||
Promise.resolve({ requestId: 'timeout', stale: true, results: [] }),
|
||||
() => true,
|
||||
() => assert.fail('stale response must not be applied'),
|
||||
() => { cleared = true; },
|
||||
);
|
||||
assert.equal(cleared, true);
|
||||
});
|
||||
Reference in New Issue
Block a user