返回 oh-my-ppt
model-list.test.ts
根目录 / tests / unit / config / model-list.test.ts
1 import { describe, expect, it } from 'vitest'
2 import {
3 buildModelListRequest,
4 parseModelListResponse
5 } from '../../../src/main/config/model-list'
6
7 describe('buildModelListRequest', () => {
8 it('openai:默认官方地址,Bearer 认证', () => {
9 const spec = buildModelListRequest('openai', '', 'sk-test')
10 expect(spec.url).toBe('https://api.openai.com/v1/models')
11 expect(spec.headers).toEqual({ Authorization: 'Bearer sk-test' })
12 })
13
14 it('openai:内网地址去掉尾斜杠后拼接 /models', () => {
15 const spec = buildModelListRequest('openai', 'https://llm.corp.internal/v1/', 'key')
16 expect(spec.url).toBe('https://llm.corp.internal/v1/models')
17 })
18
19 it('openai-responses:剥离 /responses 后缀再拼接', () => {
20 expect(buildModelListRequest('openai-responses', 'https://llm.corp.internal/v1/responses', 'k').url).toBe(
21 'https://llm.corp.internal/v1/models'
22 )
23 expect(buildModelListRequest('openai-responses', 'https://llm.corp.internal/v1', 'k').url).toBe(
24 'https://llm.corp.internal/v1/models'
25 )
26 })
27
28 it('anthropic:默认官方网关,x-api-key + 版本头', () => {
29 const spec = buildModelListRequest('anthropic', '', 'sk-ant')
30 expect(spec.url).toBe('https://api.anthropic.com/v1/models?limit=1000')
31 expect(spec.headers).toEqual({ 'x-api-key': 'sk-ant', 'anthropic-version': '2023-06-01' })
32 })
33
34 it('anthropic:内网网关拼接 /v1/models', () => {
35 const spec = buildModelListRequest('anthropic', 'https://gw.corp.cn/', 'k')
36 expect(spec.url).toBe('https://gw.corp.cn/v1/models?limit=1000')
37 })
38
39 it('google:默认 generativelanguage 地址,x-goog-api-key 头', () => {
40 const spec = buildModelListRequest('google', '', 'g-key')
41 expect(spec.url).toBe('https://generativelanguage.googleapis.com/v1beta/models?pageSize=1000')
42 expect(spec.headers).toEqual({ 'x-goog-api-key': 'g-key' })
43 })
44 })
45
46 describe('parseModelListResponse', () => {
47 it('OpenAI/Anthropic 形状:取 data[].id,去重并排序', () => {
48 const models = parseModelListResponse('openai', {
49 object: 'list',
50 data: [
51 { id: 'deepseek-v4-flash', object: 'model' },
52 { id: 'deepseek-v4-flash' },
53 { id: 'glm-5.3' },
54 { object: 'model' },
55 null
56 ]
57 })
58 expect(models).toEqual(['deepseek-v4-flash', 'glm-5.3'])
59 })
60
61 it('非 google 供应商缺失 id 时回退使用 name 字段', () => {
62 const models = parseModelListResponse('anthropic', {
63 data: [{ display_name: 'Sonnet', name: 'claude-sonnet-4-5' }]
64 })
65 expect(models).toEqual(['claude-sonnet-4-5'])
66 })
67
68 it('google 形状:取 models[].name 并剥离 models/ 前缀', () => {
69 const models = parseModelListResponse('google', {
70 models: [{ name: 'models/gemini-2.0-flash' }, { name: 'models/gemini-3.1-pro' }]
71 })
72 expect(models).toEqual(['gemini-2.0-flash', 'gemini-3.1-pro'])
73 })
74
75 it('结构不符合预期时抛错', () => {
76 expect(() => parseModelListResponse('openai', { data: 'oops' })).toThrow()
77 expect(() => parseModelListResponse('google', {})).toThrow()
78 expect(() => parseModelListResponse('openai', null)).toThrow()
79 })
80
81 it('空列表返回空数组', () => {
82 expect(parseModelListResponse('openai', { data: [] })).toEqual([])
83 })
84 })
85
85 lines TYPESCRIPT