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'); }); }); });