import { DING_WORKFLOW_ALLOWED_PROCESS_CODES, getDingWorkflowProjectType, isAllowedDingWorkflowProcessCode, isDingWorkflowOngoing, normalizeDingWorkflowBrand, normalizeDingWorkflowDepartment, normalizeDingWorkflowProcessCode, sourceWorkflowTimestampToIso, } from '@/lib/ding-workflow-sync' jest.mock('mssql', () => ({ __esModule: true, default: {}, })) jest.mock('@/lib/prisma', () => ({ prisma: {} })) jest.mock('@/lib/brand-center-access', () => ({ resolveBrandCenterAccessForUser: jest.fn() })) describe('ding workflow snapshot sync semantics', () => { test.each([ ['RUNNING', null, true], ['NEW', '', true], ['COMPLETED', null, false], ['TERMINATED', null, false], ['CANCELED', null, false], ['RUNNING', '2026-08-20 10:30:00', false], ['', null, false], ])('status %s and finish time %s resolves ongoing=%s', (status, finishTime, expected) => { expect(isDingWorkflowOngoing(status, finishTime)).toBe(expected) }) it('interprets upstream timestamps as Asia/Shanghai when no zone is present', () => { expect(sourceWorkflowTimestampToIso('2026-08-20 10:30:00')).toBe('2026-08-20T02:30:00.000Z') expect(sourceWorkflowTimestampToIso('2026-08-20T10:30:00Z')).toBe('2026-08-20T10:30:00.000Z') expect(sourceWorkflowTimestampToIso('invalid')).toBeNull() }) it('only accepts the two approved process types', () => { expect(DING_WORKFLOW_ALLOWED_PROCESS_CODES).toEqual([ 'PROC-3571C915-0506-4490-A91A-8AA7EA33F838', 'PROC-AE9FF3E1-A442-4E6A-85CF-0F2B86409673', ]) expect(isAllowedDingWorkflowProcessCode(' proc-3571c915-0506-4490-a91a-8aa7ea33f838 ')).toBe(true) expect(isAllowedDingWorkflowProcessCode('PROC-AE9FF3E1-A442-4E6A-85CF-0F2B86409673')).toBe(true) expect(isAllowedDingWorkflowProcessCode('PROC-OTHER')).toBe(false) expect(isAllowedDingWorkflowProcessCode(null)).toBe(false) }) it('normalizes process codes before persistence and comparison', () => { expect(normalizeDingWorkflowProcessCode(' proc-ae9ff3e1-a442-4e6a-85cf-0f2b86409673 ')) .toBe('PROC-AE9FF3E1-A442-4E6A-85CF-0F2B86409673') expect(normalizeDingWorkflowProcessCode('')).toBeNull() }) it('maps the two process codes to the dashboard task types', () => { expect(getDingWorkflowProjectType('PROC-3571C915-0506-4490-A91A-8AA7EA33F838')).toBe('美术设计流程') expect(getDingWorkflowProjectType('PROC-AE9FF3E1-A442-4E6A-85CF-0F2B86409673')).toBe('内容视频和图片拍摄') expect(getDingWorkflowProjectType('PROC-OTHER')).toBe('其他流程') }) it('normalizes approved brands and groups unmatched values as other brands', () => { expect(normalizeDingWorkflowBrand('自有品牌-亿家达')).toBe('亿家达') expect(normalizeDingWorkflowBrand('索菲亚')).toBe('索菲亚') expect(normalizeDingWorkflowBrand('新品牌')).toBe('其他品牌') expect(normalizeDingWorkflowBrand(null)).toBe('其他品牌') }) it('normalizes DingTalk department fields before grouping requester dimensions', () => { expect(normalizeDingWorkflowDepartment('["运营中心E"]')).toBe('运营中心E') expect(normalizeDingWorkflowDepartment('[{"name":"品牌中心"}]')).toBe('品牌中心') expect(normalizeDingWorkflowDepartment(['运营中心E', '运营中心E'])).toBe('运营中心E') expect(normalizeDingWorkflowDepartment('综合支持部')).toBe('综合支持部') expect(normalizeDingWorkflowDepartment(null)).toBeNull() }) })