review-rewards.component.spec.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { TestBed } from '@angular/core/testing';
  2. import { ReviewRewardsComponent } from './review-rewards.component';
  3. import { OperationsService } from '../operations.service';
  4. import { ReviewRewardPage } from '../admin.models';
  5. describe('ReviewRewardsComponent',()=>{
  6. const empty:ReviewRewardPage={items:[],total:0,page:1,pageSize:20,summary:{reviewCount:0,reviewAmount:0,historicalCount:0,exceptionCount:0}};
  7. let service:jasmine.SpyObj<OperationsService>;
  8. beforeEach(async()=>{
  9. service=jasmine.createSpyObj('OperationsService',['reviewRewards','confirmLegacyReviewRewards','correctReviewReward','payrolls']);service.reviewRewards.and.resolveTo(empty);service.confirmLegacyReviewRewards.and.resolveTo({confirmed:1,alreadyConfirmed:0});
  10. await TestBed.configureTestingModule({imports:[ReviewRewardsComponent],providers:[{provide:OperationsService,useValue:service}]}).compileComponents();
  11. });
  12. it('passes coach, store, month and status filters, resetting pagination when filters change',async()=>{
  13. const fixture=TestBed.createComponent(ReviewRewardsComponent),component=fixture.componentInstance;
  14. fixture.componentRef.setInput('filters',{month:'2026-09',coachId:10,storeId:40,search:'老师'});fixture.detectChanges();await fixture.whenStable();
  15. expect(service.reviewRewards).toHaveBeenCalledWith(component.filters,1,'');component.status.set('historical');await component.load(2);expect(service.reviewRewards).toHaveBeenCalledWith(component.filters,2,'historical');
  16. fixture.componentRef.setInput('filters',{...component.filters,month:'2026-10'});fixture.detectChanges();await fixture.whenStable();expect(service.reviewRewards).toHaveBeenCalledWith(component.filters,1,'historical');
  17. });
  18. it('shows historical evidence as zero value pending review, separately from earned totals',async()=>{
  19. service.reviewRewards.and.resolveTo({...empty,total:1,summary:{...empty.summary,historicalCount:1},items:[{objectId:'r',taskId:'t',coachId:10,coachName:'老师',studentName:'学生',courseName:'单词',storeId:40,storeName:'门店',plannedDate:'2026-08-01',completedAt:'',incomeMonth:'',amount:0,status:'historical',statusLabel:'历史待核对',exception:''}]});
  20. const fixture=TestBed.createComponent(ReviewRewardsComponent);fixture.componentRef.setInput('filters',{month:'2026-09',coachId:0,storeId:0,search:''});fixture.detectChanges();await fixture.whenStable();fixture.detectChanges();
  21. expect(fixture.nativeElement.textContent).toContain('需核对历史发放情况');expect(fixture.nativeElement.textContent).toContain('¥0.00');
  22. });
  23. it('keeps the newest response and displays read errors instead of a false zero income',async()=>{
  24. const fixture=TestBed.createComponent(ReviewRewardsComponent),component=fixture.componentInstance;component.filters={month:'2026-09',coachId:0,storeId:0,search:''};
  25. let resolveOld!:(value:ReviewRewardPage)=>void;service.reviewRewards.and.returnValues(new Promise(resolve=>resolveOld=resolve),Promise.resolve({...empty,total:2}));
  26. const old=component.load();await component.load();resolveOld({...empty,total:1});await old;expect(component.data()?.total).toBe(2);
  27. service.reviewRewards.and.rejectWith(new Error('服务不可用'));await component.load();expect(component.error()).toBe('服务不可用');expect(component.data()).toBeNull();
  28. });
  29. it('clears record type only for an explicit reset', async()=>{const fixture=TestBed.createComponent(ReviewRewardsComponent),component=fixture.componentInstance;component.filters={month:'2026-09',coachId:0,storeId:0,search:''};component.status.set('historical');fixture.componentRef.setInput('filters',{...component.filters,resetRevision:1});fixture.detectChanges();await fixture.whenStable();expect(component.status()).toBe('');});
  30. it('requires manager review and a reason before confirming selected historical evidence',async()=>{
  31. const fixture=TestBed.createComponent(ReviewRewardsComponent),component=fixture.componentInstance;component.filters={month:'2026-09',coachId:0,storeId:0,search:''};
  32. component.toggleSelection('reward-1',true);component.confirmReason.set('已核对未发放');await component.confirmSelected();expect(service.confirmLegacyReviewRewards).not.toHaveBeenCalled();
  33. component.canManage=true;await component.confirmSelected();expect(service.confirmLegacyReviewRewards).toHaveBeenCalledWith(['reward-1'],'已核对未发放');expect(component.selectedIds()).toEqual([]);
  34. });
  35. it('requires a reviewed correction reason and a versioned draft for paid evidence',async()=>{
  36. const component=TestBed.createComponent(ReviewRewardsComponent).componentInstance;component.filters={month:'2026-10',coachId:0,storeId:0,search:''};
  37. const row:any={objectId:'reward-1',canCorrect:true,batchStatus:'paid',amount:1};
  38. await component.openCorrection(row);expect(component.correction()).toBeNull();
  39. component.canManage=true;service.payrolls.and.resolveTo({items:[{objectId:'draft',month:'2026-11',status:'draft',version:4}],total:1} as any);
  40. await component.openCorrection(row);component.correctionReason.set('核对真实完成时间');await component.saveCorrection();expect(service.correctReviewReward).not.toHaveBeenCalled();
  41. component.correctionBatch.set('draft');service.correctReviewReward.and.resolveTo({});await component.saveCorrection();
  42. expect(service.correctReviewReward).toHaveBeenCalledWith('reward-1','核对真实完成时间','draft',4);expect(component.correction()).toBeNull();
  43. });
  44. });