Files
sub2api/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts
T

281 lines
9.2 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { nextTick } from 'vue'
vi.mock('vue-i18n', () => ({
useI18n: () => ({
t: (key: string) => key
})
}))
vi.mock('@/composables/useClipboard', () => ({
useClipboard: () => ({
copyToClipboard: vi.fn().mockResolvedValue(true)
})
}))
import UseKeyModal from '../UseKeyModal.vue'
describe('UseKeyModal', () => {
it('renders Grok Build and OpenCode setup for Grok groups', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-grok-test',
baseUrl: 'https://example.com/v1',
platform: 'grok'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const grokTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.grokCli')
)
expect(grokTab).toBeDefined()
const grokConfig = wrapper.findAll('pre code')
.map((code) => code.text())
.find((content) => content.includes('[model."sub2api-grok"]'))
expect(grokConfig).toBeDefined()
expect(grokConfig).toContain('model = "grok-4.5"')
expect(grokConfig).toContain('base_url = "https://example.com/v1"')
expect(grokConfig).toContain('api_key = "sk-grok-test"')
expect(grokConfig).toContain('api_backend = "responses"')
const windowsTab = wrapper.findAll('button').find(
(button) => button.text().trim() === 'Windows'
)
expect(windowsTab).toBeDefined()
await windowsTab!.trigger('click')
await nextTick()
expect(wrapper.text()).toContain('%userprofile%\\.grok/config.toml')
const opencodeTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.opencode')
)
expect(opencodeTab).toBeDefined()
await opencodeTab!.trigger('click')
await nextTick()
const parsed = JSON.parse(wrapper.find('pre code').text())
expect(parsed.provider.grok.npm).toBe('@ai-sdk/openai')
expect(parsed.provider.grok.options).toEqual({
baseURL: 'https://example.com/v1',
apiKey: 'sk-grok-test'
})
expect(parsed.provider.grok.models['grok-4.5']).toBeDefined()
expect(parsed.provider.grok.models['grok-build-0.1']).toBeDefined()
expect(parsed.provider.grok.models['grok-composer-2.5-fast']).toBeDefined()
expect(parsed.provider.grok.models['gpt-5.6']).toBeUndefined()
})
it('renders minimal image executor authorization in OpenAI Codex config', () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'openai'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const codeBlocks = wrapper.findAll('pre code').map((code) => code.text())
const configToml = codeBlocks.find((content) => content.includes('model_provider = "OpenAI"'))
expect(configToml).toBeDefined()
expect(configToml).toContain('model = "gpt-5.5"')
expect(configToml).toContain('review_model = "gpt-5.5"')
expect(configToml).not.toContain('model = "gpt-5.4"')
expect(configToml).not.toContain('model_context_window')
expect(configToml).not.toContain('model_auto_compact_token_limit')
expect(configToml).toContain('requires_openai_auth = false')
expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }')
expect(configToml).not.toContain('env_key')
expect(configToml).not.toContain('image_generation')
expect(configToml).not.toContain('supports_websockets')
expect(configToml).not.toContain('responses_websockets_v2')
expect(configToml).toContain('[features]\ngoals = true')
expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}')
expect(wrapper.text()).toContain('auth.json')
})
it('renders minimal image executor authorization in OpenAI Codex WebSocket config', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'openai'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const wsTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.codexCliWs')
)
expect(wsTab).toBeDefined()
await wsTab!.trigger('click')
await nextTick()
const codeBlocks = wrapper.findAll('pre code').map((code) => code.text())
const configToml = codeBlocks.find((content) => content.includes('supports_websockets = true'))
expect(configToml).toBeDefined()
expect(configToml).toContain('model = "gpt-5.5"')
expect(configToml).toContain('review_model = "gpt-5.5"')
expect(configToml).not.toContain('model = "gpt-5.4"')
expect(configToml).not.toContain('model_context_window')
expect(configToml).not.toContain('model_auto_compact_token_limit')
expect(configToml).toContain('requires_openai_auth = false')
expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }')
expect(configToml).not.toContain('env_key')
expect(configToml).not.toContain('image_generation')
expect(configToml).toContain('supports_websockets = true')
expect(configToml).toContain('[features]\nresponses_websockets_v2 = true\ngoals = true')
expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}')
expect(wrapper.text()).toContain('auth.json')
})
it('renders GPT-5.4 mini entry in OpenCode config', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'openai'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const opencodeTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.opencode')
)
expect(opencodeTab).toBeDefined()
await opencodeTab!.trigger('click')
await nextTick()
const codeBlock = wrapper.find('pre code')
expect(codeBlock.exists()).toBe(true)
expect(codeBlock.text()).toContain('"name": "GPT-5.4 Mini"')
expect(codeBlock.text()).not.toContain('"name": "GPT-5.4 Nano"')
})
it('renders GPT-5.6 alias and max variants in OpenCode config', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'openai'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const opencodeTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.opencode')
)
expect(opencodeTab).toBeDefined()
await opencodeTab!.trigger('click')
await nextTick()
const parsed = JSON.parse(wrapper.find('pre code').text())
const models = parsed.provider.openai.models
for (const model of ['gpt-5.6', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna']) {
expect(models[model]).toBeDefined()
expect(models[model].variants).toHaveProperty('max')
expect(models[model].variants).toHaveProperty('xhigh')
}
expect(models['gpt-5.6'].name).toBe('GPT-5.6 (Sol)')
})
it('renders Claude Fable 5 OpenCode config with adaptive thinking', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'antigravity'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const opencodeTab = wrapper.findAll('button').find((button) =>
button.text().includes('keys.useKeyModal.cliTabs.opencode')
)
expect(opencodeTab).toBeDefined()
await opencodeTab!.trigger('click')
await nextTick()
const claudeConfig = wrapper.findAll('pre code')
.map((code) => code.text())
.find((content) => content.includes('"antigravity-claude"'))
expect(claudeConfig).toBeDefined()
const parsed = JSON.parse(claudeConfig!)
const fable = parsed.provider['antigravity-claude'].models['claude-fable-5']
expect(fable.name).toBe('Claude Fable 5')
expect(fable.limit).toEqual({ context: 1048576, output: 128000 })
expect(fable.options.thinking).toEqual({ type: 'adaptive' })
expect(fable.options.thinking).not.toHaveProperty('budgetTokens')
})
})