mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
169 lines
5.8 KiB
TypeScript
169 lines
5.8 KiB
TypeScript
import type { Logger, ModuleRegistry } from '@n8n/backend-common';
|
|
import { CliParser } from '@n8n/backend-common';
|
|
import { CommandMetadata } from '@n8n/decorators';
|
|
import { Container } from '@n8n/di';
|
|
import { mock } from 'jest-mock-extended';
|
|
import { z } from 'zod';
|
|
|
|
import { CommandRegistry } from '../command-registry';
|
|
|
|
jest.mock('fast-glob');
|
|
|
|
import glob from 'fast-glob';
|
|
|
|
describe('CommandRegistry', () => {
|
|
let commandRegistry: CommandRegistry;
|
|
let commandMetadata: CommandMetadata;
|
|
const moduleRegistry = mock<ModuleRegistry>();
|
|
const logger = mock<Logger>();
|
|
let originalProcessArgv: string[];
|
|
let mockProcessExit: jest.SpyInstance;
|
|
const cliParser = new CliParser(logger);
|
|
|
|
class TestCommand {
|
|
flags: any;
|
|
|
|
init = jest.fn();
|
|
|
|
run = jest.fn();
|
|
|
|
catch = jest.fn();
|
|
|
|
finally = jest.fn();
|
|
}
|
|
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
|
|
originalProcessArgv = process.argv;
|
|
mockProcessExit = jest.spyOn(process, 'exit').mockImplementation((() => {}) as any);
|
|
|
|
(glob as unknown as jest.Mock).mockResolvedValue([]);
|
|
|
|
commandMetadata = new CommandMetadata();
|
|
Container.set(CommandMetadata, commandMetadata);
|
|
|
|
commandMetadata.register('test-command', {
|
|
description: 'Test command description',
|
|
class: TestCommand,
|
|
examples: ['--example'],
|
|
flagsSchema: z.object({
|
|
flag1: z.string().describe('Flag one description').optional(),
|
|
flag2: z.boolean().describe('Flag two description').optional(),
|
|
shortFlag: z.number().alias('s').describe('Short flag with alias').optional(),
|
|
}),
|
|
});
|
|
|
|
Container.set(TestCommand, new TestCommand());
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.argv = originalProcessArgv;
|
|
mockProcessExit.mockRestore();
|
|
jest.resetAllMocks();
|
|
});
|
|
|
|
it('should execute the specified command', async () => {
|
|
process.argv = ['node', 'n8n', 'test-command'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
expect(moduleRegistry.loadModules).toHaveBeenCalled();
|
|
|
|
const commandInstance = Container.get(commandMetadata.get('test-command')!.class);
|
|
expect(commandInstance.init).toHaveBeenCalled();
|
|
expect(commandInstance.run).toHaveBeenCalled();
|
|
expect(commandInstance.finally).toHaveBeenCalledWith(undefined);
|
|
});
|
|
|
|
it('should handle command errors', async () => {
|
|
process.argv = ['node', 'n8n', 'test-command'];
|
|
|
|
const error = new Error('Test error');
|
|
const commandClass = commandMetadata.get('test-command')!.class;
|
|
const commandInstance = Container.get(commandClass);
|
|
commandInstance.run = jest.fn().mockRejectedValue(error);
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
expect(commandInstance.catch).toHaveBeenCalledWith(error);
|
|
expect(commandInstance.finally).toHaveBeenCalledWith(error);
|
|
});
|
|
|
|
it('should parse and apply command flags', async () => {
|
|
process.argv = ['node', 'n8n', 'test-command', '--flag1', 'value1', '--flag2', '-s', '123'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
const commandInstance = Container.get(commandMetadata.get('test-command')!.class);
|
|
expect(commandInstance.flags).toEqual({
|
|
flag1: 'value1',
|
|
flag2: true,
|
|
shortFlag: 123,
|
|
});
|
|
});
|
|
|
|
it('should handle alias flags', async () => {
|
|
process.argv = ['node', 'n8n', 'test-command', '--flag1', 'value1', '-s', '123'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
const commandInstance = Container.get(commandMetadata.get('test-command')!.class);
|
|
expect(commandInstance.flags).toEqual({
|
|
flag1: 'value1',
|
|
shortFlag: 123,
|
|
});
|
|
});
|
|
|
|
it('should exit with error when command not found', async () => {
|
|
process.argv = ['node', 'n8n', 'non-existent-command'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('not found'));
|
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it('should display help when --help flag is used', async () => {
|
|
process.argv = ['node', 'n8n', 'test-command', '--help'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('USAGE'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('FLAGS'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('DESCRIPTION'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('EXAMPLES'));
|
|
expect(mockProcessExit).toHaveBeenCalledWith(0);
|
|
});
|
|
|
|
it('should list all commands when global help is requested', async () => {
|
|
process.argv = ['node', 'n8n', '--help'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
await commandRegistry.execute();
|
|
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Available commands'));
|
|
expect(mockProcessExit).toHaveBeenCalledWith(0);
|
|
});
|
|
|
|
it('should display proper command usage with printCommandUsage', () => {
|
|
process.argv = ['node', 'n8n', 'test-command'];
|
|
|
|
commandRegistry = new CommandRegistry(commandMetadata, moduleRegistry, logger, cliParser);
|
|
const commandEntry = commandMetadata.get('test-command')!;
|
|
commandRegistry.printCommandUsage(commandEntry);
|
|
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('USAGE'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('test-command'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('--flag1 <value>'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('-s, --shortFlag <value>'));
|
|
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Flag one description'));
|
|
});
|
|
});
|