const { parseStoreCommand, getCommandText } = require('../bot/handlers'); const { STORE_MODES } = require('../constants'); // The two phrase regexes registered in server.js, kept in lock-step here so // the test suite documents the routing contract (and fails fast if either // drifts). const HELP_PHRASE = /^(?:\S+\s+)?help\b/i; const ST_PHRASE = /^(?:\S+\s+)?st\b/i; describe('parseStoreCommand', () => { it('defaults to INFO mode for a bare st ', () => { expect(parseStoreCommand('st 305')).toEqual({ storeNumber: '305', mode: STORE_MODES.INFO, }); }); it('recognises the network subcommand', () => { expect(parseStoreCommand('st 305 network')).toEqual({ storeNumber: '305', mode: STORE_MODES.NETWORK, }); }); it('recognises the pos subcommand', () => { expect(parseStoreCommand('st 305 pos')).toEqual({ storeNumber: '305', mode: STORE_MODES.POS, }); }); it('treats ios and iphone as the same mode', () => { expect(parseStoreCommand('st 305 ios').mode).toBe(STORE_MODES.IOS); expect(parseStoreCommand('st 305 iphone').mode).toBe(STORE_MODES.IOS); }); it('recognises the phone and av placeholder subcommands', () => { expect(parseStoreCommand('st 305 phone').mode).toBe(STORE_MODES.PHONE); expect(parseStoreCommand('st 305 av').mode).toBe(STORE_MODES.AV); }); it('does not match "phone" inside another word', () => { // "phones" should not pick up PHONE mode — must be a whole word. expect(parseStoreCommand('st 305 phones').mode).toBe(STORE_MODES.INFO); }); it('returns null storeNumber when no digits are present', () => { expect(parseStoreCommand('st')).toEqual({ storeNumber: null, mode: null }); expect(parseStoreCommand('st network')).toEqual({ storeNumber: null, mode: null }); }); }); describe('getCommandText', () => { it('prefers trigger.command + trigger.prompt (framework-cleaned text)', () => { // What the framework gives us in a group space after stripping the bot // mention: command is the matched phrase, prompt is everything after. const trigger = { command: 'st', prompt: ' 782 network', message: { text: 'devStoreHealthAnalyzer st 782 network' }, }; expect(getCommandText(trigger)).toBe('st 782 network'); }); it('handles a DM message (no bot-name prefix) the same way', () => { const trigger = { command: 'st', prompt: ' 782 pos', message: { text: 'st 782 pos' }, }; expect(getCommandText(trigger)).toBe('st 782 pos'); }); it('falls back to message.text when command/prompt are absent', () => { expect(getCommandText({ message: { text: 'st 305' } })).toBe('st 305'); }); it('returns an empty string for an empty trigger', () => { expect(getCommandText({})).toBe(''); expect(getCommandText(null)).toBe(''); }); }); describe('route phrase regexes', () => { // Direct-message form (no bot name). it('matches bare DM commands', () => { expect(ST_PHRASE.test('st 782')).toBe(true); expect(ST_PHRASE.test('st 782 network')).toBe(true); expect(HELP_PHRASE.test('help')).toBe(true); expect(HELP_PHRASE.test('help st')).toBe(true); }); // Group-mention form: Webex prepends "BotName " to mentioned messages. it('matches group-mention commands with a leading bot-name prefix', () => { expect(ST_PHRASE.test('devStoreHealthAnalyzer st 782')).toBe(true); expect(ST_PHRASE.test('devStoreHealthAnalyzer st 782 ios')).toBe(true); expect(HELP_PHRASE.test('devStoreHealthAnalyzer help')).toBe(true); }); // Don't trigger on similar-looking words. it('does not match unrelated words containing "st"', () => { expect(ST_PHRASE.test('stop the build')).toBe(false); expect(ST_PHRASE.test('start now')).toBe(false); expect(ST_PHRASE.test('fast 305')).toBe(false); }); // Don't trigger when the command is buried mid-sentence in a DM. it('does not match commands buried more than one word deep', () => { expect(ST_PHRASE.test('please run st 305')).toBe(false); expect(HELP_PHRASE.test('I really need help')).toBe(false); }); // Disambiguation: "BotName help st" should hit help only, not st. it('routes "help st" to help only', () => { const msg = 'devStoreHealthAnalyzer help st'; expect(HELP_PHRASE.test(msg)).toBe(true); expect(ST_PHRASE.test(msg)).toBe(false); }); });