@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
283 lines • 14.2 kB
JavaScript
"use strict";
// *****************************************************************************
// Copyright (C) 2018 Red Hat and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
const command_1 = require("./command");
const chai = require("chai");
const expect = chai.expect;
let commandRegistry;
describe('Commands', () => {
beforeEach(() => {
commandRegistry = new command_1.CommandRegistry(new EmptyContributionProvider());
});
it('should register and execute a given command', async () => {
const concatId = 'concat';
const command = { id: concatId };
commandRegistry.registerCommand(command, new ConcatCommandHandler());
const result = await commandRegistry.executeCommand(concatId, 'a', 'b', 'c');
expect('abc').equals(result);
});
it('should add command to recently used', async () => {
const commandId = 'stub';
const command = { id: commandId };
commandRegistry.registerCommand(command, new StubCommandHandler());
commandRegistry.addRecentCommand(command);
expect(commandRegistry.recent.length).equal(1);
});
it('should add multiple commands to recently used in the order they were used', async () => {
const commandIds = ['a', 'b', 'c'];
const commands = [
{ id: commandIds[0] },
{ id: commandIds[1] },
{ id: commandIds[2] },
];
// Register each command.
commands.forEach((c) => {
commandRegistry.registerCommand(c, new StubCommandHandler());
});
// Execute order c, b, a.
commandRegistry.addRecentCommand(commands[2]);
commandRegistry.addRecentCommand(commands[1]);
commandRegistry.addRecentCommand(commands[0]);
// Expect recently used to be a, b, c.
const result = commandRegistry.recent;
expect(result.length).equal(3);
expect(result[0].id).equal(commandIds[0]);
expect(result[1].id).equal(commandIds[1]);
expect(result[2].id).equal(commandIds[2]);
});
it('should add a previously used command to the top of the most recently used', async () => {
const commandIds = ['a', 'b', 'c'];
const commands = [
{ id: commandIds[0] },
{ id: commandIds[1] },
{ id: commandIds[2] },
];
// Register each command.
commands.forEach((c) => {
commandRegistry.registerCommand(c, new StubCommandHandler());
});
// Execute order a, b, c, a.
commandRegistry.addRecentCommand(commands[0]);
commandRegistry.addRecentCommand(commands[1]);
commandRegistry.addRecentCommand(commands[2]);
commandRegistry.addRecentCommand(commands[0]);
// Expect recently used to be a, b, c.
const result = commandRegistry.recent;
expect(result.length).equal(3);
expect(result[0].id).equal(commandIds[0]);
expect(result[1].id).equal(commandIds[2]);
expect(result[2].id).equal(commandIds[1]);
});
it('should clear the recently used command history', async () => {
const commandIds = ['a', 'b', 'c'];
const commands = [
{ id: commandIds[0] },
{ id: commandIds[1] },
{ id: commandIds[2] },
];
// Register each command.
commands.forEach((c) => {
commandRegistry.registerCommand(c, new StubCommandHandler());
});
// Execute each command.
commandRegistry.addRecentCommand(commands[0]);
commandRegistry.addRecentCommand(commands[1]);
commandRegistry.addRecentCommand(commands[2]);
// Clear the list of recently used commands.
commandRegistry.clearCommandHistory();
expect(commandRegistry.recent.length).equal(0);
});
it('should return with an empty array of handlers if the command is not registered', () => {
expect(commandRegistry.getCommand('missing')).to.be.undefined;
expect(commandRegistry.getAllHandlers('missing')).to.be.empty;
});
it('should return with an empty array of handlers if the command has no registered handlers', () => {
commandRegistry.registerCommand({ id: 'id' });
expect(commandRegistry.getCommand('id')).to.be.not.undefined;
expect(commandRegistry.getAllHandlers('id')).to.be.empty;
});
it('should return all handlers including the non active ones', () => {
commandRegistry.registerCommand({ id: 'id' });
commandRegistry.registerHandler('id', new StubCommandHandler());
commandRegistry.registerHandler('id', new NeverActiveStubCommandHandler());
expect(commandRegistry.getAllHandlers('id').length).to.be.equal(2);
});
describe('registerAlias', () => {
it('onDidExecuteCommand fires for alias when target is executed', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerAlias('alias', 'target');
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('target');
expect(events).to.deep.equal(['target', 'alias']);
});
it('onDidExecuteCommand fires only for alias when alias is executed (no reverse)', async () => {
commandRegistry.registerCommand({ id: 'alias' }, new StubCommandHandler());
commandRegistry.registerAlias('alias', 'target');
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('alias');
// Unidirectional: an alias fires for its target, but not the other way round
expect(events).to.deep.equal(['alias']);
});
it('onWillExecuteCommand fires for alias when target is executed', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerAlias('alias', 'target');
const events = [];
commandRegistry.onWillExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('target');
expect(events).to.deep.equal(['target', 'alias']);
});
it('disposing the alias removes the event link', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
const disposable = commandRegistry.registerAlias('alias', 'target');
disposable.dispose();
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('target');
expect(events).to.deep.equal(['target']);
});
it('getAliases returns the aliases registered for a target', () => {
commandRegistry.registerAlias('a', 'b');
expect(commandRegistry.getAliases('b')).to.deep.equal(['a']);
});
it('getAliases returns nothing for the alias direction (unidirectional)', () => {
commandRegistry.registerAlias('a', 'b');
expect(commandRegistry.getAliases('a')).to.be.empty;
});
it('getAliases returns nothing for unaliased commands', () => {
expect(commandRegistry.getAliases('nonexistent')).to.be.empty;
});
it('a target can carry several aliases', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerAlias('alias1', 'target');
commandRegistry.registerAlias('alias2', 'target');
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('target');
expect(events).to.deep.equal(['target', 'alias1', 'alias2']);
});
it('disposing one alias keeps the others', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
const first = commandRegistry.registerAlias('alias1', 'target');
commandRegistry.registerAlias('alias2', 'target');
first.dispose();
expect(commandRegistry.getAliases('target')).to.deep.equal(['alias2']);
});
it('alias events include correct args', async () => {
commandRegistry.registerCommand({ id: 'target' }, new ConcatCommandHandler());
commandRegistry.registerAlias('alias', 'target');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const capturedArgs = [];
commandRegistry.onDidExecuteCommand(e => capturedArgs.push(e.args));
await commandRegistry.executeCommand('target', 'x', 'y');
expect(capturedArgs.length).to.equal(2);
expect(capturedArgs[0]).to.deep.equal(['x', 'y']);
expect(capturedArgs[1]).to.deep.equal(['x', 'y']);
});
it('nested execution: alias handler delegating to target fires target and alias events', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerCommand({ id: 'alias' }, {
execute: () => commandRegistry.executeCommand('target')
});
commandRegistry.registerAlias('alias', 'target');
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('alias');
// The alias is on the stack while the target runs, so its event is only reported once.
expect(events).to.deep.equal(['target', 'alias']);
});
it('reports the alias once for the will execute event as well', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerCommand({ id: 'alias' }, {
execute: () => commandRegistry.executeCommand('target')
});
commandRegistry.registerAlias('alias', 'target');
const events = [];
commandRegistry.onWillExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('alias');
expect(events).to.deep.equal(['alias', 'target']);
});
it('reports the alias again once the delegating execution finished', async () => {
commandRegistry.registerCommand({ id: 'target' }, new StubCommandHandler());
commandRegistry.registerCommand({ id: 'alias' }, {
execute: () => commandRegistry.executeCommand('target')
});
commandRegistry.registerAlias('alias', 'target');
await commandRegistry.executeCommand('alias');
const events = [];
commandRegistry.onDidExecuteCommand(e => events.push(e.commandId));
await commandRegistry.executeCommand('target');
expect(events).to.deep.equal(['target', 'alias']);
});
});
describe('compareCommands', () => {
it('should sort command \'a\' before command \'b\' with categories', () => {
const a = { id: 'a', category: 'a', label: 'a' };
const b = { id: 'b', category: 'b', label: 'b' };
expect(command_1.Command.compareCommands(a, b)).to.equal(-1);
expect(command_1.Command.compareCommands(b, a)).to.equal(1);
});
it('should sort command \'a\' before command \'b\' without categories', () => {
const a = { id: 'a', label: 'a' };
const b = { id: 'b', label: 'b' };
expect(command_1.Command.compareCommands(a, b)).to.equal(-1);
expect(command_1.Command.compareCommands(b, a)).to.equal(1);
});
it('should sort command \'a\' before command \'b\' with mix-match categories', () => {
const a = { id: 'a', category: 'a', label: 'a' };
const b = { id: 'b', label: 'a' };
expect(command_1.Command.compareCommands(a, b)).to.equal(1);
expect(command_1.Command.compareCommands(b, a)).to.equal(-1);
});
it('should sort irregardless of casing', () => {
const lowercase = { id: 'a', label: 'a' };
const uppercase = { id: 'a', label: 'A' };
expect(command_1.Command.compareCommands(lowercase, uppercase)).to.equal(0);
});
it('should not sort if commands are equal', () => {
const a = { id: 'a', label: 'a' };
expect(command_1.Command.compareCommands(a, a)).to.equal(0);
});
it('should not sort commands without labels', () => {
const a = { id: 'a' };
const b = { id: 'b' };
expect(command_1.Command.compareCommands(a, b)).to.equal(0);
});
});
});
class EmptyContributionProvider {
getContributions(recursive) {
return [];
}
}
class ConcatCommandHandler {
execute(...args) {
let concat = '';
args.forEach(element => {
concat += element;
});
return concat;
}
}
class StubCommandHandler {
execute(...args) { return undefined; }
}
class NeverActiveStubCommandHandler extends StubCommandHandler {
isEnabled() { return false; }
}
//# sourceMappingURL=command.spec.js.map