contacts.service.spec.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { TestBed } from '@angular/core/testing';
  2. import { Agent, Person } from './api/models';
  3. import { ContactsService } from './contacts.service';
  4. import { FmodeApi } from './api/fmode-api';
  5. import { LiveService } from './live.service';
  6. /**
  7. * 通讯录服务。
  8. *
  9. * 重点回归:
  10. * ① 同事由 `Agent.owner` **去重聚合**(同一 owner 的多个容器只出一行)
  11. * ② Tab 切换与关键字过滤叠加时结果正确
  12. * ③ 空态只在「加载完成且确实没有」时为真
  13. */
  14. describe('ContactsService', () => {
  15. let svc: ContactsService;
  16. let live: LiveService;
  17. function agent(id: string, name: string, owner?: Person, extra: Partial<Agent> = {}): Agent {
  18. return {
  19. id,
  20. name,
  21. status: 'idle',
  22. matrixReady: true,
  23. unread: 0,
  24. owner,
  25. ...extra,
  26. };
  27. }
  28. const OWNER_A: Person = { id: 'u1', name: '张总', mobile: '13800000001' };
  29. const OWNER_B: Person = { id: 'u2', name: '李工', mobile: '13800000002' };
  30. function setAgents(list: Agent[]): void {
  31. (live as unknown as { _agents: { set(v: Agent[]): void }; _state: { set(v: string): void } })._agents.set(list);
  32. (live as unknown as { _state: { set(v: string): void } })._state.set(list.length ? 'ready' : 'empty');
  33. }
  34. beforeEach(() => {
  35. TestBed.resetTestingModule();
  36. TestBed.configureTestingModule({
  37. providers: [ContactsService, LiveService, { provide: FmodeApi, useValue: { fetchAgents: () => Promise.resolve([]) } }],
  38. });
  39. svc = TestBed.inject(ContactsService);
  40. live = TestBed.inject(LiveService);
  41. });
  42. describe('同事聚合', () => {
  43. it('🔴 同一个 owner 的多个容器 → 只出一行同事', () => {
  44. setAgents([
  45. agent('a1', 'lj', OWNER_A),
  46. agent('a2', 'lj-test', OWNER_A),
  47. agent('a3', 'other', OWNER_B),
  48. ]);
  49. expect(svc.people().map((p) => p.id)).toEqual(['u1', 'u2']);
  50. expect(svc.people()[0].agents?.length).toBe(2);
  51. });
  52. it('没有 owner 的容器 → 不进同事列表', () => {
  53. setAgents([agent('a1', 'lj')]);
  54. expect(svc.people().length).toBe(0);
  55. });
  56. it('counts 正确(ai / people / all)', () => {
  57. setAgents([
  58. agent('a1', 'lj', OWNER_A),
  59. agent('a2', 'lj-test', OWNER_A),
  60. agent('a3', 'x'),
  61. ]);
  62. const c = svc.counts();
  63. expect(c.ai).toBe(3);
  64. expect(c.people).toBe(1);
  65. expect(c.all).toBe(4); // 3 个 AI + 1 个同事
  66. });
  67. });
  68. describe('Tab 与过滤', () => {
  69. beforeEach(() => {
  70. setAgents([
  71. agent('a1', 'lj', OWNER_A, { specialty: '前端' }),
  72. agent('a2', 'lj-test', OWNER_A, { specialty: '后端' }),
  73. agent('a3', 'orphan'),
  74. ]);
  75. });
  76. it('tab=people → 不显示 AI', () => {
  77. svc.setTab('people');
  78. expect(svc.visibleAgents().length).toBe(0);
  79. expect(svc.visiblePeople().length).toBe(1);
  80. });
  81. it('tab=ai → 不显示同事', () => {
  82. svc.setTab('ai');
  83. expect(svc.visibleAgents().length).toBe(3);
  84. expect(svc.visiblePeople().length).toBe(0);
  85. });
  86. it('按容器名过滤', () => {
  87. svc.setTab('ai');
  88. svc.keyword.set('lj-test');
  89. expect(svc.visibleAgents().map((a) => a.id)).toEqual(['a2']);
  90. });
  91. it('🔴 按专长过滤(不只名字)', () => {
  92. svc.setTab('ai');
  93. svc.keyword.set('前端');
  94. expect(svc.visibleAgents().map((a) => a.id)).toEqual(['a1']);
  95. });
  96. it('🔴 按主人名字过滤(找「张总名下的容器」)', () => {
  97. svc.setTab('ai');
  98. svc.keyword.set('张总');
  99. expect(svc.visibleAgents().map((a) => a.id)).toEqual(['a1', 'a2']);
  100. });
  101. it('切换 Tab 会收起展开的同事', () => {
  102. svc.toggleColleague('u1');
  103. expect(svc.expandedColleague()).toBe('u1');
  104. svc.setTab('ai');
  105. expect(svc.expandedColleague()).toBeNull();
  106. });
  107. });
  108. describe('空态', () => {
  109. it('有数据 → isEmpty 为假', () => {
  110. setAgents([agent('a1', 'lj')]);
  111. expect(svc.isEmpty()).toBeFalse();
  112. });
  113. it('加载中 → isEmpty 为假(不能提前显示空态)', () => {
  114. setAgents([]);
  115. (live as unknown as { _state: { set(v: string): void } })._state.set('loading');
  116. expect(svc.isEmpty()).toBeFalse();
  117. });
  118. it('🔴 加载完成且确实为空 → isEmpty 为真', () => {
  119. setAgents([]);
  120. (live as unknown as { _state: { set(v: string): void } })._state.set('empty');
  121. expect(svc.isEmpty()).toBeTrue();
  122. });
  123. });
  124. });