import { TestBed } from '@angular/core/testing'; import { TaskOutcomeComponent } from './task-outcome.component'; describe('任务结束说明', () => { function create(status = 'failed', error = '[web-example] FlashRunner failed: **前置受阻**\n\n- 未找到目标设备\n- 未执行删除') { const fixture = TestBed.createComponent(TaskOutcomeComponent); fixture.componentRef.setInput('status', status); fixture.componentRef.setInput('error', error); fixture.detectChanges(); return fixture; } it('默认只显示一行摘要,展开后渲染完整 Markdown,不选择外层任务', () => { const fixture = create(); const host = fixture.nativeElement as HTMLElement; host.style.width = '280px'; const details = host.querySelector('details')!; expect(details.open).toBeFalse(); expect(host.querySelector('.summary-text')!.textContent).toBe('前置受阻'); expect(host.textContent).not.toContain('FlashRunner failed'); expect(host.querySelector('button details')).toBeNull(); const select = jasmine.createSpy('外层任务选择'); host.addEventListener('click', select); host.querySelector('summary')!.click(); expect(details.open).toBeTrue(); expect(select).not.toHaveBeenCalled(); expect(host.querySelector('.body strong')!.textContent).toBe('前置受阻'); expect(host.querySelectorAll('.body li').length).toBe(2); fixture.componentRef.setInput('error', '[web-example] FlashRunner failed: **更新说明**\n\n- 已有记录'); fixture.detectChanges(); expect(host.querySelector('details')).toBe(details); expect(details.open).toBeTrue(); host.querySelector('summary')!.click(); expect(details.open).toBeFalse(); }); it('优先采用已有结论,同时保留不同的执行错误和依据', () => { const fixture = create(); fixture.componentRef.setInput('result', {status:'blocked', reason:'目标设备未绑定', evidence:['截图中仅有 **添加设备**']}); fixture.detectChanges(); const host = fixture.nativeElement as HTMLElement; expect(host.querySelector('.summary-text')!.textContent).toBe('目标设备未绑定'); expect(host.textContent).toContain('未执行删除'); expect(host.textContent).toContain('已记录依据'); expect(host.textContent).toContain('添加设备'); }); it('完成但结论阻塞也展示说明,运行中和无内容时不展示', () => { const fixture = create('running'); expect(fixture.nativeElement.querySelector('details')).toBeNull(); fixture.componentRef.setInput('status', 'completed'); fixture.componentRef.setInput('error', ''); fixture.componentRef.setInput('result', {status:'blocked',reason:'缺少预置数据',evidence:[]}); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('.summary-text').textContent).toBe('缺少预置数据'); fixture.componentRef.setInput('result', null); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('details')).toBeNull(); }); it('不重复相同说明,不执行错误正文中的 HTML 或危险链接', () => { const error = '**失败**\n\n[打开](javascript:alert(1))'; const fixture = create('failed', error); fixture.componentRef.setInput('result', {status:'blocked',reason:error,evidence:[]}); fixture.detectChanges(); const host = fixture.nativeElement as HTMLElement; expect(host.querySelectorAll('app-report-markdown').length).toBe(1); expect(host.querySelector('script')).toBeNull(); expect(host.querySelector('a[href^="javascript:"]')).toBeNull(); }); });