mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
fix(ui): invalidate keys list after key update so table reflects changes
handleKeyUpdate in key_info_view.tsx updated local component state and called
onKeyDataUpdate after a successful /key/update, but never invalidated the
React Query keys list -- unlike handleDelete in the same file, which already
calls queryClient.invalidateQueries({ queryKey: keyKeys.lists() }).
As a result, editing a key (e.g. daily budget / budget reset) and returning
to the keys table showed stale cached values: the change looked like it "didn't
save" even though /key/update had persisted it and refreshed the runtime key
cache on the backend.
Fix: invalidate keyKeys.lists() after a successful update, mirroring the
delete path. Adds a regression test that fails before the fix (spy never
called with { queryKey: ['keys','list'] }) and passes after.
This commit is contained in:
parent
e1717c5e9c
commit
104d81caba
2 changed files with 31 additions and 4 deletions
|
|
@ -2,11 +2,12 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
// ---- Hoisted shared mocks (safe to use inside vi.mock factories) ----
|
||||
const { keyUpdateCallMock, keyDeleteCallMock, mockUseAuthorized } = vi.hoisted(() => {
|
||||
const { keyUpdateCallMock, keyDeleteCallMock, mockUseAuthorized, invalidateQueriesMock } = vi.hoisted(() => {
|
||||
return {
|
||||
keyUpdateCallMock: vi.fn().mockResolvedValue({}),
|
||||
keyDeleteCallMock: vi.fn().mockResolvedValue({}),
|
||||
mockUseAuthorized: vi.fn(),
|
||||
invalidateQueriesMock: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -270,12 +271,13 @@ vi.mock("@/app/(dashboard)/hooks/keys/useSetKeyBlockedState", () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
// useQueryClient also needs a provider; the delete-path invalidation is covered in key_info_view.test.tsx
|
||||
// useQueryClient also needs a provider; return a hoisted spy so we can assert the
|
||||
// update path invalidates the keys list (mirrors the delete-path test in key_info_view.test.tsx)
|
||||
vi.mock("@tanstack/react-query", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@tanstack/react-query")>();
|
||||
return {
|
||||
...actual,
|
||||
useQueryClient: () => ({ invalidateQueries: vi.fn() }),
|
||||
useQueryClient: () => ({ invalidateQueries: invalidateQueriesMock }),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -301,6 +303,7 @@ vi.mock("./key_edit_view", async () => {
|
|||
|
||||
// ---- SUT import AFTER mocks ----
|
||||
import KeyInfoView from "./key_info_view";
|
||||
import { keyKeys } from "@/app/(dashboard)/hooks/keys/useKeys";
|
||||
|
||||
// ---- Test data helpers ----
|
||||
const baseKeyData = {
|
||||
|
|
@ -593,3 +596,26 @@ describe("KeyInfoView handleKeyUpdate empty strings", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("KeyInfoView handleKeyUpdate keys-list invalidation", () => {
|
||||
it("invalidates the keys list query after a successful update so the table reflects the change", async () => {
|
||||
renderView(true);
|
||||
|
||||
fireEvent.click(screen.getByText("Settings"));
|
||||
fireEvent.click(screen.getByText("Edit Settings"));
|
||||
(globalThis as any).__TEST_FORM_VALUES = {
|
||||
token: "tok_123",
|
||||
max_budget: 60,
|
||||
budget_duration: "24h",
|
||||
};
|
||||
|
||||
fireEvent.click(screen.getByText("Mock Submit"));
|
||||
|
||||
await waitFor(() => expect(keyUpdateCallMock).toHaveBeenCalled());
|
||||
// The keys list must be invalidated, otherwise returning to the table shows
|
||||
// stale (cached) values — the original bug behind "budget save looks invalid".
|
||||
await waitFor(() => {
|
||||
expect(invalidateQueriesMock).toHaveBeenCalledWith({ queryKey: keyKeys.lists() });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -314,7 +314,8 @@ export default function KeyInfoView({
|
|||
}
|
||||
NotificationManager.success("Key updated successfully");
|
||||
setIsEditing(false);
|
||||
// Refresh key data here if needed
|
||||
// Invalidate the keys list so the table reflects the update (mirrors handleDelete)
|
||||
await queryClient.invalidateQueries({ queryKey: keyKeys.lists() });
|
||||
} catch (error) {
|
||||
NotificationManager.fromBackend(parseErrorMessage(error));
|
||||
console.error("Error updating key:", error);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue