quality-rules.unit.spec.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /*
  2. 单元测试脚本说明:
  3. 该文件对应 project/backend/tests/quality-rules.spec.ts。
  4. 运行脚本 run_unit_tests.ps1 会调用后端 Jest 环境执行正式测试文件。
  5. */
  6. import {
  7. allowedNextStatuses,
  8. canReadTicket,
  9. canTransition,
  10. isSlaOverdue,
  11. resolveDeadline,
  12. slaStatus,
  13. validateAttachment
  14. } from '../../project/backend/src/services/quality-rules';
  15. describe('unit: ticket status rules', () => {
  16. it('allows pending ticket to enter processing', () => {
  17. expect(canTransition('pending', 'processing')).toBe(true);
  18. });
  19. it('rejects pending ticket resolved directly', () => {
  20. expect(canTransition('pending', 'resolved')).toBe(false);
  21. });
  22. it('returns immutable next status list', () => {
  23. const next = allowedNextStatuses('pending');
  24. next.push('closed');
  25. expect(allowedNextStatuses('pending')).toEqual(['processing', 'cancelled']);
  26. });
  27. });
  28. describe('unit: permission rules', () => {
  29. const acl = {
  30. creatorId: 'customer-1',
  31. ownerId: 'engineer-1',
  32. companyUserIds: ['customer-1', 'customer-2']
  33. };
  34. it('allows admin to read every ticket', () => {
  35. expect(canReadTicket('admin-1', 'admin', acl)).toBe(true);
  36. });
  37. it('rejects unrelated customer', () => {
  38. expect(canReadTicket('customer-3', 'customer', acl)).toBe(false);
  39. });
  40. });
  41. describe('unit: SLA rules', () => {
  42. const createdAt = new Date('2026-06-01T00:00:00.000Z');
  43. it('calculates urgent deadline within 4 hours', () => {
  44. expect(resolveDeadline({ priority: 'urgent', createdAt }).toISOString()).toBe('2026-06-01T04:00:00.000Z');
  45. });
  46. it('marks ticket warning in last 20 percent time window', () => {
  47. expect(slaStatus({ priority: 'high', createdAt, now: new Date('2026-06-01T20:00:00.000Z') })).toBe('warning');
  48. });
  49. it('marks unresolved ticket overdue after deadline', () => {
  50. expect(isSlaOverdue({ priority: 'urgent', createdAt, now: new Date('2026-06-01T04:01:00.000Z') })).toBe(true);
  51. });
  52. });
  53. describe('unit: attachment validation rules', () => {
  54. it('accepts png attachment under 10MB', () => {
  55. expect(validateAttachment({ name: 'error.png', sizeMb: 2 }).valid).toBe(true);
  56. });
  57. it('rejects unsupported executable file', () => {
  58. expect(validateAttachment({ name: 'tool.exe', sizeMb: 1 })).toEqual({ valid: false, reason: 'UNSUPPORTED_TYPE' });
  59. });
  60. });