估价请求统一使用 350ms 防抖、AbortController 和请求序号,区分免费、计算中、价格不可用与失败状态,并展示候选冻结上限。价格未就绪时阻止生产提交。\n\n计价规则编辑器新增显式免费开关和 9 位价格步进。\n\n验证:Web 88 项测试和生产构建通过。
50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { GatewayPricingEstimate } from '@easyai-ai-gateway/contracts';
|
|
import {
|
|
MEDIA_ESTIMATE_DEBOUNCE_MS,
|
|
billingEstimateSignature,
|
|
mediaEstimateFromResponse,
|
|
} from './PlaygroundPage';
|
|
|
|
describe('playground pricing estimate', () => {
|
|
it('uses the specified 350ms debounce interval', () => {
|
|
expect(MEDIA_ESTIMATE_DEBOUNCE_MS).toBe(350);
|
|
});
|
|
|
|
it('only changes its signature for billing-relevant parameters', () => {
|
|
const first = billingEstimateSignature({
|
|
kind: 'images.generations', model: 'image-model', prompt: 'first',
|
|
count: 1, quality: 'high', resolution: '2K',
|
|
});
|
|
const promptOnly = billingEstimateSignature({
|
|
kind: 'images.generations', model: 'image-model', prompt: 'second',
|
|
count: 1, quality: 'high', resolution: '2K',
|
|
});
|
|
const changedCount = billingEstimateSignature({
|
|
kind: 'images.generations', model: 'image-model', prompt: 'second',
|
|
count: 2, quality: 'high', resolution: '2K',
|
|
});
|
|
expect(promptOnly).toBe(first);
|
|
expect(changedCount).not.toBe(first);
|
|
});
|
|
|
|
it('distinguishes explicit free and exposes the reservation ceiling', () => {
|
|
const response: GatewayPricingEstimate = {
|
|
candidateCount: 2,
|
|
currency: 'resource',
|
|
items: [{ amount: 0, currency: 'resource', isFree: true }],
|
|
pricingVersion: 'effective-pricing-v2',
|
|
requestFingerprint: 'fingerprint',
|
|
reservationAmount: 0,
|
|
resolver: 'effective-pricing-v2',
|
|
totalAmount: 0,
|
|
};
|
|
expect(mediaEstimateFromResponse(response)).toMatchObject({
|
|
amount: 0,
|
|
candidateCount: 2,
|
|
reservationAmount: 0,
|
|
status: 'free',
|
|
});
|
|
});
|
|
});
|