refactor: command syntax improvement
This commit is contained in:
@@ -21,11 +21,11 @@ describe('parseCommandSchema with inline-schema', () => {
|
||||
it('should parse schema with typed options', () => {
|
||||
const schema = parseCommandSchema('move <from> <to> [--all: boolean] [--count: number]');
|
||||
expect(schema.name).toBe('move');
|
||||
expect(schema.options).toHaveLength(2);
|
||||
expect(schema.options[0].name).toBe('all');
|
||||
expect(schema.flags).toHaveLength(1);
|
||||
expect(schema.options).toHaveLength(1);
|
||||
expect(schema.flags[0].name).toBe('all');
|
||||
expect(schema.options[0].name).toBe('count');
|
||||
expect(schema.options[0].schema).toBeDefined();
|
||||
expect(schema.options[1].name).toBe('count');
|
||||
expect(schema.options[1].schema).toBeDefined();
|
||||
});
|
||||
|
||||
it('should parse schema with tuple type', () => {
|
||||
@@ -54,11 +54,11 @@ describe('parseCommandSchema with inline-schema', () => {
|
||||
|
||||
it('should parse schema with mixed types', () => {
|
||||
const schema = parseCommandSchema(
|
||||
'move <from: [x: string; y: string]> <to: string> [--all: boolean] [--count: number]'
|
||||
'move <from: [x: string; y: string]> <to: string> [--count: number]'
|
||||
);
|
||||
expect(schema.name).toBe('move');
|
||||
expect(schema.params).toHaveLength(2);
|
||||
expect(schema.options).toHaveLength(2);
|
||||
expect(schema.options).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should parse schema with optional typed param', () => {
|
||||
@@ -94,17 +94,6 @@ describe('parseCommandWithSchema', () => {
|
||||
});
|
||||
|
||||
it('should parse and validate command with boolean option', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'move meeple1 region1 --all true',
|
||||
'move <from> <to> [--all: boolean]'
|
||||
);
|
||||
expect(result.valid).toBe(true);
|
||||
if (result.valid) {
|
||||
expect(result.command.options.all).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('should parse and validate command with number option', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'move meeple1 region1 --count 5',
|
||||
'move <from> <to> [--count: number]'
|
||||
@@ -115,6 +104,17 @@ describe('parseCommandWithSchema', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should parse and validate command with number option', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'move meeple1 region1 --speed 100',
|
||||
'move <from> <to> [--speed: number]'
|
||||
);
|
||||
expect(result.valid).toBe(true);
|
||||
if (result.valid) {
|
||||
expect(result.command.options.speed).toBe(100);
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail validation with wrong command name', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'jump meeple1 region1',
|
||||
@@ -144,22 +144,21 @@ describe('parseCommandWithSchema', () => {
|
||||
it('should fail validation with missing required option', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'move meeple1 region1',
|
||||
'move <from> <to> [--force: boolean]'
|
||||
'move <from> <to> [--force]'
|
||||
);
|
||||
// 可选选项,应该通过验证
|
||||
// 可选标志,应该通过验证
|
||||
expect(result.valid).toBe(true);
|
||||
});
|
||||
|
||||
it('should parse complex command with typed params and options', () => {
|
||||
const result = parseCommandWithSchema(
|
||||
'move [1; 2] region1 --all true --count 3',
|
||||
'move <from: [x: string; y: string]> <to: string> [--all: boolean] [--count: number]'
|
||||
'move [1; 2] region1 --count 3',
|
||||
'move <from: [x: string; y: string]> <to: string> [--count: number]'
|
||||
);
|
||||
expect(result.valid).toBe(true);
|
||||
if (result.valid) {
|
||||
expect(result.command.params[0]).toEqual(['1', '2']);
|
||||
expect(result.command.params[1]).toBe('region1');
|
||||
expect(result.command.options.all).toBe(true);
|
||||
expect(result.command.options.count).toBe(3);
|
||||
}
|
||||
});
|
||||
@@ -207,8 +206,8 @@ describe('validateCommand with schema types', () => {
|
||||
});
|
||||
|
||||
it('should validate command with typed options', () => {
|
||||
const schema = parseCommandSchema('move <from> <to> [--all: boolean]');
|
||||
const command = parseCommand('move meeple1 region1 --all true');
|
||||
const schema = parseCommandSchema('move <from> <to> [--count: number]');
|
||||
const command = parseCommand('move meeple1 region1 --count 5');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result.valid).toBe(true);
|
||||
});
|
||||
|
||||
@@ -70,42 +70,41 @@ describe('parseCommandSchema', () => {
|
||||
});
|
||||
|
||||
it('should parse long options', () => {
|
||||
const schema = parseCommandSchema('move --x <value> [--y value]');
|
||||
const schema = parseCommandSchema('move --x: string [--y: string]');
|
||||
expect(schema.options).toEqual([
|
||||
{ name: 'x', required: true },
|
||||
{ name: 'y', required: false },
|
||||
{ name: 'x', required: true, schema: expect.any(Object) },
|
||||
{ name: 'y', required: false, schema: expect.any(Object) },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse short options', () => {
|
||||
const schema = parseCommandSchema('move -x <value> [-y value]');
|
||||
const schema = parseCommandSchema('move -x: string [-y: string]');
|
||||
expect(schema.options).toEqual([
|
||||
{ name: 'x', short: 'x', required: true },
|
||||
{ name: 'y', short: 'y', required: false },
|
||||
{ name: 'x', short: 'x', required: true, schema: expect.any(Object) },
|
||||
{ name: 'y', short: 'y', required: false, schema: expect.any(Object) },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse mixed schema', () => {
|
||||
const schema = parseCommandSchema('move <from> <to> [--force] [-f] [--speed <val>] [-s val]');
|
||||
const schema = parseCommandSchema('move <from> <to> [--force] [-f] [--speed: string -s]');
|
||||
expect(schema).toEqual({
|
||||
name: 'move',
|
||||
params: [
|
||||
{ name: 'from', required: true, variadic: false },
|
||||
{ name: 'to', required: true, variadic: false },
|
||||
{ name: 'from', required: true, variadic: false, schema: undefined },
|
||||
{ name: 'to', required: true, variadic: false, schema: undefined },
|
||||
],
|
||||
flags: [
|
||||
{ name: 'force' },
|
||||
{ name: 'f', short: 'f' },
|
||||
],
|
||||
options: [
|
||||
{ name: 'speed', required: false },
|
||||
{ name: 's', short: 's', required: false },
|
||||
{ name: 'speed', short: 's', required: false, schema: expect.any(Object), defaultValue: undefined },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle complex schema', () => {
|
||||
const schema = parseCommandSchema('place <piece> <region> [x...] [--rotate <angle>] [--force] [-f]');
|
||||
const schema = parseCommandSchema('place <piece> <region> [x...] [--rotate: number] [--force] [-f]');
|
||||
expect(schema.name).toBe('place');
|
||||
expect(schema.params).toHaveLength(3);
|
||||
expect(schema.flags).toHaveLength(2);
|
||||
@@ -172,7 +171,7 @@ describe('validateCommand', () => {
|
||||
});
|
||||
|
||||
it('should reject missing required option', () => {
|
||||
const schema = parseCommandSchema('move <from> --speed <val>');
|
||||
const schema = parseCommandSchema('move <from> --speed: string');
|
||||
const command = parseCommand('move meeple1');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result).toEqual({
|
||||
@@ -184,14 +183,14 @@ describe('validateCommand', () => {
|
||||
});
|
||||
|
||||
it('should accept present required option', () => {
|
||||
const schema = parseCommandSchema('move <from> --speed <val>');
|
||||
const schema = parseCommandSchema('move <from> --speed: string');
|
||||
const command = parseCommand('move meeple1 --speed 10');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result).toEqual({ valid: true });
|
||||
});
|
||||
|
||||
it('should accept optional option missing', () => {
|
||||
const schema = parseCommandSchema('move <from> [--speed [val]]');
|
||||
const schema = parseCommandSchema('move <from> [--speed: string]');
|
||||
const command = parseCommand('move meeple1');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result).toEqual({ valid: true });
|
||||
@@ -206,14 +205,14 @@ describe('validateCommand', () => {
|
||||
});
|
||||
|
||||
it('should validate short form option', () => {
|
||||
const schema = parseCommandSchema('move <from> -s <val>');
|
||||
const schema = parseCommandSchema('move <from> -s: string');
|
||||
const command = parseCommand('move meeple1 -s 10');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result).toEqual({ valid: true });
|
||||
});
|
||||
|
||||
it('should provide detailed error messages', () => {
|
||||
const schema = parseCommandSchema('place <piece> <region> --rotate <angle>');
|
||||
const schema = parseCommandSchema('place <piece> <region> --rotate: string');
|
||||
const command = parseCommand('place meeple1');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result.valid).toBe(false);
|
||||
@@ -225,7 +224,7 @@ describe('validateCommand', () => {
|
||||
|
||||
describe('integration', () => {
|
||||
it('should work together parse and validate', () => {
|
||||
const schemaStr = 'place <piece> <region> [--x <val>] [--y [val]] [--force] [-f]';
|
||||
const schemaStr = 'place <piece> <region> [--x: string] [--y: string] [--force] [-f]';
|
||||
const schema = parseCommandSchema(schemaStr);
|
||||
|
||||
const validCmd = parseCommand('place meeple1 board --x 5 --force');
|
||||
@@ -235,4 +234,57 @@ describe('integration', () => {
|
||||
const result = validateCommand(invalidCmd, schema);
|
||||
expect(result.valid).toBe(false);
|
||||
});
|
||||
|
||||
it('should parse short alias syntax', () => {
|
||||
const schema = parseCommandSchema('move <from> [--verbose: boolean -v]');
|
||||
expect(schema.flags).toHaveLength(1);
|
||||
expect(schema.flags[0]).toEqual({ name: 'verbose', short: 'v' });
|
||||
});
|
||||
|
||||
it('should parse short alias for options', () => {
|
||||
const schema = parseCommandSchema('move <from> [--speed: number -s]');
|
||||
expect(schema.options).toHaveLength(1);
|
||||
expect(schema.options[0]).toEqual({
|
||||
name: 'speed',
|
||||
short: 's',
|
||||
required: false,
|
||||
schema: expect.any(Object),
|
||||
defaultValue: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse default value syntax', () => {
|
||||
const schema = parseCommandSchema('move <from> [--speed: number = 10]');
|
||||
expect(schema.options).toHaveLength(1);
|
||||
expect(schema.options[0].defaultValue).toBe(10);
|
||||
});
|
||||
|
||||
it('should parse default string value', () => {
|
||||
const schema = parseCommandSchema('move <from> [--name: string = "default"]');
|
||||
expect(schema.options).toHaveLength(1);
|
||||
expect(schema.options[0].defaultValue).toBe('default');
|
||||
});
|
||||
|
||||
it('should parse short alias with default value', () => {
|
||||
const schema = parseCommandSchema('move <from> [--speed: number -s = 5]');
|
||||
expect(schema.options).toHaveLength(1);
|
||||
expect(schema.options[0].short).toBe('s');
|
||||
expect(schema.options[0].defaultValue).toBe(5);
|
||||
});
|
||||
|
||||
it('should parse command with short alias', () => {
|
||||
const schema = parseCommandSchema('move <from> [--verbose -v]');
|
||||
const command = parseCommand('move meeple1 -v');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result.valid).toBe(true);
|
||||
expect(command.flags.v).toBe(true);
|
||||
});
|
||||
|
||||
it('should parse command with short alias option', () => {
|
||||
const schema = parseCommandSchema('move <from> [--speed: number -s]');
|
||||
const command = parseCommand('move meeple1 -s 100');
|
||||
const result = validateCommand(command, schema);
|
||||
expect(result.valid).toBe(true);
|
||||
expect(command.options.s).toBe('100');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user