mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 10:21:16 +08:00
fix(usage): persist dashboard refresh interval (#5057)
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
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(),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user