feat: release 1.1.0 with responsive task control

This commit is contained in:
chenmingxuan committed 2026-09-24 03:31:17 +08:00
1 parent 057f0c3050
commit bfcd828fa8
37 files changed
+1601 -151

No files matched your search

@@ -0,0 +1,80 @@
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<string | null>(null),
runningSessionId: signal<string | null>(null),
agentStatus: signal('idle'),
sessions: signal<any[]>([])
};
const http = jasmine.createSpyObj<HttpClient>('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<void>(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<void>(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<void>(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('设置');
});
});