Path: blob/main/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/copilotCliAuth.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 type { SessionOptions } from '@github/copilot/sdk';6import { afterEach, beforeEach, describe, expect, it } from 'vitest';7import { IAuthenticationService } from '../../../../../platform/authentication/common/authentication';8import { ConfigKey, IConfigurationService } from '../../../../../platform/configuration/common/configurationService';9import { IEnvService } from '../../../../../platform/env/common/envService';10import { IVSCodeExtensionContext } from '../../../../../platform/extContext/common/extensionContext';11import { ILogService } from '../../../../../platform/log/common/logService';12import { DisposableStore } from '../../../../../util/vs/base/common/lifecycle';13import { IInstantiationService } from '../../../../../util/vs/platform/instantiation/common/instantiation';14import { createExtensionUnitTestingServices } from '../../../../test/node/services';15import { CopilotCLISDK } from '../copilotCli';1617type TokenAuthInfo = Extract<NonNullable<SessionOptions['authInfo']>, { type: 'token' }>;18type HmacAuthInfo = Extract<NonNullable<SessionOptions['authInfo']>, { type: 'hmac' }>;1920describe('CopilotCLISDK Authentication', () => {21const disposables = new DisposableStore();22let instantiationService: IInstantiationService;23let logService: ILogService;2425class TestCopilotCLISDK extends CopilotCLISDK {26protected override async ensureShims(): Promise<void> {27return;28}29}3031// Helper to create a mock extension context32function createMockExtensionContext(): IVSCodeExtensionContext {33return {34workspaceState: {35get: () => ({}),36update: async () => { },37keys: () => []38}39} as unknown as IVSCodeExtensionContext;40}4142// Helper to create a mock env service43function createMockEnvService(): IEnvService {44return {} as unknown as IEnvService;45}4647beforeEach(() => {48const services = disposables.add(createExtensionUnitTestingServices());49const accessor = services.createTestingAccessor();50instantiationService = services.seal();51logService = accessor.get(ILogService);52});5354afterEach(() => {55disposables.clear();56});5758it('should skip token validation when proxy URL is configured', async () => {59// Mock configuration to return a proxy URL60const mockConfigService = {61getConfig(key: unknown) {62if (key === ConfigKey.Shared.DebugOverrideProxyUrl) {63return 'https://proxy.example.com';64}65return undefined;66}67} as unknown as IConfigurationService;6869const mockAuthService = {70async getGitHubSession(): Promise<undefined> {71// This should not be called when proxy is configured72throw new Error('getGitHubSession should not be called when proxy is configured');73}74} as unknown as IAuthenticationService;7576const sdk = new TestCopilotCLISDK(77createMockExtensionContext(),78createMockEnvService(),79logService,80instantiationService,81mockAuthService,82mockConfigService83);8485const authInfo = await sdk.getAuthInfo() as HmacAuthInfo;8687expect(authInfo.type).toBe('hmac');88expect(authInfo.hmac).toBe('empty');89expect(authInfo.host).toBe('https://github.com');90expect(authInfo.copilotUser?.endpoints?.api).toBe('https://proxy.example.com');91});9293it('should call getGitHubSession when no proxy URL is configured', async () => {94let getGitHubSessionCalled = false;9596// Mock configuration to return no proxy URLs97const mockConfigService = {98getConfig() {99return undefined;100}101} as unknown as IConfigurationService;102103const mockAuthService = {104async getGitHubSession() {105getGitHubSessionCalled = true;106return {107accessToken: 'test-token',108id: 'test-id',109scopes: [] as readonly string[],110account: { id: 'test-account', label: 'Test User' }111};112}113} as unknown as IAuthenticationService;114115const sdk = new TestCopilotCLISDK(116createMockExtensionContext(),117createMockEnvService(),118logService,119instantiationService,120mockAuthService,121mockConfigService122);123124const authInfo = await sdk.getAuthInfo() as TokenAuthInfo;125126expect(getGitHubSessionCalled).toBe(true);127expect(authInfo.type).toBe('token');128expect(authInfo.token).toBe('test-token');129expect(authInfo.host).toBe('https://github.com');130});131132it('should return empty token when getGitHubSession returns undefined and no proxy is configured', async () => {133// Mock configuration to return no proxy URLs134const mockConfigService = {135getConfig() {136return undefined;137}138} as unknown as IConfigurationService;139140const mockAuthService = {141async getGitHubSession() {142return undefined;143}144} as unknown as IAuthenticationService;145146const sdk = new TestCopilotCLISDK(147createMockExtensionContext(),148createMockEnvService(),149logService,150instantiationService,151mockAuthService,152mockConfigService153);154155const authInfo = await sdk.getAuthInfo() as TokenAuthInfo;156157expect(authInfo.type).toBe('token');158expect(authInfo.token).toBe('');159expect(authInfo.host).toBe('https://github.com');160});161});162163164