| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- /*
- 单元测试脚本说明:
- 该文件对应 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' });
- });
- });
|