Files
lettabot/src/core/commands.test.ts
2026-03-11 17:27:07 -07:00

121 lines
4.0 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { parseCommand, COMMANDS, HELP_TEXT } from './commands.js';
describe('parseCommand', () => {
describe('valid commands', () => {
it('returns { command, args } for /status', () => {
expect(parseCommand('/status')).toEqual({ command: 'status', args: '' });
});
it('returns { command, args } for /heartbeat', () => {
expect(parseCommand('/heartbeat')).toEqual({ command: 'heartbeat', args: '' });
});
it('returns { command, args } for /help', () => {
expect(parseCommand('/help')).toEqual({ command: 'help', args: '' });
});
it('returns { command, args } for /start', () => {
expect(parseCommand('/start')).toEqual({ command: 'start', args: '' });
});
it('returns { command, args } for /reset', () => {
expect(parseCommand('/reset')).toEqual({ command: 'reset', args: '' });
});
it('returns { command, args } for /model', () => {
expect(parseCommand('/model')).toEqual({ command: 'model', args: '' });
});
it('returns { command, args } for /cancel', () => {
expect(parseCommand('/cancel')).toEqual({ command: 'cancel', args: '' });
});
});
describe('invalid input', () => {
it('returns null for non-slash messages', () => {
expect(parseCommand('hello')).toBeNull();
expect(parseCommand('status')).toBeNull();
});
it('returns null for empty string', () => {
expect(parseCommand('')).toBeNull();
});
it('returns null for null/undefined', () => {
expect(parseCommand(null)).toBeNull();
expect(parseCommand(undefined)).toBeNull();
});
it('returns null for unknown commands', () => {
expect(parseCommand('/unknown')).toBeNull();
expect(parseCommand('/foo')).toBeNull();
expect(parseCommand('/stats')).toBeNull(); // Similar but not exact
});
});
describe('command parsing', () => {
it('captures trailing text as args', () => {
expect(parseCommand('/status please')).toEqual({ command: 'status', args: 'please' });
expect(parseCommand('/help me')).toEqual({ command: 'help', args: 'me' });
});
it('is case insensitive', () => {
expect(parseCommand('/STATUS')).toEqual({ command: 'status', args: '' });
expect(parseCommand('/Help')).toEqual({ command: 'help', args: '' });
expect(parseCommand('/HEARTBEAT')).toEqual({ command: 'heartbeat', args: '' });
});
it('handles commands with trailing whitespace', () => {
expect(parseCommand('/status ')).toEqual({ command: 'status', args: '' });
});
it('parses /model with a handle argument', () => {
expect(parseCommand('/model anthropic/claude-sonnet-4-5-20250929')).toEqual({
command: 'model',
args: 'anthropic/claude-sonnet-4-5-20250929',
});
});
it('preserves multi-word args', () => {
expect(parseCommand('/model some handle with spaces')).toEqual({
command: 'model',
args: 'some handle with spaces',
});
});
});
});
describe('COMMANDS', () => {
it('contains all expected commands', () => {
expect(COMMANDS).toContain('status');
expect(COMMANDS).toContain('heartbeat');
expect(COMMANDS).toContain('reset');
expect(COMMANDS).toContain('help');
expect(COMMANDS).toContain('start');
expect(COMMANDS).toContain('model');
expect(COMMANDS).toContain('setconv');
});
it('has exactly 8 commands', () => {
expect(COMMANDS).toHaveLength(8);
});
});
describe('HELP_TEXT', () => {
it('contains command descriptions', () => {
expect(HELP_TEXT).toContain('/status');
expect(HELP_TEXT).toContain('/heartbeat');
expect(HELP_TEXT).toContain('/reset');
expect(HELP_TEXT).toContain('/cancel');
expect(HELP_TEXT).toContain('/help');
expect(HELP_TEXT).toContain('/start');
expect(HELP_TEXT).toContain('/model');
expect(HELP_TEXT).toContain('/setconv');
});
it('contains LettaBot branding', () => {
expect(HELP_TEXT).toContain('LettaBot');
});
});