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

156 lines
4.4 KiB
TypeScript

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
fireEvent,
render,
screen,
waitFor,
within,
} from "@testing-library/react";
import type { ComponentProps } from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { UsageDashboard } from "@/components/usage/UsageDashboard";
const useProviderStatsMock = vi.hoisted(() => vi.fn());
const useModelStatsMock = vi.hoisted(() => vi.fn());
vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string, fallback?: string) => fallback ?? key,
i18n: {
resolvedLanguage: "en",
language: "en",
},
}),
}));
vi.mock("framer-motion", () => ({
motion: {
div: ({ children, ...props }: any) => <div {...props}>{children}</div>,
},
}));
vi.mock("@/hooks/useUsageEventBridge", () => ({
useUsageEventBridge: () => {},
}));
vi.mock("@/lib/query/usage", async () => {
const actual =
await vi.importActual<typeof import("@/lib/query/usage")>(
"@/lib/query/usage",
);
return {
...actual,
useProviderStats: (...args: unknown[]) => useProviderStatsMock(...args),
useModelStats: (...args: unknown[]) => useModelStatsMock(...args),
};
});
vi.mock("@/components/usage/UsageHero", () => ({
UsageHero: () => <div data-testid="usage-hero" />,
}));
vi.mock("@/components/usage/UsageTrendChart", () => ({
UsageTrendChart: () => <div data-testid="usage-trend" />,
}));
vi.mock("@/components/usage/RequestLogTable", () => ({
RequestLogTable: () => <div data-testid="request-log-table" />,
}));
vi.mock("@/components/usage/ProviderStatsTable", () => ({
ProviderStatsTable: () => <div data-testid="provider-stats-table" />,
}));
vi.mock("@/components/usage/ModelStatsTable", () => ({
ModelStatsTable: () => <div data-testid="model-stats-table" />,
}));
vi.mock("@/components/usage/PricingConfigPanel", () => ({
PricingConfigPanel: () => <div data-testid="pricing-config-panel" />,
}));
vi.mock("@/components/usage/UsageDateRangePicker", () => ({
UsageDateRangePicker: () => <button type="button">date-range</button>,
}));
vi.mock("@/components/ui/select", () => ({
Select: ({ value, onValueChange, children }: any) => (
<div data-testid={`select-${value}`}>
{children}
<button type="button" onClick={() => onValueChange?.("5000")}>
choose-5000
</button>
</div>
),
SelectTrigger: ({ children, ...props }: any) => (
<button type="button" {...props}>
{children}
</button>
),
SelectValue: () => null,
SelectContent: ({ children }: any) => <div>{children}</div>,
SelectItem: ({ children, ...props }: any) => <div {...props}>{children}</div>,
}));
const renderDashboard = (props: ComponentProps<typeof UsageDashboard> = {}) => {
const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
},
});
return render(
<QueryClientProvider client={queryClient}>
<UsageDashboard {...props} />
</QueryClientProvider>,
);
};
describe("UsageDashboard", () => {
beforeEach(() => {
useProviderStatsMock.mockReset();
useModelStatsMock.mockReset();
useProviderStatsMock.mockReturnValue({ data: [] });
useModelStatsMock.mockReturnValue({ data: [] });
});
it("uses the saved refresh interval when mounted", () => {
renderDashboard({ refreshIntervalMs: 5000 });
expect(screen.getByTestId("select-5000")).toBeInTheDocument();
});
it("persists refresh interval changes", async () => {
const onRefreshIntervalChange = vi.fn().mockResolvedValue(true);
renderDashboard({ onRefreshIntervalChange });
fireEvent.click(
within(screen.getByTestId("select-30000")).getByRole("button", {
name: "choose-5000",
}),
);
await waitFor(() =>
expect(onRefreshIntervalChange).toHaveBeenCalledWith(5000),
);
expect(screen.getByTestId("select-5000")).toBeInTheDocument();
});
it("rolls back optimistic interval changes when persistence fails", async () => {
const onRefreshIntervalChange = vi.fn().mockResolvedValue(false);
renderDashboard({ onRefreshIntervalChange });
fireEvent.click(
within(screen.getByTestId("select-30000")).getByRole("button", {
name: "choose-5000",
}),
);
await waitFor(() =>
expect(onRefreshIntervalChange).toHaveBeenCalledWith(5000),
);
await waitFor(() =>
expect(screen.getByTestId("select-30000")).toBeInTheDocument(),
);
});
});