Files

115 lines
3.7 KiB
TypeScript

import { describe, expect, it } from 'bun:test';
import {
mergeModelOptions,
modelSearchText,
modelsFromDiscoveredPayload,
modelsFromRecord,
reconcileModelSelection,
usableModelAlias,
} from '../src/services/modelService';
describe('model discovery selection', () => {
const discovered = [
{ name: 'deepseek-chat' },
{ name: 'deepseek-reasoner' },
{ name: 'deepseek-new-model' },
];
it('selects every discovered model on the first fetch for a new connection', () => {
expect(Array.from(reconcileModelSelection(discovered, [], [], 'initial'))).toEqual([
'deepseek-chat',
'deepseek-reasoner',
'deepseek-new-model',
]);
});
it('keeps saved selections and leaves newly discovered models unchecked', () => {
expect(Array.from(reconcileModelSelection(
discovered,
[{ name: 'deepseek-chat' }],
['deepseek-chat'],
'initial',
))).toEqual(['deepseek-chat']);
});
it('preserves refresh selections, drops unavailable discoveries, and keeps configured models', () => {
expect(Array.from(reconcileModelSelection(
[{ name: 'deepseek-reasoner' }, { name: 'deepseek-new-model' }],
[{ name: 'custom-model' }],
['DEEPSEEK-REASONER', 'removed-model', 'custom-model'],
'refresh',
))).toEqual(['deepseek-reasoner', 'custom-model']);
});
it('deduplicates model names case-insensitively and keeps configured metadata', () => {
expect(mergeModelOptions(
[{ name: 'deepseek-chat' }],
[{ name: ' DEEPSEEK-CHAT ', alias: 'Chat' }],
)).toEqual([{ name: 'DEEPSEEK-CHAT', alias: 'Chat' }]);
});
it('keeps display names for search without treating them as aliases', () => {
expect(mergeModelOptions(
[{ name: 'codex-auto-review', displayName: 'Codex Auto Review' }],
[{ name: 'codex-auto-review', alias: 'review-alias' }],
)).toEqual([{
name: 'codex-auto-review',
alias: 'review-alias',
displayName: 'Codex Auto Review',
}]);
expect(modelSearchText({
name: 'codex-auto-review',
displayName: 'Codex Auto Review',
})).toContain('codex auto review');
});
});
describe('model catalog parsing', () => {
it('does not treat display names as aliases', () => {
expect(modelsFromRecord([
{
name: 'codex-auto-review',
display_name: 'Codex Auto Review',
displayName: 'Ignored Fallback',
},
{
id: 'gpt-5.6-terra',
'display-name': 'GPT-5.6 Terra',
},
])).toEqual([
{ name: 'codex-auto-review', displayName: 'Codex Auto Review' },
{ name: 'gpt-5.6-terra', displayName: 'GPT-5.6 Terra' },
]);
});
it('preserves existing aliases from saved configuration, including spaced ones', () => {
expect(modelsFromRecord([
{ name: 'codex-auto-review', alias: 'Codex Auto Review' },
{ name: 'gpt-test', alias: 'review-alias' },
])).toEqual([
{ name: 'codex-auto-review', alias: 'Codex Auto Review' },
{ name: 'gpt-test', alias: 'review-alias' },
]);
});
it('rejects whitespace in newly entered aliases', () => {
expect(usableModelAlias('Codex Auto Review')).toBe('');
expect(usableModelAlias(' review-alias ')).toBe('review-alias');
expect(usableModelAlias('')).toBe('');
});
it('does not import spaced display names as aliases when discovering models', () => {
expect(modelsFromDiscoveredPayload({
data: [
{ id: 'codex-auto-review', display_name: 'Codex Auto Review' },
{ id: 'gpt-test', alias: 'Codex Auto Review' },
{ id: 'gpt-alias', alias: 'review-alias' },
],
})).toEqual([
{ name: 'codex-auto-review', displayName: 'Codex Auto Review' },
{ name: 'gpt-test' },
{ name: 'gpt-alias', alias: 'review-alias' },
]);
});
});