Files
wehub-resource-sync 64ed910d3f
CI / Backend Checks (push) Has been cancelled
CI / Frontend Checks (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:57:20 +08:00

94 lines
2.5 KiB
TypeScript

import { render, screen, fireEvent } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { PricingEditModal } from "@/components/usage/PricingEditModal";
import type { ModelPricing } from "@/types/usage";
vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string, options?: string | { defaultValue?: string }) =>
typeof options === "string" ? options : options?.defaultValue ?? key,
}),
}));
vi.mock("sonner", () => ({
toast: {
success: vi.fn(),
error: vi.fn(),
},
}));
vi.mock("@/lib/query/usage", () => ({
useUpdateModelPricing: () => ({
mutateAsync: vi.fn(),
isPending: false,
}),
}));
vi.mock("@/components/common/FullScreenPanel", () => ({
FullScreenPanel: ({
children,
footer,
}: {
children: React.ReactNode;
footer?: React.ReactNode;
}) => (
<div>
{children}
{footer}
</div>
),
}));
const model: ModelPricing = {
modelId: "deepseek-v4",
displayName: "DeepSeek V4",
inputCostPerMillion: "1",
outputCostPerMillion: "3",
cacheReadCostPerMillion: "0.0028",
cacheCreationCostPerMillion: "0",
};
const PRICE_FIELDS = [
{ id: "inputCost", label: "输入成本" },
{ id: "outputCost", label: "输出成本" },
{ id: "cacheReadCost", label: "缓存读取成本" },
{ id: "cacheCreationCost", label: "缓存写入成本" },
] as const;
describe("PricingEditModal", () => {
it("all price inputs have step=0.0001", () => {
render(<PricingEditModal open model={model} onClose={() => {}} />);
for (const { id } of PRICE_FIELDS) {
const input = screen.getByLabelText(/每百万 tokens/ as unknown as string, {
selector: `#${id}`,
}) as HTMLInputElement;
expect(input).toHaveAttribute("step", "0.0001");
}
});
it("accepts precise cache read cost like 0.0028", () => {
render(<PricingEditModal open model={model} onClose={() => {}} />);
const cacheReadInput = document.getElementById(
"cacheReadCost",
) as HTMLInputElement;
expect(cacheReadInput.value).toBe("0.0028");
expect(cacheReadInput.checkValidity()).toBe(true);
});
it("allows user to input sub-cent prices via change event", () => {
render(
<PricingEditModal open model={model} onClose={() => {}} isNew />,
);
const cacheReadInput = document.getElementById(
"cacheReadCost",
) as HTMLInputElement;
fireEvent.change(cacheReadInput, { target: { value: "0.0015" } });
expect(cacheReadInput.value).toBe("0.0015");
});
});