145 lines
5.6 KiB
TypeScript
145 lines
5.6 KiB
TypeScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
automationUsesAdvanced,
|
|
matchFormFieldCondition,
|
|
splitAutomationBranches,
|
|
planAutomationActions,
|
|
splitFormAnswer,
|
|
type AutomationStep,
|
|
} from '@mento/shared';
|
|
import {
|
|
formatFormAnswers,
|
|
pickRoundRobin,
|
|
renderAutomationTemplate,
|
|
} from '../src/automations/automation-engine.util';
|
|
|
|
const KEY = 'coop_type';
|
|
const answers = (raw: string): Record<string, string> => ({ [KEY]: raw });
|
|
|
|
function cond(id: string, value: string): AutomationStep {
|
|
return {
|
|
id,
|
|
kind: 'condition',
|
|
conditionField: 'form_field',
|
|
conditionKey: KEY,
|
|
conditionOp: 'contains',
|
|
conditionValue: value,
|
|
};
|
|
}
|
|
|
|
function act(id: string): AutomationStep {
|
|
return { id, kind: 'action', action: 'create_activity' };
|
|
}
|
|
|
|
const BSJ: AutomationStep[] = [
|
|
cond('c1', 'بنکداری'),
|
|
act('a1'),
|
|
cond('c2', 'آنلاین شاپ'),
|
|
act('a2'),
|
|
cond('c3', 'ویترین نقره'),
|
|
act('a3'),
|
|
];
|
|
|
|
function run(steps: AutomationStep[], raw: string, mode: 'branches' | 'stop' = 'branches') {
|
|
const values = answers(raw);
|
|
return planAutomationActions(steps, mode, (s) =>
|
|
matchFormFieldCondition(s.conditionOp, values[s.conditionKey ?? ''], s.conditionValue),
|
|
).map((s) => s.id);
|
|
}
|
|
|
|
describe('اتوماسیون شاخهای فرم', () => {
|
|
it('چندانتخابی را میشکند', () => {
|
|
assert.deepEqual(splitFormAnswer('بنکداری, آنلاین شاپ'), ['بنکداری', 'آنلاین شاپ']);
|
|
assert.deepEqual(splitFormAnswer('الف، ب'), ['الف', 'ب']);
|
|
assert.deepEqual(splitFormAnswer(''), []);
|
|
assert.deepEqual(splitFormAnswer(undefined), []);
|
|
});
|
|
|
|
it('عملگرهای فیلد فرم', () => {
|
|
assert.equal(matchFormFieldCondition('contains', 'بنکداری, ویترین نقره', 'ویترین نقره'), true);
|
|
assert.equal(matchFormFieldCondition('contains', 'بنکداری', 'آنلاین شاپ'), false);
|
|
assert.equal(matchFormFieldCondition('not_contains', 'بنکداری', 'آنلاین شاپ'), true);
|
|
assert.equal(matchFormFieldCondition('eq', 'بنکداری', 'بنکداری'), true);
|
|
assert.equal(matchFormFieldCondition('eq', 'بنکداری, آنلاین شاپ', 'بنکداری'), false);
|
|
assert.equal(matchFormFieldCondition('is_set', 'x', ''), true);
|
|
assert.equal(matchFormFieldCondition('is_empty', '', ''), true);
|
|
});
|
|
|
|
it('هر گزینه فقط شاخهٔ خودش را اجرا میکند', () => {
|
|
assert.deepEqual(run(BSJ, 'بنکداری'), ['a1']);
|
|
assert.deepEqual(run(BSJ, 'آنلاین شاپ'), ['a2']);
|
|
assert.deepEqual(run(BSJ, 'ویترین نقره'), ['a3']);
|
|
});
|
|
|
|
it('چند تیک = چند فعالیت', () => {
|
|
assert.deepEqual(run(BSJ, 'بنکداری, ویترین نقره'), ['a1', 'a3']);
|
|
assert.deepEqual(run(BSJ, 'بنکداری, آنلاین شاپ, ویترین نقره'), ['a1', 'a2', 'a3']);
|
|
assert.deepEqual(run(BSJ, ''), []);
|
|
});
|
|
|
|
it('شرطهای پشتسرهم با «و» ترکیب میشوند', () => {
|
|
const steps = [cond('c1', 'بنکداری'), cond('c2', 'آنلاین شاپ'), act('a1'), act('a2')];
|
|
assert.deepEqual(run(steps, 'بنکداری'), []);
|
|
assert.deepEqual(run(steps, 'بنکداری, آنلاین شاپ'), ['a1', 'a2']);
|
|
});
|
|
|
|
it('حالت stop رفتار قدیمی را حفظ میکند', () => {
|
|
assert.deepEqual(run(BSJ, 'آنلاین شاپ', 'stop'), []);
|
|
assert.deepEqual(run(BSJ, 'بنکداری, آنلاین شاپ, ویترین نقره', 'stop'), ['a1', 'a2', 'a3']);
|
|
assert.deepEqual(
|
|
planAutomationActions([act('a0')], undefined, () => false).map((s) => s.id),
|
|
['a0'],
|
|
);
|
|
});
|
|
|
|
it('تفکیک شاخهها برای نمایش موازی', () => {
|
|
assert.deepEqual(splitAutomationBranches(BSJ), {
|
|
prefixEnd: 0,
|
|
branches: [
|
|
{ start: 0, end: 2 },
|
|
{ start: 2, end: 4 },
|
|
{ start: 4, end: 6 },
|
|
],
|
|
});
|
|
const mixed = [act('a0'), cond('c1', 'x'), cond('c2', 'y'), act('a1')];
|
|
assert.deepEqual(splitAutomationBranches(mixed), {
|
|
prefixEnd: 1,
|
|
branches: [{ start: 1, end: 4 }],
|
|
});
|
|
assert.deepEqual(splitAutomationBranches([act('a0')]), { prefixEnd: 1, branches: [] });
|
|
});
|
|
|
|
it('تشخیص نیاز به اتوماسیون حرفهای', () => {
|
|
assert.equal(automationUsesAdvanced([act('a0')], 'stop'), false);
|
|
assert.equal(automationUsesAdvanced([act('a0')], 'branches'), true);
|
|
assert.equal(automationUsesAdvanced(BSJ, 'stop'), true);
|
|
assert.equal(
|
|
automationUsesAdvanced([{ ...act('a0'), assignMode: 'team_round_robin' }], undefined),
|
|
true,
|
|
);
|
|
});
|
|
|
|
it('تقسیم نوبتی مساوی و پایدار', () => {
|
|
const team = ['u3', 'u1', 'u2'];
|
|
const picks = [1, 2, 3, 4, 5, 6].map((n) => pickRoundRobin(team, n));
|
|
assert.deepEqual(picks, ['u1', 'u2', 'u3', 'u1', 'u2', 'u3']);
|
|
assert.equal(pickRoundRobin([], 1), null);
|
|
assert.equal(pickRoundRobin(['u1', 'u1'], 2), 'u1');
|
|
});
|
|
|
|
it('جایگذاری متغیرها و خلاصهٔ پاسخها', () => {
|
|
const text = renderAutomationTemplate('تماس با {{title}} ({{mobile}}) — {{field.coop_type}} از {{form}}', {
|
|
title: 'علی',
|
|
mobile: '0912',
|
|
formName: 'BSJ',
|
|
formValues: answers('بنکداری'),
|
|
});
|
|
assert.equal(text, 'تماس با علی (0912) — بنکداری از BSJ');
|
|
assert.equal(
|
|
formatFormAnswers([{ key: KEY, label: 'نوع همکاری' }], { [KEY]: 'بنکداری', extra: 'x' }),
|
|
'نوع همکاری: بنکداری\nextra: x',
|
|
);
|
|
});
|
|
});
|