mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
cover new useLogFilterLogic invariants: activeTab gate, filterByCurrentUser fallback, debounce negative, partial merge
Follow-up to the test refactor. Adds coverage for invariants the refactored hook contract introduced but that the first pass didn't assert: - query enablement: expand the single accessToken-null case into an it.each over all four credential props (accessToken, token, userRole, userID), plus a separate test for activeTab !== "request logs" - filterByCurrentUser: when true with a blank User ID filter, the outbound request carries user_id = userID - debounce: also assert the negative case — no call in the first 100ms after a filter change (first waiting out the initial mount fire) - handleFilterChange: partial updates merge without clobbering other filter keys (protects the spread + default-fill semantics) - handleFilterReset: calls setCurrentPage(1) alongside restoring filters
This commit is contained in:
parent
3db143b932
commit
8b633a2efc
1 changed files with 93 additions and 2 deletions
|
|
@ -109,6 +109,17 @@ describe("useLogFilterLogic", () => {
|
|||
expect(result.current.filters["Status"]).toBe("");
|
||||
});
|
||||
|
||||
it("calls setCurrentPage(1)", () => {
|
||||
const setCurrentPage = vi.fn();
|
||||
const { result } = renderFilterHook({ setCurrentPage });
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterReset();
|
||||
});
|
||||
|
||||
expect(setCurrentPage).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("triggers a fetch with all filter params undefined", async () => {
|
||||
vi.mocked(uiSpendLogsCall).mockResolvedValue(emptyResponse);
|
||||
const { result } = renderFilterHook();
|
||||
|
|
@ -156,6 +167,22 @@ describe("useLogFilterLogic", () => {
|
|||
expect(setCurrentPage).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("merges partial updates without clobbering other filter keys", () => {
|
||||
const { result } = renderFilterHook();
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ "Team ID": "team-a" });
|
||||
});
|
||||
expect(result.current.filters["Team ID"]).toBe("team-a");
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ Model: "gpt-4" });
|
||||
});
|
||||
|
||||
expect(result.current.filters["Team ID"]).toBe("team-a");
|
||||
expect(result.current.filters["Model"]).toBe("gpt-4");
|
||||
});
|
||||
|
||||
it("does not call setCurrentPage when filters are identical", async () => {
|
||||
const setCurrentPage = vi.fn();
|
||||
const { result } = renderFilterHook({ setCurrentPage });
|
||||
|
|
@ -259,6 +286,24 @@ describe("useLogFilterLogic", () => {
|
|||
|
||||
await waitFor(() => expect(uiSpendLogsCall).toHaveBeenCalled(), { timeout: 500 });
|
||||
});
|
||||
|
||||
it("does not call uiSpendLogsCall before the debounce elapses", async () => {
|
||||
const { result } = renderFilterHook();
|
||||
|
||||
// Wait for the initial query fire, then reset the spy so we only observe
|
||||
// calls triggered by the filter change below.
|
||||
await waitFor(() => expect(uiSpendLogsCall).toHaveBeenCalled(), { timeout: 500 });
|
||||
vi.mocked(uiSpendLogsCall).mockClear();
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ "Key Alias": "alias-1" });
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
expect(uiSpendLogsCall).not.toHaveBeenCalled();
|
||||
|
||||
await waitFor(() => expect(uiSpendLogsCall).toHaveBeenCalled(), { timeout: 500 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("backend filtered logs", () => {
|
||||
|
|
@ -455,8 +500,30 @@ describe("useLogFilterLogic", () => {
|
|||
});
|
||||
|
||||
describe("query enablement", () => {
|
||||
it("does not call uiSpendLogsCall when accessToken is null", async () => {
|
||||
const { result } = renderFilterHook({ accessToken: null });
|
||||
const nullCredentialCases: Array<{ name: string; override: HookOverrides }> = [
|
||||
{ name: "accessToken", override: { accessToken: null } },
|
||||
{ name: "token", override: { token: null } },
|
||||
{ name: "userRole", override: { userRole: null } },
|
||||
{ name: "userID", override: { userID: null } },
|
||||
];
|
||||
|
||||
it.each(nullCredentialCases)(
|
||||
"does not call uiSpendLogsCall when $name is null",
|
||||
async ({ override }) => {
|
||||
const { result } = renderFilterHook(override);
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ "Key Alias": "alias-1" });
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 350));
|
||||
|
||||
expect(uiSpendLogsCall).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
it("does not call uiSpendLogsCall when activeTab is not 'request logs'", async () => {
|
||||
const { result } = renderFilterHook({ activeTab: "audit logs" });
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ "Key Alias": "alias-1" });
|
||||
|
|
@ -468,6 +535,30 @@ describe("useLogFilterLogic", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("filterByCurrentUser", () => {
|
||||
it("sends user_id: userID when the User ID filter is blank", async () => {
|
||||
const { result } = renderFilterHook({
|
||||
filterByCurrentUser: true,
|
||||
userID: "me-123",
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.handleFilterChange({ "Key Alias": "alias-1" });
|
||||
});
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(uiSpendLogsCall).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({ user_id: "me-123" }),
|
||||
}),
|
||||
);
|
||||
},
|
||||
{ timeout: 500 },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("error handling", () => {
|
||||
it("does not crash when uiSpendLogsCall throws", async () => {
|
||||
vi.mocked(uiSpendLogsCall).mockRejectedValue(new Error("Network error"));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue