Path: blob/main/extensions/copilot/src/extension/chatSessions/copilotcli/vscode-node/test/context.spec.ts
13406 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { beforeEach, describe, expect, it, vi } from 'vitest';67vi.mock('vscode', () => ({8commands: {9executeCommand: vi.fn().mockResolvedValue(undefined),10},11}));1213import * as vscode from 'vscode';14import { registerCommandContext } from '../commands/context';1516type Listener = (...args: unknown[]) => void;1718/**19* A mock InProcHttpServer with controllable events and session ids.20*/21class MockHttpServerWithEvents {22private _connectListeners: Listener[] = [];23private _disconnectListeners: Listener[] = [];24private _connectedSessionIds: readonly string[] = [];2526readonly onDidClientConnect = vi.fn((listener: Listener) => {27this._connectListeners.push(listener);28return { dispose: () => { this._connectListeners = this._connectListeners.filter(l => l !== listener); } };29});3031readonly onDidClientDisconnect = vi.fn((listener: Listener) => {32this._disconnectListeners.push(listener);33return { dispose: () => { this._disconnectListeners = this._disconnectListeners.filter(l => l !== listener); } };34});3536readonly getConnectedSessionIds = vi.fn((): readonly string[] => this._connectedSessionIds);3738setConnectedSessionIds(ids: readonly string[]): void {39this._connectedSessionIds = ids;40}4142fireConnect(): void {43for (const listener of this._connectListeners) {44listener();45}46}4748fireDisconnect(): void {49for (const listener of this._disconnectListeners) {50listener();51}52}53}5455describe('registerCommandContext', () => {56let mockServer: MockHttpServerWithEvents;5758beforeEach(() => {59vi.mocked(vscode.commands.executeCommand).mockClear();60mockServer = new MockHttpServerWithEvents();61});6263it('should set context to false when no sessions are connected initially', () => {64mockServer.setConnectedSessionIds([]);65registerCommandContext(mockServer as any);6667expect(vscode.commands.executeCommand).toHaveBeenCalledWith(68'setContext',69'github.copilot.chat.copilotCLI.hasSession',70false,71);72});7374it('should set context to true when sessions are connected initially', () => {75mockServer.setConnectedSessionIds(['session-1']);76registerCommandContext(mockServer as any);7778expect(vscode.commands.executeCommand).toHaveBeenCalledWith(79'setContext',80'github.copilot.chat.copilotCLI.hasSession',81true,82);83});8485it('should update context to true when a client connects', () => {86mockServer.setConnectedSessionIds([]);87registerCommandContext(mockServer as any);88vi.mocked(vscode.commands.executeCommand).mockClear();8990mockServer.setConnectedSessionIds(['session-1']);91mockServer.fireConnect();9293expect(vscode.commands.executeCommand).toHaveBeenCalledWith(94'setContext',95'github.copilot.chat.copilotCLI.hasSession',96true,97);98});99100it('should update context to false when all clients disconnect', () => {101mockServer.setConnectedSessionIds(['session-1']);102registerCommandContext(mockServer as any);103vi.mocked(vscode.commands.executeCommand).mockClear();104105mockServer.setConnectedSessionIds([]);106mockServer.fireDisconnect();107108expect(vscode.commands.executeCommand).toHaveBeenCalledWith(109'setContext',110'github.copilot.chat.copilotCLI.hasSession',111false,112);113});114115it('should remain true when one of multiple clients disconnects', () => {116mockServer.setConnectedSessionIds(['session-1', 'session-2']);117registerCommandContext(mockServer as any);118vi.mocked(vscode.commands.executeCommand).mockClear();119120mockServer.setConnectedSessionIds(['session-2']);121mockServer.fireDisconnect();122123expect(vscode.commands.executeCommand).toHaveBeenCalledWith(124'setContext',125'github.copilot.chat.copilotCLI.hasSession',126true,127);128});129130it('should register listeners for both connect and disconnect events', () => {131mockServer.setConnectedSessionIds([]);132registerCommandContext(mockServer as any);133134expect(mockServer.onDidClientConnect).toHaveBeenCalledOnce();135expect(mockServer.onDidClientDisconnect).toHaveBeenCalledOnce();136});137138it('should return a disposable that cleans up event listeners', () => {139mockServer.setConnectedSessionIds([]);140const disposables = registerCommandContext(mockServer as any);141vi.mocked(vscode.commands.executeCommand).mockClear();142143disposables.dispose();144145// After disposing, firing events should not trigger context updates146mockServer.setConnectedSessionIds(['session-1']);147mockServer.fireConnect();148mockServer.fireDisconnect();149150expect(vscode.commands.executeCommand).not.toHaveBeenCalled();151});152153it('should handle multiple connect and disconnect events', () => {154mockServer.setConnectedSessionIds([]);155registerCommandContext(mockServer as any);156vi.mocked(vscode.commands.executeCommand).mockClear();157158// First client connects159mockServer.setConnectedSessionIds(['session-1']);160mockServer.fireConnect();161expect(vscode.commands.executeCommand).toHaveBeenLastCalledWith(162'setContext',163'github.copilot.chat.copilotCLI.hasSession',164true,165);166167// Second client connects168mockServer.setConnectedSessionIds(['session-1', 'session-2']);169mockServer.fireConnect();170expect(vscode.commands.executeCommand).toHaveBeenLastCalledWith(171'setContext',172'github.copilot.chat.copilotCLI.hasSession',173true,174);175176// First client disconnects177mockServer.setConnectedSessionIds(['session-2']);178mockServer.fireDisconnect();179expect(vscode.commands.executeCommand).toHaveBeenLastCalledWith(180'setContext',181'github.copilot.chat.copilotCLI.hasSession',182true,183);184185// Last client disconnects186mockServer.setConnectedSessionIds([]);187mockServer.fireDisconnect();188expect(vscode.commands.executeCommand).toHaveBeenLastCalledWith(189'setContext',190'github.copilot.chat.copilotCLI.hasSession',191false,192);193});194});195196197