diff --git a/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.test.tsx new file mode 100644 index 00000000000..9474c8aa9c8 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.test.tsx @@ -0,0 +1,67 @@ +import { describe, expect, it, vi } from "vitest"; +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import CacheTypeSelector from "./CacheTypeSelector"; + +const renderStandard = (overrides: Partial> = {}) => + render( + , + ); + +const openSelectFor = (labelText: string) => { + const selector = screen.getByText(labelText).parentElement!.querySelector(".ant-select-selector"); + fireEvent.mouseDown(selector as Element); +}; + +const optionLabels = async (): Promise => + waitFor(() => { + const options = Array.from(document.querySelectorAll(".ant-select-item-option-content")); + expect(options.length).toBeGreaterThan(0); + return options.map((el) => el.textContent ?? ""); + }); + +describe("CacheTypeSelector", () => { + it("should not offer Semantic as a Redis deployment type", async () => { + renderStandard(); + + openSelectFor("Redis Deployment Type"); + + expect(await optionLabels()).toEqual(["Node (Single Instance)", "Cluster", "Sentinel"]); + }); + + it("should offer Semantic only as a Cache Type", async () => { + renderStandard(); + + openSelectFor("Cache Type"); + + expect(await optionLabels()).toEqual(["Standard (exact match)", "Semantic (similarity-based)"]); + }); + + it("should call onCacheModeChange with semantic when the semantic cache type is chosen", async () => { + const onCacheModeChange = vi.fn(); + renderStandard({ onCacheModeChange }); + + openSelectFor("Cache Type"); + const semantic = await waitFor(() => { + const match = Array.from(document.querySelectorAll(".ant-select-item-option")).find((el) => + el.textContent?.includes("Semantic"), + ); + expect(match).toBeTruthy(); + return match as HTMLElement; + }); + fireEvent.click(semantic); + + expect(onCacheModeChange).toHaveBeenCalledWith("semantic"); + }); + + it("should hide the deployment type selector when semantic caching is selected", () => { + renderStandard({ cacheMode: "semantic" }); + + expect(screen.queryByText("Redis Deployment Type")).not.toBeInTheDocument(); + }); +}); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.tsx b/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.tsx new file mode 100644 index 00000000000..162c1cf6fde --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheTypeSelector.tsx @@ -0,0 +1,62 @@ +import React from "react"; +import { Select } from "antd"; +import { + CACHE_MODES, + CACHE_MODE_DESCRIPTIONS, + CACHE_MODE_LABELS, + CacheMode, + REDIS_DEPLOYMENT_DESCRIPTIONS, + REDIS_DEPLOYMENT_LABELS, + REDIS_DEPLOYMENT_TYPES, + RedisDeploymentType, +} from "./cacheSettingsFields"; + +interface CacheTypeSelectorProps { + cacheMode: CacheMode; + deploymentType: RedisDeploymentType; + onCacheModeChange: (mode: CacheMode) => void; + onDeploymentTypeChange: (type: RedisDeploymentType) => void; +} + +const cacheModeOptions = CACHE_MODES.map((mode) => ({ value: mode, label: CACHE_MODE_LABELS[mode] })); +const deploymentTypeOptions = REDIS_DEPLOYMENT_TYPES.map((type) => ({ + value: type, + label: REDIS_DEPLOYMENT_LABELS[type], +})); + +const CacheTypeSelector: React.FC = ({ + cacheMode, + deploymentType, + onCacheModeChange, + onDeploymentTypeChange, +}) => { + return ( +
+
+ + + value={cacheMode} + onChange={(value) => onCacheModeChange(value)} + options={cacheModeOptions} + style={{ width: "100%" }} + /> +

{CACHE_MODE_DESCRIPTIONS[cacheMode]}

+
+ + {cacheMode === "standard" && ( +
+ + + value={deploymentType} + onChange={(value) => onDeploymentTypeChange(value)} + options={deploymentTypeOptions} + style={{ width: "100%" }} + /> +

{REDIS_DEPLOYMENT_DESCRIPTIONS[deploymentType]}

+
+ )} +
+ ); +}; + +export default CacheTypeSelector;