Wire the order parser to the WhatsApp bot. A known user forwards an order, ends it with Done, picks a shop, confirms a summary and the order is saved.
89 lines
3.3 KiB
TypeScript
89 lines
3.3 KiB
TypeScript
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);
|
|
});
|
|
});
|