sub2api/frontend/src/components/account/__tests__/AccountTestModal.spec.ts
shaw 095f457c57 feat(openai): port /responses/compact account support flow (PR #1555)
vansour/sub2api#1555 的 OpenAI compact 能力建模手工移植到当前 main:账号
级 compact 状态/auto-force_on-force_off 模式、compact-only 模型映射、调度器
tier 分层(已支持 > 未知 > 已知不支持)、管理后台 compact 主动探测,以及对应
i18n/状态徽章。普通 /responses 流量行为不变,无数据库迁移。
2026-04-25 14:52:58 +08:00

151 lines
3.5 KiB
TypeScript

import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import { flushPromises, mount } from '@vue/test-utils'
import { defineComponent } from 'vue'
import AccountTestModal from '../AccountTestModal.vue'
const { getAvailableModelsMock } = vi.hoisted(() => ({
getAvailableModelsMock: vi.fn()
}))
vi.mock('@/api/admin', () => ({
adminAPI: {
accounts: {
getAvailableModels: getAvailableModelsMock
}
}
}))
vi.mock('@/composables/useClipboard', () => ({
useClipboard: () => ({
copyToClipboard: vi.fn()
})
}))
vi.mock('vue-i18n', async () => {
const actual = await vi.importActual<typeof import('vue-i18n')>('vue-i18n')
return {
...actual,
useI18n: () => ({
t: (key: string) => key
})
}
})
const BaseDialogStub = defineComponent({
name: 'BaseDialog',
props: { show: { type: Boolean, default: false } },
template: '<div v-if="show"><slot /><slot name="footer" /></div>'
})
const SelectStub = defineComponent({
name: 'SelectStub',
props: {
modelValue: { type: [String, Number, Boolean, null], default: '' },
options: { type: Array, default: () => [] },
valueKey: { type: String, default: 'value' },
labelKey: { type: String, default: 'label' }
},
emits: ['update:modelValue'],
template: `
<select
v-bind="$attrs"
:value="modelValue"
@change="$emit('update:modelValue', $event.target.value)"
>
<option
v-for="option in options"
:key="option[valueKey]"
:value="option[valueKey]"
>
{{ option[labelKey] }}
</option>
</select>
`
})
const TextAreaStub = defineComponent({
name: 'TextArea',
props: {
modelValue: { type: String, default: '' }
},
emits: ['update:modelValue'],
template: `
<textarea
v-bind="$attrs"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
`
})
function buildAccount() {
return {
id: 1,
name: 'OpenAI OAuth',
platform: 'openai',
type: 'oauth',
status: 'active',
credentials: {},
extra: {},
concurrency: 1,
priority: 1,
proxy_id: null,
auto_pause_on_expired: false
} as any
}
describe('AccountTestModal', () => {
const originalFetch = global.fetch
beforeEach(() => {
getAvailableModelsMock.mockReset()
getAvailableModelsMock.mockResolvedValue([
{ id: 'gpt-5.4', display_name: 'GPT-5.4' }
])
global.fetch = vi.fn().mockResolvedValue({
ok: true,
body: {
getReader: () => ({
read: vi.fn().mockResolvedValue({ done: true, value: undefined })
})
}
} as any)
localStorage.setItem('auth_token', 'test-token')
})
afterEach(() => {
global.fetch = originalFetch
localStorage.clear()
})
it('posts compact mode for OpenAI compact probe', async () => {
const wrapper = mount(AccountTestModal, {
props: {
show: true,
account: buildAccount()
},
global: {
stubs: {
BaseDialog: BaseDialogStub,
Select: SelectStub,
TextArea: TextAreaStub,
Icon: true
}
}
})
await flushPromises()
;(wrapper.vm as any).selectedModelId = 'gpt-5.4'
;(wrapper.vm as any).testMode = 'compact'
await (wrapper.vm as any).startTest()
await flushPromises()
expect(global.fetch).toHaveBeenCalledTimes(1)
const [, options] = (global.fetch as any).mock.calls[0]
expect(JSON.parse(options.body)).toMatchObject({
model_id: 'gpt-5.4',
mode: 'compact'
})
})
})