Files
CRM_Montzar/apps/api/test/automation-branches.test.ts
T

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',
);
});
});