import { signal } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; import { AgentService } from '../../services/agent.service'; import { SystemService } from '../../services/system.service'; import { AutomationPanelComponent } from './automation-panel.component'; describe('AutomationPanelComponent batch deletion', () => { const agent = { currentSessionId: signal(null), runningSessionId: signal(null), agentStatus: signal('idle'), sessions: signal([]) }; const http = jasmine.createSpyObj('HttpClient', ['get', 'delete']); beforeEach(async () => { (http.get.and as any).callFake((url: string) => of(url.endsWith('/preferences') ? { formats: ['docx', 'xlsx'], batch_timeout_seconds: 1800 } : [])); http.delete.and.returnValue(of({ status: 'deleted' })); http.delete.calls.reset(); await TestBed.configureTestingModule({ imports: [AutomationPanelComponent], providers: [ { provide: AgentService, useValue: agent }, { provide: SystemService, useValue: { connectedDevices: signal([]) } }, { provide: HttpClient, useValue: http } ] }).compileComponents(); }); it('confirms deletion and removes the batch from the visible list', async () => { const fixture = TestBed.createComponent(AutomationPanelComponent); fixture.componentInstance.tab.set('batches'); await new Promise(resolve => setTimeout(resolve, 0)); fixture.componentInstance.batches.set([ { id: 'batch-1', name: '批量冒烟', status: 'completed', created_at: 100 } ]); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('[aria-label="删除批次:批量冒烟"]')).not.toBeNull(); spyOn(window, 'confirm').and.returnValue(true); const button = fixture.nativeElement.querySelector('.delete-batch') as HTMLButtonElement; button.click(); await new Promise(resolve => setTimeout(resolve, 0)); fixture.detectChanges(); expect(http.delete).toHaveBeenCalledWith('/api/automation/batches/batch-1'); expect(fixture.componentInstance.batches()).toEqual([]); }); it('keeps a running batch protected from the delete control', async () => { const fixture = TestBed.createComponent(AutomationPanelComponent); fixture.componentInstance.tab.set('batches'); await new Promise(resolve => setTimeout(resolve, 0)); fixture.componentInstance.batches.set([ { id: 'batch-2', name: '进行中', status: 'running', created_at: 100 } ]); fixture.detectChanges(); expect((fixture.nativeElement.querySelector('.delete-batch') as HTMLButtonElement).disabled).toBeTrue(); }); it('shows the failure reason and renders Chinese report structure with line breaks', () => { const fixture = TestBed.createComponent(AutomationPanelComponent); fixture.detectChanges(); fixture.componentInstance.report.set({ id: 'task-1', name: '系统设置检查', status: 'failed', verdict: '未验证', error: '模型连续 3 次未提供可执行工具调用', goal: '查看设置', expected: '', content: '## 结果\n第一行\n第二行\n\n| 项目 | 状态 |\n| --- | --- |\n| 设置 | 未验证 |' }); fixture.detectChanges(); const root = fixture.nativeElement as HTMLElement; expect(root.querySelector('.report-error')?.textContent).toContain('连续 3 次'); expect(root.querySelector('.report-body h2')?.textContent).toBe('结果'); expect(root.querySelector('.report-body')?.textContent).toContain('第一行'); expect(root.querySelector('.report-body')?.textContent).toContain('第二行'); expect(root.querySelector('.report-body table td')?.textContent).toBe('设置'); }); });