Some checks failed
CI / verify (push) Has been cancelled
New /provisionPhone <storeNumber> command manages the store user's wired desk phones via the same card pattern as /provisionDect: multi-select checkbox list that doubles as the display, MACs render as AA:BB:CC:DD:EE:FF, model dropdown for add (defaults to 7841), side-by-side Add / Remove-checked actions, and every removal goes through an explicit confirm card. Adds are idempotent (MACs already registered are skipped) and bulk MAC input is supported. DECT handsets are filtered out of the display so /provisionPhone and /provisionDect coexist cleanly on the same store user without overlapping responsibilities. Refactors: - Extract MAC helpers (normalize/format/display) to src/utils/mac.js so both DECT and wired-phone flows share one implementation. dect.js re-exports for backward compat with existing consumers. - Add parseEmailArg helper; migrate /userInfo to use it. Tests: pure-logic coverage for WIRED_PHONE_MODELS, isSupportedWiredModel, filterWiredPhones (DECT/model filter), and parseEmailArg. Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
3.7 KiB
JavaScript
98 lines
3.7 KiB
JavaScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import {
|
|
parseEmailArg,
|
|
parseStoreArg,
|
|
parseStoreNumber,
|
|
storeEmail,
|
|
} from '../src/commands/helpers.js';
|
|
|
|
// parseStoreArg regressed once already: the framework's trigger.prompt is
|
|
// everything AFTER the matched command (e.g. " 792" for "/storeInfo 792"),
|
|
// but the old implementation split and took index [1], which returned
|
|
// undefined. These tests lock that behavior down.
|
|
describe('parseStoreArg', () => {
|
|
it('reads first token from trigger.prompt (DM path)', () => {
|
|
assert.equal(parseStoreArg({ prompt: ' 792' }), '792');
|
|
});
|
|
|
|
it('handles a prompt with trailing junk', () => {
|
|
assert.equal(parseStoreArg({ prompt: ' 499 extra text' }), '499');
|
|
});
|
|
|
|
it('falls back to trigger.args when prompt is empty (DM)', () => {
|
|
// In DMs the framework populates args as [command, ...positional].
|
|
assert.equal(parseStoreArg({ prompt: '', args: ['/storeInfo', '792'] }), '792');
|
|
});
|
|
|
|
it('falls back to trigger.args in mentioned group rooms', () => {
|
|
// In group rooms args[0] is the bot name; we look for the first
|
|
// token starting with '/' and take the one after it.
|
|
assert.equal(
|
|
parseStoreArg({ prompt: '', args: ['aeoCallProvisioning', '/storeInfo', '792'] }),
|
|
'792',
|
|
);
|
|
});
|
|
|
|
it('returns undefined when nothing usable is present', () => {
|
|
assert.equal(parseStoreArg({}), undefined);
|
|
assert.equal(parseStoreArg({ prompt: ' ', args: [] }), undefined);
|
|
assert.equal(parseStoreArg(null), undefined);
|
|
assert.equal(parseStoreArg(undefined), undefined);
|
|
});
|
|
});
|
|
|
|
describe('parseStoreNumber', () => {
|
|
it('accepts 1-5 digit numeric strings', () => {
|
|
assert.equal(parseStoreNumber({ prompt: ' 1' }), '1');
|
|
assert.equal(parseStoreNumber({ prompt: ' 499' }), '499');
|
|
assert.equal(parseStoreNumber({ prompt: ' 12345' }), '12345');
|
|
});
|
|
|
|
it('rejects non-numeric input', () => {
|
|
assert.equal(parseStoreNumber({ prompt: ' abc' }), null);
|
|
assert.equal(parseStoreNumber({ prompt: ' 49a' }), null);
|
|
assert.equal(parseStoreNumber({ prompt: ' 4-9' }), null);
|
|
});
|
|
|
|
it('rejects overly long numbers', () => {
|
|
assert.equal(parseStoreNumber({ prompt: ' 123456' }), null);
|
|
});
|
|
|
|
it('returns null when the arg is missing', () => {
|
|
assert.equal(parseStoreNumber({}), null);
|
|
assert.equal(parseStoreNumber({ prompt: '' }), null);
|
|
});
|
|
});
|
|
|
|
describe('storeEmail', () => {
|
|
it('zero-pads to 5 digits and appends @ae.com', () => {
|
|
assert.equal(storeEmail(499), 'ae00499@ae.com');
|
|
assert.equal(storeEmail(1), 'ae00001@ae.com');
|
|
assert.equal(storeEmail(12345), 'ae12345@ae.com');
|
|
});
|
|
|
|
it('accepts numeric-string input', () => {
|
|
assert.equal(storeEmail('42'), 'ae00042@ae.com');
|
|
});
|
|
});
|
|
|
|
describe('parseEmailArg', () => {
|
|
it('returns a lowercased email when the shape looks valid', () => {
|
|
assert.equal(parseEmailArg({ prompt: ' McQueenJ@AE.com' }), 'mcqueenj@ae.com');
|
|
assert.equal(parseEmailArg({ prompt: ' ae00499@ae.com' }), 'ae00499@ae.com');
|
|
});
|
|
|
|
it('rejects non-email input', () => {
|
|
assert.equal(parseEmailArg({ prompt: ' joe' }), null);
|
|
assert.equal(parseEmailArg({ prompt: ' joe@' }), null);
|
|
assert.equal(parseEmailArg({ prompt: ' joe@ae' }), null);
|
|
assert.equal(parseEmailArg({ prompt: ' @ae.com' }), null);
|
|
});
|
|
|
|
it('returns null when the arg is missing', () => {
|
|
assert.equal(parseEmailArg({}), null);
|
|
assert.equal(parseEmailArg({ prompt: '' }), null);
|
|
});
|
|
});
|