文件
OmniCard/backend/test/modules/crm/lead-automation.test.ts

86 行
2.6 KiB
TypeScript

import {
LeadStageAutomationService,
evaluateLeadStagePromotion,
LeadStage,
LeadBehaviorTrigger,
} from '../../../src/modules/crm/service/lead-automation';
describe('Point 58 (P1): 出海潜客线索行为自动化阶段推进引擎', () => {
let service: LeadStageAutomationService;
beforeEach(() => {
service = new LeadStageAutomationService();
});
describe('1. evaluateLeadStagePromotion (行为触发与阶段自动跃升)', () => {
it('新访客停留时长超过 120 秒且有 AI 咨询互动时,应自动从 new 推进为 contacted', () => {
const next = evaluateLeadStagePromotion('new', {
action: 'AI_CHAT_INTERACT',
staySeconds: 150,
radarScore: 65,
});
expect(next.promoted).toBe(true);
expect(next.targetStage).toBe('contacted');
expect(next.reason).toContain('AI');
});
it('访客提交留资或雷达意向分 >= 80 时,应自动推进为 qualified', () => {
const next = evaluateLeadStagePromotion('contacted', {
action: 'FORM_SUBMITTED',
radarScore: 85,
});
expect(next.promoted).toBe(true);
expect(next.targetStage).toBe('qualified');
});
it('成功预约跨国会议时,应直接跃升至 proposal 阶段', () => {
const next = evaluateLeadStagePromotion('qualified', {
action: 'MEETING_SCHEDULED',
});
expect(next.promoted).toBe(true);
expect(next.targetStage).toBe('proposal');
});
it('Stripe 订阅付款成功时,自动推进为 closed_won 成交', () => {
const next = evaluateLeadStagePromotion('proposal', {
action: 'PAYMENT_SUCCESS',
});
expect(next.promoted).toBe(true);
expect(next.targetStage).toBe('closed_won');
});
it('已有高阶段 (如 proposal) 不应因低频次事件发生逆向降级', () => {
const next = evaluateLeadStagePromotion('proposal', {
action: 'PAGE_VIEW',
staySeconds: 10,
});
expect(next.promoted).toBe(false);
expect(next.targetStage).toBe('proposal');
});
});
describe('2. LeadStageAutomationService 状态流转执行与日志审计', () => {
it('应自动执行线索推进并返回流转记录', async () => {
const mockLead = {
id: 701,
stage: 'new' as LeadStage,
name: 'Tariq',
};
const result = await service.processBehaviorEvent(mockLead, {
action: 'FORM_SUBMITTED',
radarScore: 90,
});
expect(result.previousStage).toBe('new');
expect(result.currentStage).toBe('qualified');
expect(result.historyLog.length).toBeGreaterThan(0);
});
});
});