Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/copilotCliAuth.spec.ts
13406 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { SessionOptions } from '@github/copilot/sdk';
7
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
8
import { IAuthenticationService } from '../../../../../platform/authentication/common/authentication';
9
import { ConfigKey, IConfigurationService } from '../../../../../platform/configuration/common/configurationService';
10
import { IEnvService } from '../../../../../platform/env/common/envService';
11
import { IVSCodeExtensionContext } from '../../../../../platform/extContext/common/extensionContext';
12
import { ILogService } from '../../../../../platform/log/common/logService';
13
import { DisposableStore } from '../../../../../util/vs/base/common/lifecycle';
14
import { IInstantiationService } from '../../../../../util/vs/platform/instantiation/common/instantiation';
15
import { createExtensionUnitTestingServices } from '../../../../test/node/services';
16
import { CopilotCLISDK } from '../copilotCli';
17
18
type TokenAuthInfo = Extract<NonNullable<SessionOptions['authInfo']>, { type: 'token' }>;
19
type HmacAuthInfo = Extract<NonNullable<SessionOptions['authInfo']>, { type: 'hmac' }>;
20
21
describe('CopilotCLISDK Authentication', () => {
22
const disposables = new DisposableStore();
23
let instantiationService: IInstantiationService;
24
let logService: ILogService;
25
26
class TestCopilotCLISDK extends CopilotCLISDK {
27
protected override async ensureShims(): Promise<void> {
28
return;
29
}
30
}
31
32
// Helper to create a mock extension context
33
function createMockExtensionContext(): IVSCodeExtensionContext {
34
return {
35
workspaceState: {
36
get: () => ({}),
37
update: async () => { },
38
keys: () => []
39
}
40
} as unknown as IVSCodeExtensionContext;
41
}
42
43
// Helper to create a mock env service
44
function createMockEnvService(): IEnvService {
45
return {} as unknown as IEnvService;
46
}
47
48
beforeEach(() => {
49
const services = disposables.add(createExtensionUnitTestingServices());
50
const accessor = services.createTestingAccessor();
51
instantiationService = services.seal();
52
logService = accessor.get(ILogService);
53
});
54
55
afterEach(() => {
56
disposables.clear();
57
});
58
59
it('should skip token validation when proxy URL is configured', async () => {
60
// Mock configuration to return a proxy URL
61
const mockConfigService = {
62
getConfig(key: unknown) {
63
if (key === ConfigKey.Shared.DebugOverrideProxyUrl) {
64
return 'https://proxy.example.com';
65
}
66
return undefined;
67
}
68
} as unknown as IConfigurationService;
69
70
const mockAuthService = {
71
async getGitHubSession(): Promise<undefined> {
72
// This should not be called when proxy is configured
73
throw new Error('getGitHubSession should not be called when proxy is configured');
74
}
75
} as unknown as IAuthenticationService;
76
77
const sdk = new TestCopilotCLISDK(
78
createMockExtensionContext(),
79
createMockEnvService(),
80
logService,
81
instantiationService,
82
mockAuthService,
83
mockConfigService
84
);
85
86
const authInfo = await sdk.getAuthInfo() as HmacAuthInfo;
87
88
expect(authInfo.type).toBe('hmac');
89
expect(authInfo.hmac).toBe('empty');
90
expect(authInfo.host).toBe('https://github.com');
91
expect(authInfo.copilotUser?.endpoints?.api).toBe('https://proxy.example.com');
92
});
93
94
it('should call getGitHubSession when no proxy URL is configured', async () => {
95
let getGitHubSessionCalled = false;
96
97
// Mock configuration to return no proxy URLs
98
const mockConfigService = {
99
getConfig() {
100
return undefined;
101
}
102
} as unknown as IConfigurationService;
103
104
const mockAuthService = {
105
async getGitHubSession() {
106
getGitHubSessionCalled = true;
107
return {
108
accessToken: 'test-token',
109
id: 'test-id',
110
scopes: [] as readonly string[],
111
account: { id: 'test-account', label: 'Test User' }
112
};
113
}
114
} as unknown as IAuthenticationService;
115
116
const sdk = new TestCopilotCLISDK(
117
createMockExtensionContext(),
118
createMockEnvService(),
119
logService,
120
instantiationService,
121
mockAuthService,
122
mockConfigService
123
);
124
125
const authInfo = await sdk.getAuthInfo() as TokenAuthInfo;
126
127
expect(getGitHubSessionCalled).toBe(true);
128
expect(authInfo.type).toBe('token');
129
expect(authInfo.token).toBe('test-token');
130
expect(authInfo.host).toBe('https://github.com');
131
});
132
133
it('should return empty token when getGitHubSession returns undefined and no proxy is configured', async () => {
134
// Mock configuration to return no proxy URLs
135
const mockConfigService = {
136
getConfig() {
137
return undefined;
138
}
139
} as unknown as IConfigurationService;
140
141
const mockAuthService = {
142
async getGitHubSession() {
143
return undefined;
144
}
145
} as unknown as IAuthenticationService;
146
147
const sdk = new TestCopilotCLISDK(
148
createMockExtensionContext(),
149
createMockEnvService(),
150
logService,
151
instantiationService,
152
mockAuthService,
153
mockConfigService
154
);
155
156
const authInfo = await sdk.getAuthInfo() as TokenAuthInfo;
157
158
expect(authInfo.type).toBe('token');
159
expect(authInfo.token).toBe('');
160
expect(authInfo.host).toBe('https://github.com');
161
});
162
});
163
164