/* 单元测试脚本说明: 该文件对应 project/backend/tests/quality-rules.spec.ts。 运行脚本 run_unit_tests.ps1 会调用后端 Jest 环境执行正式测试文件。 */ import { allowedNextStatuses, canReadTicket, canTransition, isSlaOverdue, resolveDeadline, slaStatus, validateAttachment } from '../../project/backend/src/services/quality-rules'; describe('unit: ticket status rules', () => { it('allows pending ticket to enter processing', () => { expect(canTransition('pending', 'processing')).toBe(true); }); it('rejects pending ticket resolved directly', () => { expect(canTransition('pending', 'resolved')).toBe(false); }); it('returns immutable next status list', () => { const next = allowedNextStatuses('pending'); next.push('closed'); expect(allowedNextStatuses('pending')).toEqual(['processing', 'cancelled']); }); }); describe('unit: permission rules', () => { const acl = { creatorId: 'customer-1', ownerId: 'engineer-1', companyUserIds: ['customer-1', 'customer-2'] }; it('allows admin to read every ticket', () => { expect(canReadTicket('admin-1', 'admin', acl)).toBe(true); }); it('rejects unrelated customer', () => { expect(canReadTicket('customer-3', 'customer', acl)).toBe(false); }); }); describe('unit: SLA rules', () => { const createdAt = new Date('2026-06-01T00:00:00.000Z'); it('calculates urgent deadline within 4 hours', () => { expect(resolveDeadline({ priority: 'urgent', createdAt }).toISOString()).toBe('2026-06-01T04:00:00.000Z'); }); it('marks ticket warning in last 20 percent time window', () => { expect(slaStatus({ priority: 'high', createdAt, now: new Date('2026-06-01T20:00:00.000Z') })).toBe('warning'); }); it('marks unresolved ticket overdue after deadline', () => { expect(isSlaOverdue({ priority: 'urgent', createdAt, now: new Date('2026-06-01T04:01:00.000Z') })).toBe(true); }); }); describe('unit: attachment validation rules', () => { it('accepts png attachment under 10MB', () => { expect(validateAttachment({ name: 'error.png', sizeMb: 2 }).valid).toBe(true); }); it('rejects unsupported executable file', () => { expect(validateAttachment({ name: 'tool.exe', sizeMb: 1 })).toEqual({ valid: false, reason: 'UNSUPPORTED_TYPE' }); }); });