fb130d1847
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 57s
Project CI / AI game creator shell Rust lane 2/2 (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
后台模型目录增加 codex/cc 执行模式绑定,旧目录缺省兼容 Codex AGC 客户端按模型绑定路由 Codex app-server 或 Claude Agent SDK sidecar 随包携带 Node runtime、Claude Agent SDK 与匹配平台 Claude runtime 补充模型配置、客户端选择、运行时适配、MCP 取消和定向测试 同步 AGC 模型配置规范、里程碑计划与共享决策记录
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
// @vitest-environment jsdom
|
|
import {
|
|
cleanup,
|
|
fireEvent,
|
|
render,
|
|
screen,
|
|
waitFor,
|
|
} from '@testing-library/react';
|
|
import { afterEach, expect, test, vi } from 'vitest';
|
|
|
|
import { getAgcModelCatalog, saveAgcModelCatalog } from '../api/adminApiClient';
|
|
import { AdminAgcModelsPage } from './AdminAgcModelsPage';
|
|
|
|
vi.mock('../api/adminApiClient', () => ({
|
|
getAgcModelCatalog: vi.fn(),
|
|
saveAgcModelCatalog: vi.fn(),
|
|
isAdminApiError: vi.fn(() => false),
|
|
formatAdminApiError: vi.fn(() => '保存失败'),
|
|
}));
|
|
vi.mock('../components/useAdminWriteConfirm', () => ({
|
|
useAdminWriteConfirm: () => ({
|
|
confirmWrite: async () => true,
|
|
confirmDialog: null,
|
|
}),
|
|
}));
|
|
afterEach(() => {
|
|
cleanup();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
test('edits alias and upstream model without changing the stable identifier or revision', async () => {
|
|
const catalog = {
|
|
revision: 3,
|
|
defaultModelId: 'quality',
|
|
models: [
|
|
{
|
|
id: 'quality',
|
|
alias: '高质量',
|
|
modelId: 'gpt-6-astra',
|
|
enabled: true,
|
|
agentMode: 'codex' as const,
|
|
},
|
|
],
|
|
};
|
|
vi.mocked(getAgcModelCatalog).mockResolvedValue(catalog);
|
|
vi.mocked(saveAgcModelCatalog).mockImplementation(async (_, input) => ({
|
|
...input,
|
|
revision: 4,
|
|
}));
|
|
render(<AdminAgcModelsPage token="test" onUnauthorized={vi.fn()} />);
|
|
await screen.findByDisplayValue('gpt-6-astra');
|
|
fireEvent.change(screen.getByLabelText('模型 1 别名'), {
|
|
target: { value: '精细创作' },
|
|
});
|
|
fireEvent.click(screen.getByRole('button', { name: '保存' }));
|
|
await waitFor(() =>
|
|
expect(saveAgcModelCatalog).toHaveBeenCalledWith('test', {
|
|
...catalog,
|
|
models: [{ ...catalog.models[0], alias: '精细创作' }],
|
|
}),
|
|
);
|
|
await waitFor(() => {
|
|
expect(screen.getAllByText('已保存').length).toBeGreaterThanOrEqual(2);
|
|
});
|
|
});
|
|
|
|
test('new models default to Codex and save the selected Agent mode', async () => {
|
|
const catalog = {
|
|
revision: 3,
|
|
defaultModelId: 'quality',
|
|
models: [
|
|
{
|
|
id: 'quality',
|
|
alias: '高质量',
|
|
modelId: 'gpt-6-astra',
|
|
enabled: true,
|
|
agentMode: 'codex' as const,
|
|
},
|
|
],
|
|
};
|
|
vi.mocked(getAgcModelCatalog).mockResolvedValue(catalog);
|
|
vi.mocked(saveAgcModelCatalog).mockImplementation(async (_, input) => ({
|
|
...input,
|
|
revision: 4,
|
|
}));
|
|
render(<AdminAgcModelsPage token="test" onUnauthorized={vi.fn()} />);
|
|
await screen.findByDisplayValue('gpt-6-astra');
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: '添加模型' }));
|
|
const agentMode = screen.getByLabelText('模型 2 Agent 模式');
|
|
expect((agentMode as HTMLSelectElement).value).toBe('codex');
|
|
fireEvent.change(agentMode, { target: { value: 'cc' } });
|
|
fireEvent.click(screen.getByRole('button', { name: '保存' }));
|
|
|
|
await waitFor(() => {
|
|
const calls = vi.mocked(saveAgcModelCatalog).mock.calls;
|
|
const payload = calls[calls.length - 1]?.[1];
|
|
expect(payload?.models).toHaveLength(2);
|
|
expect(payload?.models[1]).toMatchObject({
|
|
alias: '',
|
|
modelId: '',
|
|
enabled: true,
|
|
agentMode: 'cc',
|
|
});
|
|
});
|
|
});
|