import { describe, expect, it } from 'vitest'; import { classify, hasOrderContent } from './commands'; const idle = { collecting: false }; const col = { collecting: true }; describe('classify: single-word commands', () => { it.each(['done', 'DONE', 'Done', ' done ', 'done.', 'Done!', 'submit', 'Submit.'])('%j is submit', (t) => { expect(classify(t, idle)).toEqual({ kind: 'submit', body: '' }); }); it.each(['cancel', 'Cancel', 'CANCEL!', ' cancel. '])('%j is cancel', (t) => { expect(classify(t, idle)).toEqual({ kind: 'cancel' }); }); it.each(['?', 'help', 'Help', 'HELP'])('%j is help', (t) => { expect(classify(t, idle)).toEqual({ kind: 'help' }); }); it.each([ ['1', 1], ['2', 2], ['3', 3], [' 4 ', 4], ['12', 12], ['1.', 1], ])('%j is number %i', (t, n) => { expect(classify(t, idle)).toEqual({ kind: 'number', n }); }); }); describe('classify: order text and look-alikes', () => { it.each(['0888=2', '0888', '123', 'hello', 'thanks', '👍', 'done please', 'cancelled', 'yes', ''])( '%j is text', (t) => { expect(classify(t, idle)).toEqual({ kind: 'text' }); }, ); it('whitespace only is text', () => { expect(classify(' \n \n', idle)).toEqual({ kind: 'text' }); }); it('three or more digits are never a menu number', () => { expect(classify('100', idle)).toEqual({ kind: 'text' }); }); }); describe('classify: done as the last line', () => { it('splits order text from Done', () => { expect(classify('0888\n0057\ndone', idle)).toEqual({ kind: 'submit', body: '0888\n0057' }); }); it('ignores case, punctuation, CRLF and trailing blank lines', () => { expect(classify('0888=2\r\n7810=1\r\nSubmit.\n\n', idle)).toEqual({ kind: 'submit', body: '0888=2\n7810=1' }); }); it('done only counts on the last line', () => { expect(classify('done\n0888', idle)).toEqual({ kind: 'text' }); }); it('cancel on a later line of a longer message is not a command', () => { expect(classify('0888\ncancel', idle)).toEqual({ kind: 'text' }); }); }); describe('classify: trailing 1 (Hermes merges quick messages)', () => { it('is Done when the conversation was already collecting', () => { expect(classify('0888=2\n7810=1\n1', col)).toEqual({ kind: 'submit', body: '0888=2\n7810=1' }); }); it('stays order text in the first message of an order', () => { expect(classify('0888=2\n7810=1\n1', idle)).toEqual({ kind: 'text' }); }); it('a lone 1 is a number either way (the engine decides what it means)', () => { expect(classify('1', col)).toEqual({ kind: 'number', n: 1 }); expect(classify('1', idle)).toEqual({ kind: 'number', n: 1 }); }); it('only 1 works this way, not other numbers', () => { expect(classify('0888=2\n2', col)).toEqual({ kind: 'text' }); }); it('a line ending in 1 is not a trailing 1', () => { expect(classify('0888=2\n7801', col)).toEqual({ kind: 'text' }); }); }); describe('hasOrderContent', () => { it('is true for an entry', () => { expect(hasOrderContent('0888=2')).toBe(true); }); it('is true for something unreadable', () => { expect(hasOrderContent('08?8=2')).toBe(true); }); it('is false for chatter, emoji, a lone number and totals', () => { for (const t of ['ok', 'thanks', '👍', '1', '12', 'Total 50', '']) expect(hasOrderContent(t)).toBe(false); }); });