import { TestBed } from '@angular/core/testing'; import { provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestResultCardComponent } from './test-result-card.component'; describe('用例测试结果卡片', () => { beforeEach(() => TestBed.configureTestingModule({providers:[provideHttpClient(), provideHttpClientTesting()]})); afterEach(() => TestBed.inject(HttpTestingController).verify()); it('显式展示不通过及原因,允许展开证据', () => { const fixture = TestBed.createComponent(TestResultCardComponent); fixture.componentRef.setInput('result', {status: 'failed', reason: '预期英文,实际为中文。', evidence: ['截图显示搜索设置']}); fixture.detectChanges(); const view: HTMLElement = fixture.nativeElement; expect(view.querySelector('[aria-label="用例测试结果"]')).not.toBeNull(); expect(view.querySelector('.prominent')?.textContent).toContain('测试不通过'); expect(view.querySelector('.reason')?.textContent).toContain('预期英文,实际为中文。'); const details = view.querySelector('details')!; expect(details.open).toBeFalse(); details.querySelector('summary')!.click(); expect(details.open).toBeTrue(); expect(details.textContent).toContain('截图显示搜索设置'); }); it('人工复验可覆盖 AI 判定,保留原始结论并提交备注', () => { const fixture = TestBed.createComponent(TestResultCardComponent); const ai = {status:'failed',reason:'AI发现不一致',evidence:['步骤 3 截图'],source:'ai'}; fixture.componentRef.setInput('result', ai); fixture.componentRef.setInput('sessionId', 'task-1'); fixture.componentRef.setInput('executionStatus','completed'); const saved = jasmine.createSpy(); fixture.componentInstance.reviewSaved.subscribe(saved); fixture.detectChanges(); fixture.nativeElement.querySelector('.review-toolbar button').click(); fixture.detectChanges(); fixture.componentInstance.note = '实际符合预期,已人工核对'; fixture.nativeElement.querySelector('.confirm-pass').click(); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('.confirm-fail').disabled).toBeTrue(); const request = TestBed.inject(HttpTestingController).expectOne('/api/automation/reports/task-1/review'); expect(request.request.method).toBe('PUT'); expect(request.request.body).toEqual({status:'passed',reason:'实际符合预期,已人工核对'}); const manual = {status:'passed',reason:'实际符合预期,已人工核对',evidence:[],source:'human',reviewed_at:100,ai_result:ai}; request.flush({id:'task-1',test_result:manual,verdict:'测试通过(人工确认)'}); fixture.componentRef.setInput('result',manual); fixture.detectChanges(); expect(saved).toHaveBeenCalled(); expect(fixture.nativeElement.textContent).toContain('人工通过'); expect(fixture.nativeElement.textContent).toContain('原 AI 结论'); expect(fixture.nativeElement.textContent).toContain('AI发现不一致'); expect(fixture.nativeElement.querySelector('.review-form')).toBeNull(); fixture.destroy(); }); it('保存失败时保留备注并允许重试,执行中不显示人工复验', () => { const fixture = TestBed.createComponent(TestResultCardComponent); fixture.componentRef.setInput('result',{status:'inconclusive',reason:'尚未验证',evidence:[]}); fixture.componentRef.setInput('sessionId','task-2'); fixture.componentRef.setInput('executionStatus','running'); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('.review-toolbar')).toBeNull(); fixture.componentRef.setInput('executionStatus','failed'); fixture.detectChanges(); fixture.nativeElement.querySelector('.review-toolbar button').click(); fixture.detectChanges(); fixture.componentInstance.note = '人工发现异常'; fixture.nativeElement.querySelector('.confirm-fail').click(); TestBed.inject(HttpTestingController).expectOne('/api/automation/reports/task-2/review').flush({detail:'报告正在打包'}, {status:409,statusText:'Conflict'}); fixture.detectChanges(); expect(fixture.componentInstance.note).toBe('人工发现异常'); expect(fixture.nativeElement.querySelector('[role="alert"]').textContent).toContain('报告正在打包'); expect(fixture.nativeElement.querySelector('.confirm-fail').disabled).toBeFalse(); fixture.destroy(); }); });