Path: blob/main/src/vs/workbench/services/commands/test/common/commandService.test.ts
3296 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*--------------------------------------------------------------------------------------------*/4import assert from 'assert';5import { DisposableStore } from '../../../../../base/common/lifecycle.js';6import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';7import { CommandsRegistry } from '../../../../../platform/commands/common/commands.js';8import { InstantiationService } from '../../../../../platform/instantiation/common/instantiationService.js';9import { NullLogService } from '../../../../../platform/log/common/log.js';10import { NullExtensionService } from '../../../extensions/common/extensions.js';11import { CommandService } from '../../common/commandService.js';1213suite('CommandService', function () {1415const store = ensureNoDisposablesAreLeakedInTestSuite();1617setup(function () {18store.add(CommandsRegistry.registerCommand('foo', function () { }));19});2021test('activateOnCommand', () => {2223let lastEvent: string;2425const service = store.add(new CommandService(new InstantiationService(), new class extends NullExtensionService {26override activateByEvent(activationEvent: string): Promise<void> {27lastEvent = activationEvent;28return super.activateByEvent(activationEvent);29}30}, new NullLogService()));3132return service.executeCommand('foo').then(() => {33assert.ok(lastEvent, 'onCommand:foo');34return service.executeCommand('unknownCommandId');35}).then(() => {36assert.ok(false);37}, () => {38assert.ok(lastEvent, 'onCommand:unknownCommandId');39});40});4142test('fwd activation error', async function () {4344const extensionService = new class extends NullExtensionService {45override activateByEvent(activationEvent: string): Promise<void> {46return Promise.reject(new Error('bad_activate'));47}48};4950const service = store.add(new CommandService(new InstantiationService(), extensionService, new NullLogService()));5152await extensionService.whenInstalledExtensionsRegistered();5354return service.executeCommand('foo').then(() => assert.ok(false), err => {55assert.strictEqual(err.message, 'bad_activate');56});57});5859test('!onReady, but executeCommand', function () {6061let callCounter = 0;62const reg = CommandsRegistry.registerCommand('bar', () => callCounter += 1);6364const service = store.add(new CommandService(new InstantiationService(), new class extends NullExtensionService {65override whenInstalledExtensionsRegistered() {66return new Promise<boolean>(_resolve => { /*ignore*/ });67}68}, new NullLogService()));6970service.executeCommand('bar');71assert.strictEqual(callCounter, 1);72reg.dispose();73});7475test('issue #34913: !onReady, unknown command', function () {7677let callCounter = 0;78let resolveFunc: Function;79const whenInstalledExtensionsRegistered = new Promise<boolean>(_resolve => { resolveFunc = _resolve; });8081const service = store.add(new CommandService(new InstantiationService(), new class extends NullExtensionService {82override whenInstalledExtensionsRegistered() {83return whenInstalledExtensionsRegistered;84}85}, new NullLogService()));8687const r = service.executeCommand('bar');88assert.strictEqual(callCounter, 0);8990const reg = CommandsRegistry.registerCommand('bar', () => callCounter += 1);91resolveFunc!(true);9293return r.then(() => {94reg.dispose();95assert.strictEqual(callCounter, 1);96});97});9899test('Stop waiting for * extensions to activate when trigger is satisfied #62457', function () {100101let callCounter = 0;102const disposable = new DisposableStore();103const events: string[] = [];104const service = store.add(new CommandService(new InstantiationService(), new class extends NullExtensionService {105106override activateByEvent(event: string): Promise<void> {107events.push(event);108if (event === '*') {109return new Promise(() => { }); //forever promise...110}111if (event.indexOf('onCommand:') === 0) {112return new Promise(resolve => {113setTimeout(() => {114const reg = CommandsRegistry.registerCommand(event.substr('onCommand:'.length), () => {115callCounter += 1;116});117disposable.add(reg);118resolve();119}, 0);120});121}122return Promise.resolve();123}124125}, new NullLogService()));126127return service.executeCommand('farboo').then(() => {128assert.strictEqual(callCounter, 1);129assert.deepStrictEqual(events.sort(), ['*', 'onCommand:farboo'].sort());130}).finally(() => {131disposable.dispose();132});133});134135test('issue #71471: wait for onCommand activation even if a command is registered', () => {136const expectedOrder: string[] = ['registering command', 'resolving activation event', 'executing command'];137const actualOrder: string[] = [];138const disposables = new DisposableStore();139const service = store.add(new CommandService(new InstantiationService(), new class extends NullExtensionService {140141override activateByEvent(event: string): Promise<void> {142if (event === '*') {143return new Promise(() => { }); //forever promise...144}145if (event.indexOf('onCommand:') === 0) {146return new Promise(resolve => {147setTimeout(() => {148// Register the command after some time149actualOrder.push('registering command');150const reg = CommandsRegistry.registerCommand(event.substr('onCommand:'.length), () => {151actualOrder.push('executing command');152});153disposables.add(reg);154155setTimeout(() => {156// Resolve the activation event after some more time157actualOrder.push('resolving activation event');158resolve();159}, 10);160}, 10);161});162}163return Promise.resolve();164}165166}, new NullLogService()));167168return service.executeCommand('farboo2').then(() => {169assert.deepStrictEqual(actualOrder, expectedOrder);170}).finally(() => {171disposables.dispose();172});173});174175test('issue #142155: execute commands synchronously if possible', async () => {176const actualOrder: string[] = [];177178const disposables = new DisposableStore();179disposables.add(CommandsRegistry.registerCommand(`bizBaz`, () => {180actualOrder.push('executing command');181}));182const extensionService = new class extends NullExtensionService {183override activationEventIsDone(_activationEvent: string): boolean {184return true;185}186};187const service = store.add(new CommandService(new InstantiationService(), extensionService, new NullLogService()));188189await extensionService.whenInstalledExtensionsRegistered();190191try {192actualOrder.push(`before call`);193const promise = service.executeCommand('bizBaz');194actualOrder.push(`after call`);195await promise;196actualOrder.push(`resolved`);197assert.deepStrictEqual(actualOrder, [198'before call',199'executing command',200'after call',201'resolved'202]);203} finally {204disposables.dispose();205}206});207});208209210