Files
Genarrative/apps/admin-web/src/pages/AdminEditorGenerationPricingPage.test.tsx
T
kdletters 071faa482c 统一 Rust 与 TypeScript 格式化门禁
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口

完成项目 TypeScript/Prettier 与 Rust 全量格式化

修复 Pingora expected executable 门禁的空白敏感误报

同步开发运维文档与 AGC skill pack 格式化忽略规则
2026-09-01 16:28:34 +08:00

93 lines
2.8 KiB
TypeScript

/* @vitest-environment jsdom */
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, expect, test, vi } from 'vitest';
import {
getAdminEditorGenerationPricing,
upsertAdminEditorGenerationPricing,
} from '../api/adminApiClient';
import type { EditorGenerationPricingConfigPayload } from '../api/adminApiTypes';
import { AdminEditorGenerationPricingPage } from './AdminEditorGenerationPricingPage';
vi.mock('../api/adminApiClient', () => ({
formatAdminApiError: vi.fn((error: unknown) =>
error instanceof Error ? error.message : '请求失败',
),
getAdminEditorGenerationPricing: vi.fn(),
isAdminApiError: vi.fn(() => false),
upsertAdminEditorGenerationPricing: vi.fn(),
}));
const pricing: EditorGenerationPricingConfigPayload = {
models: {
'gemini-3.1-flash-image-preview': {
unit: 'perGeneration',
prices: { '0.5K': 8, '1K': 12, '2K': 24 },
},
'gpt-image-2': {
unit: 'perGeneration',
prices: { '1K': 3, '2K': 5 },
},
'seedance2.0-fast': {
unit: 'perSecond',
prices: { '480p': 10, '720p': 20, '1080p': 40 },
},
'seedance2.0': {
unit: 'perSecond',
prices: { '480p': 12, '720p': 24, '1080p': 48 },
},
'audio1.0': { unit: 'perGeneration', price: 5 },
'chirp-v5': { unit: 'perGeneration', price: 12 },
},
};
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(getAdminEditorGenerationPricing).mockResolvedValue(pricing);
vi.mocked(upsertAdminEditorGenerationPricing).mockResolvedValue({
...pricing,
models: {
...pricing.models,
'gpt-image-2': {
unit: 'perGeneration',
prices: { '1K': 20, '2K': 58 },
},
},
});
});
test('模型定价后台按模型展示单位并保存尺寸定价', async () => {
const user = userEvent.setup();
render(
<AdminEditorGenerationPricingPage
token="admin-token"
onUnauthorized={vi.fn()}
/>,
);
expect((await screen.findAllByText('按次')).length).toBeGreaterThan(0);
expect(screen.getAllByText('按秒').length).toBeGreaterThan(0);
const gptImage2kInput = screen.getByLabelText('gpt-image-2 2K');
fireEvent.change(gptImage2kInput, { target: { value: '58' } });
await user.click(screen.getByRole('button', { name: '保存定价' }));
await user.click(screen.getByRole('button', { name: '确认' }));
await waitFor(() => {
expect(upsertAdminEditorGenerationPricing).toHaveBeenCalledWith(
'admin-token',
expect.objectContaining({
models: expect.objectContaining({
'gpt-image-2': expect.objectContaining({
unit: 'perGeneration',
prices: expect.objectContaining({
'2K': 58,
}),
}),
}),
}),
);
});
});