Skip to content
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion packages/core/src/services/web-terminal-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,20 @@ describe('WebTerminalRegistry', () => {
},
onData: vi.fn((listener) => {
onData = listener;
return { dispose: disposeData };
// Capture this session's spy by value: the describe-scope `disposeData`
// variable is reassigned every test, and a deferred exit-time release
// from a previous session may fire during a later test — it must hit
// its own spy, not the current one. Same reason the detach guard
// checks listener identity before clearing the shared `onData`.
const disposeDataSpy = disposeData;
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
return {
// Model node-pty's disposable detaching the listener, so a test can
// tell a synchronous dispose apart from the deferred one.
dispose: () => {
if (onData === listener) onData = () => {};
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
disposeDataSpy();
},
};
}),
onExit: vi.fn((listener) => {
onExit = listener;
Expand Down Expand Up @@ -483,6 +496,29 @@ describe('WebTerminalRegistry', () => {
expect(spawnSync).not.toHaveBeenCalled();
});

it('lets output queued behind onExit reach the scrollback before the release', async () => {
osPlatform.mockReturnValue('win32');
const registry = new WebTerminalRegistry();
await registry.create({
terminalId: 'terminal:exit-trailing',
workspaceCwd: '/workspace',
});

// The release is deferred one tick after onExit so a trailing onData
// queued in the same turn still lands in the scrollback first. The fake
// detaches the listener on dispose, so with a synchronous release the
// tail is lost — this test fails if the defer is removed.
onExit({ exitCode: 0 });
onData('trailing');
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
await new Promise<void>((resolve) => setImmediate(resolve));

expect(disposeData).toHaveBeenCalledOnce();
expect(registry.readSnapshot('terminal:exit-trailing')).toMatchObject({
output: 'trailing',
exited: true,
});
});

it('forwards live output and bounds unacknowledged PTY input', async () => {
const registry = new WebTerminalRegistry();
await registry.create({
Expand Down
Loading