133 lines
6.6 KiB
TypeScript
133 lines
6.6 KiB
TypeScript
import { TestBed } from '@angular/core/testing';
|
|
import { provideHttpClient } from '@angular/common/http';
|
|
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
|
import { ModelSettingsComponent } from './model-settings.component';
|
|
import { CapabilitySettingsComponent } from './capability-settings.component';
|
|
|
|
describe('持久化模型与功能设置', () => {
|
|
let http: HttpTestingController;
|
|
const config = { base_url: 'https://example.test/v1', model: 'mimo-v2.6-flash',
|
|
api_key_configured: true, timeout_seconds: 300, max_retries: 5, retry_interval_seconds: 10, reasoning_effort: 'high',
|
|
model_presets: ['gpt-5.6-luna', 'gpt-6-luna', 'mimo-v2.6-flash', 'mimo-v2.6-pro'], env_path: '/app/.env' };
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()] });
|
|
http = TestBed.inject(HttpTestingController);
|
|
});
|
|
afterEach(() => http.verify());
|
|
|
|
it('加载配置后保留密钥,保存新模型且不发送空密钥', () => {
|
|
const fixture = TestBed.createComponent(ModelSettingsComponent);
|
|
fixture.detectChanges();
|
|
http.expectOne('/api/system/model-settings').flush(config);
|
|
const component = fixture.componentInstance;
|
|
expect(component.apiKey).toBe('');
|
|
expect(component.keyConfigured()).toBeTrue();
|
|
component.model = 'another-model';
|
|
component.save();
|
|
const request = http.expectOne('/api/system/model-settings');
|
|
expect(request.request.method).toBe('POST');
|
|
expect(request.request.body.model).toBe('another-model');
|
|
expect(request.request.body.reasoning_effort).toBe('high');
|
|
expect(request.request.body.timeout_seconds).toBe(300);
|
|
expect(request.request.body.max_retries).toBe(5);
|
|
expect(request.request.body.retry_interval_seconds).toBe(10);
|
|
expect(request.request.body.api_key).toBeUndefined();
|
|
request.flush({ ...config, model: 'another-model' });
|
|
expect(component.busy()).toBeNull();
|
|
expect(component.message()).toContain('保存');
|
|
});
|
|
|
|
it('预设按钮填入名称,自定义模型与 max 可以保存并重新加载', async () => {
|
|
const fixture = TestBed.createComponent(ModelSettingsComponent);
|
|
fixture.detectChanges();
|
|
http.expectOne('/api/system/model-settings').flush(config);
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
const root: HTMLElement = fixture.nativeElement;
|
|
const presets = root.querySelectorAll<HTMLButtonElement>('.model-presets button');
|
|
expect(Array.from(presets, button => button.textContent?.trim())).toEqual([
|
|
'gpt-5.6-luna', 'gpt-6-luna', 'mimo-v2.6-flash', 'mimo-v2.6-pro'
|
|
]);
|
|
presets[0].click();
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
const input = root.querySelector<HTMLInputElement>('#model-name')!;
|
|
expect(input.value).toBe('gpt-5.6-luna');
|
|
expect(presets[0].getAttribute('aria-pressed')).toBe('true');
|
|
presets[1].click();
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
expect(input.value).toBe('gpt-6-luna');
|
|
presets[3].click();
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
expect(input.value).toBe('mimo-v2.6-pro');
|
|
expect(input.getAttribute('list')).toBeNull();
|
|
expect(input.autocomplete).toBe('off');
|
|
input.value = 'custom/model-v2';
|
|
input.dispatchEvent(new Event('input'));
|
|
const reasoning = root.querySelector<HTMLSelectElement>('#model-reasoning')!;
|
|
reasoning.value = 'max';
|
|
reasoning.dispatchEvent(new Event('change'));
|
|
fixture.detectChanges();
|
|
await fixture.whenStable();
|
|
expect(presets[0].getAttribute('aria-pressed')).toBe('false');
|
|
root.querySelector<HTMLFormElement>('form')!.dispatchEvent(new Event('submit', { cancelable: true }));
|
|
const request = http.expectOne('/api/system/model-settings');
|
|
expect(request.request.body.model).toBe('custom/model-v2');
|
|
expect(request.request.body.reasoning_effort).toBe('max');
|
|
const saved = { ...config, model: 'custom/model-v2', reasoning_effort: 'max' };
|
|
request.flush(saved);
|
|
fixture.destroy();
|
|
const reopened = TestBed.createComponent(ModelSettingsComponent);
|
|
reopened.detectChanges();
|
|
http.expectOne('/api/system/model-settings').flush(saved);
|
|
reopened.detectChanges();
|
|
await reopened.whenStable();
|
|
expect(reopened.nativeElement.querySelector('#model-name').value).toBe('custom/model-v2');
|
|
expect(reopened.nativeElement.querySelector('#model-reasoning').value).toBe('max');
|
|
});
|
|
|
|
it('连接测试使用当前输入而不写入保存接口', () => {
|
|
const fixture = TestBed.createComponent(ModelSettingsComponent);
|
|
fixture.detectChanges();
|
|
http.expectOne('/api/system/model-settings').flush(config);
|
|
fixture.componentInstance.test();
|
|
const request = http.expectOne('/api/system/model-settings/test');
|
|
expect(request.request.body.model).toBe('mimo-v2.6-flash');
|
|
request.flush({ message: 'Responses 连接测试成功' });
|
|
http.expectNone('/api/system/model-settings');
|
|
expect(fixture.componentInstance.message()).toContain('成功');
|
|
});
|
|
|
|
it('加载失败时保持功能开关不可保存,避免覆盖现有设置', () => {
|
|
const fixture = TestBed.createComponent(CapabilitySettingsComponent);
|
|
fixture.detectChanges();
|
|
http.expectOne('/api/system/capability-settings').flush({}, { status: 500, statusText: 'Error' });
|
|
expect(fixture.componentInstance.error()).toContain('加载失败');
|
|
fixture.componentInstance.save();
|
|
http.expectNone('/api/system/capability-settings');
|
|
});
|
|
|
|
it('录屏与视频分析独立保存,重新打开后保留各自状态', () => {
|
|
const capabilities = { video_enabled: true, recording_enabled: false, outputter_enabled: true, step_summarizer_enabled: false };
|
|
const fixture = TestBed.createComponent(CapabilitySettingsComponent);
|
|
fixture.detectChanges();
|
|
http.expectOne('/api/system/capability-settings').flush(capabilities);
|
|
fixture.componentInstance.config.video_enabled = false;
|
|
fixture.componentInstance.config.recording_enabled = true;
|
|
fixture.componentInstance.save();
|
|
const request = http.expectOne('/api/system/capability-settings');
|
|
expect(request.request.body.video_enabled).toBeFalse();
|
|
expect(request.request.body.recording_enabled).toBeTrue();
|
|
const saved = { ...capabilities, video_enabled: false, recording_enabled: true };
|
|
request.flush(saved);
|
|
fixture.destroy();
|
|
const reopened = TestBed.createComponent(CapabilitySettingsComponent);
|
|
reopened.detectChanges();
|
|
http.expectOne('/api/system/capability-settings').flush(saved);
|
|
expect(reopened.componentInstance.config.video_enabled).toBeFalse();
|
|
expect(reopened.componentInstance.config.recording_enabled).toBeTrue();
|
|
});
|
|
});
|