Path: blob/main/src/vs/workbench/api/test/browser/mainThreadAuthentication.integrationTest.ts
5220 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 assert from 'assert';6import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';7import { TestDialogService } from '../../../../platform/dialogs/test/common/testDialogService.js';8import { TestInstantiationService } from '../../../../platform/instantiation/test/common/instantiationServiceMock.js';9import { INotificationService } from '../../../../platform/notification/common/notification.js';10import { TestNotificationService } from '../../../../platform/notification/test/common/testNotificationService.js';11import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.js';12import { IStorageService } from '../../../../platform/storage/common/storage.js';13import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';14import { NullTelemetryService } from '../../../../platform/telemetry/common/telemetryUtils.js';15import { MainThreadAuthentication } from '../../browser/mainThreadAuthentication.js';16import { ExtHostContext, MainContext } from '../../common/extHost.protocol.js';17import { IActivityService } from '../../../services/activity/common/activity.js';18import { AuthenticationService } from '../../../services/authentication/browser/authenticationService.js';19import { IAuthenticationExtensionsService, IAuthenticationService } from '../../../services/authentication/common/authentication.js';20import { IExtensionService } from '../../../services/extensions/common/extensions.js';21import { IRemoteAgentService } from '../../../services/remote/common/remoteAgentService.js';22import { TestRPCProtocol } from '../common/testRPCProtocol.js';23import { TestEnvironmentService, TestHostService, TestQuickInputService, TestRemoteAgentService } from '../../../test/browser/workbenchTestServices.js';24import { TestActivityService, TestExtensionService, TestProductService, TestStorageService } from '../../../test/common/workbenchTestServices.js';25import { IBrowserWorkbenchEnvironmentService } from '../../../services/environment/browser/environmentService.js';26import { IProductService } from '../../../../platform/product/common/productService.js';27import { AuthenticationAccessService, IAuthenticationAccessService } from '../../../services/authentication/browser/authenticationAccessService.js';28import { IAccountUsage, IAuthenticationUsageService } from '../../../services/authentication/browser/authenticationUsageService.js';29import { AuthenticationExtensionsService } from '../../../services/authentication/browser/authenticationExtensionsService.js';30import { ILogService, NullLogService } from '../../../../platform/log/common/log.js';31import { IHostService } from '../../../services/host/browser/host.js';32import { IOpenerService } from '../../../../platform/opener/common/opener.js';33import { IUserActivityService, UserActivityService } from '../../../services/userActivity/common/userActivityService.js';34import { ISecretStorageService } from '../../../../platform/secrets/common/secrets.js';35import { TestSecretStorageService } from '../../../../platform/secrets/test/common/testSecretStorageService.js';36import { IDynamicAuthenticationProviderStorageService } from '../../../services/authentication/common/dynamicAuthenticationProviderStorage.js';37import { DynamicAuthenticationProviderStorageService } from '../../../services/authentication/browser/dynamicAuthenticationProviderStorageService.js';38import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';39import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js';40import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';4142class TestAuthUsageService implements IAuthenticationUsageService {43_serviceBrand: undefined;44initializeExtensionUsageCache(): Promise<void> { return Promise.resolve(); }45extensionUsesAuth(extensionId: string): Promise<boolean> { return Promise.resolve(false); }46readAccountUsages(providerId: string, accountName: string): IAccountUsage[] { return []; }47removeAccountUsage(providerId: string, accountName: string): void { }48addAccountUsage(providerId: string, accountName: string, scopes: ReadonlyArray<string>, extensionId: string, extensionName: string): void { }49}5051suite('MainThreadAuthentication', () => {52const disposables = ensureNoDisposablesAreLeakedInTestSuite();5354let mainThreadAuthentication: MainThreadAuthentication;55let instantiationService: TestInstantiationService;56let rpcProtocol: TestRPCProtocol;5758setup(async () => {59// services60const services = new ServiceCollection();61services.set(ILogService, new SyncDescriptor(NullLogService));62services.set(IDialogService, new SyncDescriptor(TestDialogService, [{ confirmed: true }]));63services.set(IStorageService, new SyncDescriptor(TestStorageService));64services.set(ISecretStorageService, new SyncDescriptor(TestSecretStorageService));65services.set(IDynamicAuthenticationProviderStorageService, new SyncDescriptor(DynamicAuthenticationProviderStorageService));66services.set(IQuickInputService, new SyncDescriptor(TestQuickInputService));67services.set(IExtensionService, new SyncDescriptor(TestExtensionService));68services.set(IActivityService, new SyncDescriptor(TestActivityService));69services.set(IRemoteAgentService, new SyncDescriptor(TestRemoteAgentService));70services.set(INotificationService, new SyncDescriptor(TestNotificationService));71services.set(IHostService, new SyncDescriptor(TestHostService));72services.set(IUserActivityService, new SyncDescriptor(UserActivityService));73services.set(IAuthenticationAccessService, new SyncDescriptor(AuthenticationAccessService));74services.set(IAuthenticationService, new SyncDescriptor(AuthenticationService));75services.set(IAuthenticationUsageService, new SyncDescriptor(TestAuthUsageService));76services.set(IAuthenticationExtensionsService, new SyncDescriptor(AuthenticationExtensionsService));77instantiationService = disposables.add(new TestInstantiationService(services, undefined, undefined, true));7879// stubs80// eslint-disable-next-line local/code-no-dangerous-type-assertions81instantiationService.stub(IOpenerService, {} as Partial<IOpenerService>);82instantiationService.stub(ITelemetryService, NullTelemetryService);83instantiationService.stub(IBrowserWorkbenchEnvironmentService, TestEnvironmentService);84instantiationService.stub(IProductService, TestProductService);8586rpcProtocol = disposables.add(new TestRPCProtocol());87mainThreadAuthentication = disposables.add(instantiationService.createInstance(MainThreadAuthentication, rpcProtocol));88rpcProtocol.set(MainContext.MainThreadAuthentication, mainThreadAuthentication);89});9091test('provider registration completes without errors', async () => {92// Test basic registration - this should complete without throwing93await mainThreadAuthentication.$registerAuthenticationProvider({94id: 'test-provider',95label: 'Test Provider',96supportsMultipleAccounts: false97});9899// Test unregistration - this should also complete without throwing100await mainThreadAuthentication.$unregisterAuthenticationProvider('test-provider');101102// Success if we reach here without timeout103assert.ok(true, 'Registration and unregistration completed successfully');104});105106test('event suppression during explicit unregistration', async () => {107let unregisterEventFired = false;108let eventProviderId: string | undefined;109110// Mock the ext host to capture unregister events111const mockExtHost = {112$onDidUnregisterAuthenticationProvider: (id: string) => {113unregisterEventFired = true;114eventProviderId = id;115return Promise.resolve();116},117$getSessions: () => Promise.resolve([]),118// eslint-disable-next-line local/code-no-any-casts119$createSession: () => Promise.resolve({} as any),120$removeSession: () => Promise.resolve(),121$onDidChangeAuthenticationSessions: () => Promise.resolve(),122$registerDynamicAuthProvider: () => Promise.resolve('test'),123$onDidChangeDynamicAuthProviderTokens: () => Promise.resolve(),124$getSessionsFromChallenges: () => Promise.resolve([]),125// eslint-disable-next-line local/code-no-any-casts126$createSessionFromChallenges: () => Promise.resolve({} as any),127};128rpcProtocol.set(ExtHostContext.ExtHostAuthentication, mockExtHost);129130// Register a provider131await mainThreadAuthentication.$registerAuthenticationProvider({132id: 'test-suppress',133label: 'Test Suppress',134supportsMultipleAccounts: false135});136137// Reset the flag138unregisterEventFired = false;139eventProviderId = undefined;140141// Unregister the provider - this should NOT fire the event due to suppression142await mainThreadAuthentication.$unregisterAuthenticationProvider('test-suppress');143144// Verify the event was suppressed145assert.strictEqual(unregisterEventFired, false, 'Unregister event should be suppressed during explicit unregistration');146assert.strictEqual(eventProviderId, undefined, 'No provider ID should be captured from suppressed event');147});148149test('concurrent provider registrations complete without errors', async () => {150// Register multiple providers simultaneously151const registrationPromises = [152mainThreadAuthentication.$registerAuthenticationProvider({153id: 'concurrent-1',154label: 'Concurrent 1',155supportsMultipleAccounts: false156}),157mainThreadAuthentication.$registerAuthenticationProvider({158id: 'concurrent-2',159label: 'Concurrent 2',160supportsMultipleAccounts: false161}),162mainThreadAuthentication.$registerAuthenticationProvider({163id: 'concurrent-3',164label: 'Concurrent 3',165supportsMultipleAccounts: false166})167];168169await Promise.all(registrationPromises);170171// Unregister all providers172const unregistrationPromises = [173mainThreadAuthentication.$unregisterAuthenticationProvider('concurrent-1'),174mainThreadAuthentication.$unregisterAuthenticationProvider('concurrent-2'),175mainThreadAuthentication.$unregisterAuthenticationProvider('concurrent-3')176];177178await Promise.all(unregistrationPromises);179180// Success if we reach here without timeout181assert.ok(true, 'Concurrent registrations and unregistrations completed successfully');182});183});184185186