From 64f6f45c9229d70dbce08c402fe84de7262f99ef Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Thu, 23 Jul 2026 23:30:18 -0700 Subject: [PATCH] fix(ui): render each policy template parameter once A template with no LLM enrichment rendered every parameter field twice: the shared list already covers them, because nonEnrichmentParams is the full parameter list when there is no enrichment, and a second no-enrichment branch mapped the same list again. Predates the shadcn migration and was carried forward by it. The test now asserts exactly one field per parameter, and fails if the duplicate branch comes back. --- .../template_parameter_modal.test.tsx | 16 +++++++++------- .../_components/template_parameter_modal.tsx | 2 -- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.test.tsx index 1af45012d54..5dcab5cec80 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.test.tsx @@ -75,13 +75,15 @@ describe("TemplateParameterModal", () => { expect(screen.getByText("Configure competitor blocking for your brand")).toBeInTheDocument(); }); - it("renders a labelled field per template parameter and marks the required ones", async () => { + it("renders exactly one labelled field per template parameter", async () => { renderModal(); - expect((await screen.findAllByText("Organization Name")).length).toBeGreaterThan(0); - expect(screen.getAllByText("Note").length).toBeGreaterThan(0); - expect(screen.getAllByPlaceholderText("e.g. Contoso").length).toBeGreaterThan(0); - expect(screen.getAllByPlaceholderText("optional note").length).toBeGreaterThan(0); + // Exactly one: a plain template used to render every parameter twice, once from + // the shared list and again from a duplicate no-enrichment branch. + expect(await screen.findByText("Organization Name")).toBeInTheDocument(); + expect(screen.getByText("Note")).toBeInTheDocument(); + expect(screen.getAllByPlaceholderText("e.g. Contoso")).toHaveLength(1); + expect(screen.getAllByPlaceholderText("optional note")).toHaveLength(1); }); it("keeps Continue disabled until every required parameter is filled", async () => { @@ -91,7 +93,7 @@ describe("TemplateParameterModal", () => { await screen.findByText("Basic Redaction"); expect(screen.getByRole("button", { name: "Continue" })).toBeDisabled(); - await user.type(screen.getAllByPlaceholderText("e.g. Contoso")[0], "Contoso"); + await user.type(screen.getByPlaceholderText("e.g. Contoso"), "Contoso"); expect(screen.getByRole("button", { name: "Continue" })).not.toBeDisabled(); }); @@ -102,7 +104,7 @@ describe("TemplateParameterModal", () => { renderModal({ onConfirm }); await screen.findByText("Basic Redaction"); - await user.type(screen.getAllByPlaceholderText("e.g. Contoso")[0], "Contoso"); + await user.type(screen.getByPlaceholderText("e.g. Contoso"), "Contoso"); await user.click(screen.getByRole("button", { name: "Continue" })); expect(onConfirm).toHaveBeenCalledTimes(1); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.tsx index 13166080d0b..06c9284fffc 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/template_parameter_modal.tsx @@ -387,8 +387,6 @@ const TemplateParameterModal: React.FC = ({ )} )} - - {!hasEnrichment && parameters.map(renderParameterField)}