161 lines
5.5 KiB
TypeScript
161 lines
5.5 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { CommandParser, createCommandParser } from '../../src/commands/CommandParser';
|
|
import { CommandParseError } from '../../src/commands/CommandParser';
|
|
|
|
describe('CommandParser', () => {
|
|
let parser: CommandParser;
|
|
|
|
beforeEach(() => {
|
|
parser = createCommandParser();
|
|
});
|
|
|
|
describe('parse', () => {
|
|
it('should parse simple command without args', () => {
|
|
const result = parser.parse('shuffle');
|
|
|
|
expect(result.commandName).toBe('shuffle');
|
|
expect(result.args.positional).toEqual([]);
|
|
expect(result.args.flags).toEqual({});
|
|
});
|
|
|
|
it('should parse command with positional args', () => {
|
|
const result = parser.parse('move card-1 discard');
|
|
|
|
expect(result.commandName).toBe('move');
|
|
expect(result.args.positional).toEqual(['card-1', 'discard']);
|
|
expect(result.args.flags).toEqual({});
|
|
});
|
|
|
|
it('should parse command with multiple positional args', () => {
|
|
const result = parser.parse('position p1 3 5');
|
|
|
|
expect(result.commandName).toBe('position');
|
|
expect(result.args.positional).toEqual(['p1', '3', '5']);
|
|
});
|
|
|
|
it('should parse command with flag', () => {
|
|
const result = parser.parse('shuffle discard --seed=2026');
|
|
|
|
expect(result.commandName).toBe('shuffle');
|
|
expect(result.args.positional).toEqual(['discard']);
|
|
expect(result.args.flags).toEqual({ seed: 2026 });
|
|
});
|
|
|
|
it('should parse command with multiple flags', () => {
|
|
const result = parser.parse('create meeple m1 --color=red --name=Player1');
|
|
|
|
expect(result.commandName).toBe('create');
|
|
expect(result.args.positional).toEqual(['meeple', 'm1']);
|
|
expect(result.args.flags).toEqual({ color: 'red', name: 'Player1' });
|
|
});
|
|
|
|
it('should parse command with boolean flag', () => {
|
|
const result = parser.parse('flip p1 --faceup');
|
|
|
|
expect(result.commandName).toBe('flip');
|
|
expect(result.args.positional).toEqual(['p1']);
|
|
expect(result.args.flags).toEqual({ faceup: true });
|
|
});
|
|
|
|
it('should parse command with short flag', () => {
|
|
const result = parser.parse('shuffle d1 -s');
|
|
|
|
expect(result.commandName).toBe('shuffle');
|
|
expect(result.args.positional).toEqual(['d1']);
|
|
expect(result.args.flags).toEqual({ s: true });
|
|
});
|
|
|
|
it('should parse command with short flag and value', () => {
|
|
const result = parser.parse('shuffle d1 --seed=2026');
|
|
|
|
expect(result.commandName).toBe('shuffle');
|
|
expect(result.args.positional).toEqual(['d1']);
|
|
expect(result.args.flags).toEqual({ seed: 2026 });
|
|
});
|
|
|
|
it('should parse command with string number value', () => {
|
|
const result = parser.parse('rotate p1 90');
|
|
|
|
expect(result.commandName).toBe('rotate');
|
|
expect(result.args.positional).toEqual(['p1', '90']);
|
|
});
|
|
|
|
it('should parse command with negative number', () => {
|
|
const result = parser.parse('rotate p1 -45');
|
|
|
|
expect(result.commandName).toBe('rotate');
|
|
expect(result.args.positional).toEqual(['p1', '-45']);
|
|
});
|
|
|
|
it('should parse command with float number', () => {
|
|
const result = parser.parse('rotate p1 45.5');
|
|
|
|
expect(result.commandName).toBe('rotate');
|
|
expect(result.args.positional).toEqual(['p1', '45.5']);
|
|
});
|
|
|
|
it('should parse command with quoted string', () => {
|
|
const result = parser.parse('create meeple m1 --name="Red Player"');
|
|
|
|
expect(result.commandName).toBe('create');
|
|
expect(result.args.positional).toEqual(['meeple', 'm1']);
|
|
expect(result.args.flags).toEqual({ name: 'Red Player' });
|
|
});
|
|
|
|
it('should parse command with single quoted string', () => {
|
|
const result = parser.parse("create meeple m1 --name='Blue Player'");
|
|
|
|
expect(result.commandName).toBe('create');
|
|
expect(result.args.positional).toEqual(['meeple', 'm1']);
|
|
expect(result.args.flags).toEqual({ name: 'Blue Player' });
|
|
});
|
|
|
|
it('should handle extra whitespace', () => {
|
|
const result = parser.parse(' move card-1 discard ');
|
|
|
|
expect(result.commandName).toBe('move');
|
|
expect(result.args.positional).toEqual(['card-1', 'discard']);
|
|
});
|
|
|
|
it('should throw on empty command', () => {
|
|
expect(() => parser.parse('')).toThrow(CommandParseError);
|
|
expect(() => parser.parse(' ')).toThrow(CommandParseError);
|
|
});
|
|
|
|
it('should throw on unclosed quote', () => {
|
|
expect(() => parser.parse('create meeple m1 --name="Red')).toThrow(CommandParseError);
|
|
});
|
|
});
|
|
|
|
describe('formatCommand', () => {
|
|
it('should format simple command', () => {
|
|
const formatted = CommandParser.formatCommand('shuffle');
|
|
expect(formatted).toBe('shuffle');
|
|
});
|
|
|
|
it('should format command with positional args', () => {
|
|
const formatted = CommandParser.formatCommand('move', {
|
|
positional: ['card-1', 'discard'],
|
|
flags: {},
|
|
});
|
|
expect(formatted).toBe('move card-1 discard');
|
|
});
|
|
|
|
it('should format command with flags', () => {
|
|
const formatted = CommandParser.formatCommand('shuffle', {
|
|
positional: ['discard'],
|
|
flags: { seed: 2026 },
|
|
});
|
|
expect(formatted).toBe('shuffle discard --seed=2026');
|
|
});
|
|
|
|
it('should format command with boolean flag', () => {
|
|
const formatted = CommandParser.formatCommand('flip', {
|
|
positional: ['p1'],
|
|
flags: { faceup: true },
|
|
});
|
|
expect(formatted).toBe('flip p1 --faceup');
|
|
});
|
|
});
|
|
});
|