forked from niuniu/llm-intelligence
120 lines
3.9 KiB
TypeScript
120 lines
3.9 KiB
TypeScript
|
|
import { describe, expect, it } from 'vitest'
|
||
|
|
import {
|
||
|
|
formatPrice,
|
||
|
|
formatSubscriptionQuota,
|
||
|
|
normalizeModel,
|
||
|
|
normalizeSubscriptionPlan,
|
||
|
|
providerDistribution,
|
||
|
|
summarizeModels,
|
||
|
|
summarizeSubscriptionPlans,
|
||
|
|
} from './models'
|
||
|
|
|
||
|
|
describe('models helpers', () => {
|
||
|
|
it('normalizes fallback pricing and stale flags', () => {
|
||
|
|
const model = normalizeModel({
|
||
|
|
id: 'anthropic/claude-sonnet-4.6',
|
||
|
|
provider_cn: 'Anthropic',
|
||
|
|
context_length: 200000,
|
||
|
|
input_price: '3',
|
||
|
|
output_price: '15',
|
||
|
|
data_confidence: 'stale',
|
||
|
|
})
|
||
|
|
|
||
|
|
expect(model).not.toBeNull()
|
||
|
|
expect(model?.providerCN).toBe('Anthropic')
|
||
|
|
expect(model?.inputPrice).toBe(3)
|
||
|
|
expect(model?.outputPrice).toBe(15)
|
||
|
|
expect(model?.stale).toBe(true)
|
||
|
|
expect(model?.pricingAvailable).toBe(true)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('marks free models and pricing unavailable correctly', () => {
|
||
|
|
const freeModel = normalizeModel({
|
||
|
|
id: 'qwen/qwen3-coder:free',
|
||
|
|
})
|
||
|
|
const paidModel = normalizeModel({
|
||
|
|
id: 'openai/gpt-4.1',
|
||
|
|
pricing: {},
|
||
|
|
})
|
||
|
|
|
||
|
|
expect(formatPrice(freeModel!, 'input')).toContain('免费')
|
||
|
|
expect(formatPrice(paidModel!, 'input')).toBe('pricing unavailable')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('summarizes providers and currencies', () => {
|
||
|
|
const models = [
|
||
|
|
normalizeModel({ id: 'deepseek/deepseek-chat', provider_cn: 'DeepSeek', currency: 'CNY', pricing: { input: 1, output: 2 } }),
|
||
|
|
normalizeModel({ id: 'deepseek/deepseek-reasoner', provider_cn: 'DeepSeek', currency: 'CNY', pricing: { input: 2, output: 4 } }),
|
||
|
|
normalizeModel({ id: 'anthropic/claude-sonnet-4.6', provider_cn: 'Anthropic', currency: 'USD', pricing: { input: 3, output: 15 } }),
|
||
|
|
].filter((model): model is NonNullable<typeof model> => model !== null)
|
||
|
|
|
||
|
|
expect(summarizeModels(models)).toEqual({
|
||
|
|
modelCount: 3,
|
||
|
|
providerCount: 2,
|
||
|
|
cnyCount: 2,
|
||
|
|
})
|
||
|
|
expect(providerDistribution(models)).toEqual([
|
||
|
|
{ name: 'DeepSeek', value: 2 },
|
||
|
|
{ name: 'Anthropic', value: 1 },
|
||
|
|
])
|
||
|
|
})
|
||
|
|
|
||
|
|
it('normalizes subscription plans from API payload', () => {
|
||
|
|
const plan = normalizeSubscriptionPlan({
|
||
|
|
planCode: 'token-plan-lite',
|
||
|
|
planName: '通用 Token Plan Lite',
|
||
|
|
planFamily: 'token_plan',
|
||
|
|
tier: 'Lite',
|
||
|
|
provider: 'Tencent',
|
||
|
|
providerCN: '腾讯',
|
||
|
|
operator: 'Tencent Cloud',
|
||
|
|
operatorCN: '腾讯云',
|
||
|
|
currency: 'CNY',
|
||
|
|
listPrice: 39,
|
||
|
|
priceUnit: 'CNY/month',
|
||
|
|
quotaValue: 35000000,
|
||
|
|
quotaUnit: 'tokens/month',
|
||
|
|
contextWindow: 0,
|
||
|
|
modelScope: ['tc-code-latest', 'glm-5', 'glm-5.1'],
|
||
|
|
})
|
||
|
|
|
||
|
|
expect(plan).not.toBeNull()
|
||
|
|
expect(plan?.planCode).toBe('token-plan-lite')
|
||
|
|
expect(plan?.providerCN).toBe('腾讯')
|
||
|
|
expect(plan?.modelScope.length).toBe(3)
|
||
|
|
expect(plan?.modelPreview).toBe('tc-code-latest, glm-5, glm-5.1')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('formats subscription quotas and summarizes plan stats', () => {
|
||
|
|
const plans = [
|
||
|
|
normalizeSubscriptionPlan({
|
||
|
|
planCode: 'token-plan-lite',
|
||
|
|
planName: '通用 Token Plan Lite',
|
||
|
|
providerCN: '腾讯',
|
||
|
|
listPrice: 39,
|
||
|
|
quotaValue: 35000000,
|
||
|
|
quotaUnit: 'tokens/month',
|
||
|
|
modelScope: ['tc-code-latest', 'glm-5', 'glm-5.1'],
|
||
|
|
}),
|
||
|
|
normalizeSubscriptionPlan({
|
||
|
|
planCode: 'hy-token-plan-max',
|
||
|
|
planName: 'Hy Token Plan Max',
|
||
|
|
providerCN: '腾讯',
|
||
|
|
listPrice: 468,
|
||
|
|
quotaValue: 650000000,
|
||
|
|
quotaUnit: 'tokens/month',
|
||
|
|
contextWindow: 262144,
|
||
|
|
modelScope: ['hy3-preview'],
|
||
|
|
}),
|
||
|
|
].filter((plan): plan is NonNullable<typeof plan> => plan !== null)
|
||
|
|
|
||
|
|
expect(formatSubscriptionQuota(plans[0].quotaValue, plans[0].quotaUnit)).toBe('3500万 Tokens/月')
|
||
|
|
expect(formatSubscriptionQuota(plans[1].quotaValue, plans[1].quotaUnit)).toBe('6.5亿 Tokens/月')
|
||
|
|
expect(summarizeSubscriptionPlans(plans)).toEqual({
|
||
|
|
planCount: 2,
|
||
|
|
providerCount: 1,
|
||
|
|
minMonthlyPrice: 39,
|
||
|
|
})
|
||
|
|
})
|
||
|
|
})
|