120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { BackendHttpError } from '@/common/adapter/httpBridge';
|
|
import { createTeamConfigOptionsLoader } from '@/renderer/pages/team/hooks/teamConfigOptions';
|
|
|
|
describe('createTeamConfigOptionsLoader', () => {
|
|
const configOptionsResponse = {
|
|
config_options: [
|
|
{
|
|
id: 'model',
|
|
category: 'model',
|
|
type: 'select',
|
|
current_value: 'gpt-5.5',
|
|
options: [{ value: 'gpt-5.5', label: 'GPT 5.5' }],
|
|
},
|
|
],
|
|
};
|
|
|
|
it('loads a conversation config snapshot without warming the whole team', async () => {
|
|
const calls: string[] = [];
|
|
const warmupSession = vi.fn(() => {
|
|
calls.push('warmup');
|
|
return Promise.resolve();
|
|
});
|
|
const getConfigOptions = vi.fn(async (team_id: string, conversation_id: string) => {
|
|
calls.push(`get:${team_id}:${conversation_id}`);
|
|
return configOptionsResponse;
|
|
});
|
|
const loader = createTeamConfigOptionsLoader({
|
|
team_id: 'team-1',
|
|
warmupSession,
|
|
getConfigOptions,
|
|
});
|
|
|
|
const result = await loader('conversation-1');
|
|
|
|
expect(calls).toEqual(['get:team-1:conversation-1']);
|
|
expect(warmupSession).not.toHaveBeenCalled();
|
|
expect(result?.[0]?.current_value).toBe('gpt-5.5');
|
|
});
|
|
|
|
it('can await warmup explicitly when callers need the whole team ready', async () => {
|
|
const calls: string[] = [];
|
|
const warmupSession = vi.fn(async () => {
|
|
calls.push('warmup');
|
|
});
|
|
const getConfigOptions = vi.fn(async (team_id: string, conversation_id: string) => {
|
|
calls.push(`get:${team_id}:${conversation_id}`);
|
|
return configOptionsResponse;
|
|
});
|
|
const loader = createTeamConfigOptionsLoader({
|
|
team_id: 'team-1',
|
|
warmupSession,
|
|
getConfigOptions,
|
|
});
|
|
|
|
await loader.warmup();
|
|
const result = await loader.load('conversation-1');
|
|
|
|
expect(calls).toEqual(['warmup', 'get:team-1:conversation-1']);
|
|
expect(result?.[0]?.current_value).toBe('gpt-5.5');
|
|
});
|
|
|
|
it('surfaces team runtime-not-ready without retrying config loads', async () => {
|
|
vi.useFakeTimers();
|
|
try {
|
|
const runtimeNotReady = new BackendHttpError({
|
|
method: 'GET',
|
|
path: '/api/teams/team-1/conversations/conversation-1/config-options',
|
|
status: 409,
|
|
body: {
|
|
success: false,
|
|
error: 'Team agent runtime is not ready for conversation: conversation-1',
|
|
code: 'TEAM_RUNTIME_NOT_READY',
|
|
details: { conversation_id: 'conversation-1' },
|
|
},
|
|
});
|
|
const warmupSession = vi.fn(async () => {});
|
|
const getConfigOptions = vi.fn().mockRejectedValue(runtimeNotReady);
|
|
const loader = createTeamConfigOptionsLoader({
|
|
team_id: 'team-1',
|
|
warmupSession,
|
|
getConfigOptions,
|
|
});
|
|
|
|
const resultPromise = loader.load('conversation-1');
|
|
const expectation = expect(resultPromise).rejects.toBe(runtimeNotReady);
|
|
|
|
await vi.advanceTimersByTimeAsync(31_000);
|
|
|
|
await expectation;
|
|
expect(getConfigOptions).toHaveBeenCalledTimes(1);
|
|
expect(warmupSession).not.toHaveBeenCalled();
|
|
} finally {
|
|
vi.useRealTimers();
|
|
}
|
|
});
|
|
|
|
it('does not retry ordinary config load failures', async () => {
|
|
const error = new BackendHttpError({
|
|
method: 'GET',
|
|
path: '/api/teams/team-1/conversations/conversation-1/config-options',
|
|
status: 400,
|
|
body: {
|
|
success: false,
|
|
error: 'bad request',
|
|
code: 'BAD_REQUEST',
|
|
},
|
|
});
|
|
const getConfigOptions = vi.fn().mockRejectedValue(error);
|
|
const loader = createTeamConfigOptionsLoader({
|
|
team_id: 'team-1',
|
|
warmupSession: vi.fn(async () => {}),
|
|
getConfigOptions,
|
|
});
|
|
|
|
await expect(loader.load('conversation-1')).rejects.toBe(error);
|
|
expect(getConfigOptions).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|