mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-11 18:42:56 +00:00
327 lines
9.5 KiB
TypeScript
327 lines
9.5 KiB
TypeScript
import { Command } from '../src/command';
|
|
|
|
describe('Command', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
});
|
|
|
|
describe('registerCommand', () => {
|
|
it('should register a command successfully', () => {
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: mockHandler,
|
|
};
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
|
|
const registeredCommand = commandInstance.listCommands().find(c => c.name === 'testScope:testCommand');
|
|
expect(registeredCommand).toBeDefined();
|
|
expect(registeredCommand.name).toBe('testScope:testCommand');
|
|
});
|
|
|
|
it('should throw an error if commandScope is not provided', () => {
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: mockHandler,
|
|
};
|
|
|
|
expect(() => {
|
|
commandInstance.registerCommand(command);
|
|
}).toThrow('plugin meta.commandScope is required.');
|
|
});
|
|
|
|
it('should throw an error if command is already registered', () => {
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: mockHandler,
|
|
};
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
|
|
expect(() => {
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
}).toThrow(`Command 'testCommand' is already registered.`);
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|
|
|
|
describe('unregisterCommand', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
// 先注册一个命令以便之后注销
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: mockHandler,
|
|
};
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
});
|
|
|
|
it('should unregister a command successfully', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
expect(commandInstance.listCommands().find(c => c.name === commandName)).toBeDefined();
|
|
|
|
commandInstance.unregisterCommand(commandName);
|
|
|
|
expect(commandInstance.listCommands().find(c => c.name === commandName)).toBeUndefined();
|
|
});
|
|
|
|
it('should throw an error if the command is not registered', () => {
|
|
const nonExistingCommandName = 'testScope:nonExistingCommand';
|
|
expect(() => {
|
|
commandInstance.unregisterCommand(nonExistingCommandName);
|
|
}).toThrow(`Command '${nonExistingCommandName}' is not registered.`);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|
|
|
|
describe('executeCommand', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
// 注册一个带参数校验的命令
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: mockHandler,
|
|
parameters: [
|
|
{ name: 'param1', propType: 'string' },
|
|
{ name: 'param2', propType: 'number' }
|
|
],
|
|
};
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
});
|
|
|
|
it('should execute a command successfully', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
const args = { param1: 'test', param2: 42 };
|
|
|
|
commandInstance.executeCommand(commandName, args);
|
|
|
|
expect(mockHandler).toHaveBeenCalledWith(args);
|
|
});
|
|
|
|
it('should throw an error if the command is not registered', () => {
|
|
const nonExistingCommandName = 'testScope:nonExistingCommand';
|
|
expect(() => {
|
|
commandInstance.executeCommand(nonExistingCommandName, {});
|
|
}).toThrow(`Command '${nonExistingCommandName}' is not registered.`);
|
|
});
|
|
|
|
it('should throw an error if arguments are invalid', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
const invalidArgs = { param1: 'test', param2: 'not-a-number' }; // param2 should be a number
|
|
|
|
expect(() => {
|
|
commandInstance.executeCommand(commandName, invalidArgs);
|
|
}).toThrow(`Command '${commandName}' arguments param2 is invalid.`);
|
|
});
|
|
|
|
it('should handle errors thrown by the command handler', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
const args = { param1: 'test', param2: 42 };
|
|
const errorMessage = 'Command handler error';
|
|
mockHandler.mockImplementation(() => {
|
|
throw new Error(errorMessage);
|
|
});
|
|
|
|
expect(() => {
|
|
commandInstance.executeCommand(commandName, args);
|
|
}).toThrow(errorMessage);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|
|
|
|
describe('batchExecuteCommand', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
let mockExecuteTransaction;
|
|
let mockPluginContext;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
mockExecuteTransaction = jest.fn(callback => callback());
|
|
mockPluginContext = {
|
|
common: {
|
|
utils: {
|
|
executeTransaction: mockExecuteTransaction
|
|
}
|
|
}
|
|
};
|
|
|
|
// 注册几个命令
|
|
const command1 = {
|
|
name: 'testCommand1',
|
|
handler: mockHandler,
|
|
};
|
|
const command2 = {
|
|
name: 'testCommand2',
|
|
handler: mockHandler,
|
|
};
|
|
commandInstance.registerCommand(command1, { commandScope: 'testScope' });
|
|
commandInstance.registerCommand(command2, { commandScope: 'testScope' });
|
|
});
|
|
|
|
it('should execute a batch of commands', () => {
|
|
const commands = [
|
|
{ name: 'testScope:testCommand1', args: { param: 'value1' } },
|
|
{ name: 'testScope:testCommand2', args: { param: 'value2' } },
|
|
];
|
|
|
|
commandInstance.batchExecuteCommand(commands, mockPluginContext);
|
|
|
|
expect(mockExecuteTransaction).toHaveBeenCalledTimes(1);
|
|
expect(mockHandler).toHaveBeenCalledWith({ param: 'value1' });
|
|
expect(mockHandler).toHaveBeenCalledWith({ param: 'value2' });
|
|
});
|
|
|
|
it('should not execute anything if commands array is empty', () => {
|
|
commandInstance.batchExecuteCommand([], mockPluginContext);
|
|
|
|
expect(mockExecuteTransaction).not.toHaveBeenCalled();
|
|
expect(mockHandler).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle errors thrown during command execution', () => {
|
|
const errorMessage = 'Command handler error';
|
|
mockHandler.mockImplementation(() => {
|
|
throw new Error(errorMessage);
|
|
});
|
|
|
|
const commands = [
|
|
{ name: 'testScope:testCommand1', args: { param: 'value1' } },
|
|
{ name: 'testScope:testCommand2', args: { param: 'value2' } },
|
|
];
|
|
|
|
expect(() => {
|
|
commandInstance.batchExecuteCommand(commands, mockPluginContext);
|
|
}).toThrow(errorMessage);
|
|
|
|
expect(mockExecuteTransaction).toHaveBeenCalledTimes(1); // Still called once
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|
|
|
|
describe('listCommands', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
});
|
|
|
|
it('should list all registered commands', () => {
|
|
// 注册几个命令
|
|
const command1 = {
|
|
name: 'testCommand1',
|
|
handler: mockHandler,
|
|
description: 'Test Command 1',
|
|
parameters: [{ name: 'param1', propType: 'string' }]
|
|
};
|
|
const command2 = {
|
|
name: 'testCommand2',
|
|
handler: mockHandler,
|
|
description: 'Test Command 2',
|
|
parameters: [{ name: 'param2', propType: 'number' }]
|
|
};
|
|
commandInstance.registerCommand(command1, { commandScope: 'testScope' });
|
|
commandInstance.registerCommand(command2, { commandScope: 'testScope' });
|
|
|
|
const listedCommands = commandInstance.listCommands();
|
|
|
|
expect(listedCommands.length).toBe(2);
|
|
expect(listedCommands).toEqual(expect.arrayContaining([
|
|
expect.objectContaining({
|
|
name: 'testScope:testCommand1',
|
|
description: 'Test Command 1',
|
|
parameters: [{ name: 'param1', propType: 'string' }]
|
|
}),
|
|
expect.objectContaining({
|
|
name: 'testScope:testCommand2',
|
|
description: 'Test Command 2',
|
|
parameters: [{ name: 'param2', propType: 'number' }]
|
|
})
|
|
]));
|
|
});
|
|
|
|
it('should return an empty array if no commands are registered', () => {
|
|
const listedCommands = commandInstance.listCommands();
|
|
expect(listedCommands).toEqual([]);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|
|
|
|
describe('onCommandError', () => {
|
|
let commandInstance;
|
|
let mockHandler;
|
|
let mockErrorHandler1;
|
|
let mockErrorHandler2;
|
|
|
|
beforeEach(() => {
|
|
commandInstance = new Command();
|
|
mockHandler = jest.fn();
|
|
mockErrorHandler1 = jest.fn();
|
|
mockErrorHandler2 = jest.fn();
|
|
|
|
// 注册一个命令,该命令会抛出错误
|
|
const command = {
|
|
name: 'testCommand',
|
|
handler: () => {
|
|
throw new Error('Command execution failed');
|
|
},
|
|
};
|
|
commandInstance.registerCommand(command, { commandScope: 'testScope' });
|
|
});
|
|
|
|
it('should call all registered error handlers when a command throws an error', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
commandInstance.onCommandError(mockErrorHandler1);
|
|
commandInstance.onCommandError(mockErrorHandler2);
|
|
|
|
expect(() => {
|
|
commandInstance.executeCommand(commandName, {});
|
|
}).not.toThrow();
|
|
|
|
// 确保所有错误处理函数都被调用,并且传递了正确的参数
|
|
expect(mockErrorHandler1).toHaveBeenCalledWith(commandName, expect.any(Error));
|
|
expect(mockErrorHandler2).toHaveBeenCalledWith(commandName, expect.any(Error));
|
|
});
|
|
|
|
it('should throw the error if no error handlers are registered', () => {
|
|
const commandName = 'testScope:testCommand';
|
|
|
|
expect(() => {
|
|
commandInstance.executeCommand(commandName, {});
|
|
}).toThrow('Command execution failed');
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|