From 70456fb8bb7bd67e90ba144d9d5cc8fad28239a0 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Fri, 17 Apr 2026 15:17:21 -0700 Subject: [PATCH] fix(ui): update add_plugin_form tests to match rewritten smart URL form --- .../add_plugin_form.test.tsx | 112 +++++++----------- 1 file changed, 45 insertions(+), 67 deletions(-) diff --git a/ui/litellm-dashboard/src/components/claude_code_plugins/add_plugin_form.test.tsx b/ui/litellm-dashboard/src/components/claude_code_plugins/add_plugin_form.test.tsx index 36001224cc..5152bf6a70 100644 --- a/ui/litellm-dashboard/src/components/claude_code_plugins/add_plugin_form.test.tsx +++ b/ui/litellm-dashboard/src/components/claude_code_plugins/add_plugin_form.test.tsx @@ -20,112 +20,90 @@ describe("AddPluginForm", () => { vi.clearAllMocks(); }); - it("renders the source type select with GitHub as default", () => { + it("renders with GitHub URL input", () => { renderWithProviders(); - // The default value "GitHub" is displayed in the collapsed select - expect(screen.getByText("GitHub")).toBeInTheDocument(); - // The form label is present - expect(screen.getByText("Source Type")).toBeInTheDocument(); + expect(screen.getByText("GitHub URL")).toBeInTheDocument(); + expect( + screen.getByPlaceholderText("https://github.com/org/repo/tree/main/my-skill") + ).toBeInTheDocument(); }); - it("shows URL and Path fields when git-subdir is selected", async () => { + it("shows GitHub repo preview for a plain repo URL", async () => { renderWithProviders(); - const sourceSelect = screen.getByLabelText("Source Type"); + const urlInput = screen.getByPlaceholderText( + "https://github.com/org/repo/tree/main/my-skill" + ); + await act(async () => { - fireEvent.mouseDown(sourceSelect); + fireEvent.change(urlInput, { + target: { value: "https://github.com/anthropics/claude-code" }, + }); }); await waitFor(() => { - fireEvent.click(screen.getByText("Git Subdir")); - }); - - await waitFor(() => { - expect(screen.getByPlaceholderText("https://github.com/org/repo.git")).toBeInTheDocument(); - expect(screen.getByPlaceholderText("plugins/plugin-name")).toBeInTheDocument(); + expect(screen.getByText(/GitHub repo/)).toBeInTheDocument(); }); }); - it("does not show Path field for url source type", async () => { + it("shows git-subdir preview for a tree URL", async () => { renderWithProviders(); - const sourceSelect = screen.getByLabelText("Source Type"); + const urlInput = screen.getByPlaceholderText( + "https://github.com/org/repo/tree/main/my-skill" + ); + await act(async () => { - fireEvent.mouseDown(sourceSelect); + fireEvent.change(urlInput, { + target: { + value: "https://github.com/anthropics/claude-code/tree/main/plugins/my-skill", + }, + }); }); await waitFor(() => { - fireEvent.click(screen.getByText("Git URL")); - }); - - await waitFor(() => { - expect(screen.getByPlaceholderText("https://github.com/org/repo.git")).toBeInTheDocument(); - expect(screen.queryByPlaceholderText("plugins/plugin-name")).not.toBeInTheDocument(); + expect(screen.getByText(/GitHub subdir/)).toBeInTheDocument(); }); }); - it("shows path format error when pattern does not match", async () => { + it("auto-fills skill name from repo URL", async () => { renderWithProviders(); - // Switch to git-subdir - const sourceSelect = screen.getByLabelText("Source Type"); - await act(async () => { - fireEvent.mouseDown(sourceSelect); - }); - await waitFor(() => { - fireEvent.click(screen.getByText("Git Subdir")); - }); + const urlInput = screen.getByPlaceholderText( + "https://github.com/org/repo/tree/main/my-skill" + ); - // Fill required fields - fireEvent.change(screen.getByPlaceholderText("my-awesome-plugin"), { - target: { value: "my-plugin" }, - }); - fireEvent.change(screen.getByPlaceholderText("https://github.com/org/repo.git"), { - target: { value: "https://github.com/org/repo.git" }, - }); - // Enter a path that violates the allowlist - fireEvent.change(screen.getByPlaceholderText("plugins/plugin-name"), { - target: { value: "../../etc/passwd" }, - }); - - // Submit — triggers Antd form validation await act(async () => { - fireEvent.click(screen.getByText("Register Plugin")); + fireEvent.change(urlInput, { + target: { value: "https://github.com/anthropics/my-awesome-skill" }, + }); }); await waitFor(() => { - expect( - screen.getByText( - "Path must be relative segments (alphanumeric, dots, hyphens, underscores), e.g. plugins/plugin-name" - ) - ).toBeInTheDocument(); + const nameInput = screen.getByPlaceholderText("my-skill") as HTMLInputElement; + expect(nameInput.value).toBe("my-awesome-skill"); }); }); - it("clears path field when switching away from git-subdir", async () => { + it("does not auto-fill name when name is already set", async () => { renderWithProviders(); - // Switch to git-subdir - const sourceSelect = screen.getByLabelText("Source Type"); - await act(async () => { - fireEvent.mouseDown(sourceSelect); - }); - await waitFor(() => { - fireEvent.click(screen.getByText("Git Subdir")); - }); + const nameInput = screen.getByPlaceholderText("my-skill") as HTMLInputElement; + fireEvent.change(nameInput, { target: { value: "existing-name" } }); + + const urlInput = screen.getByPlaceholderText( + "https://github.com/org/repo/tree/main/my-skill" + ); - // Switch back to GitHub await act(async () => { - fireEvent.mouseDown(sourceSelect); - }); - await waitFor(() => { - fireEvent.click(screen.getByText("GitHub")); + fireEvent.change(urlInput, { + target: { value: "https://github.com/anthropics/other-skill" }, + }); }); await waitFor(() => { - expect(screen.queryByPlaceholderText("plugins/plugin-name")).not.toBeInTheDocument(); - expect(screen.getByPlaceholderText("anthropics/claude-code")).toBeInTheDocument(); + expect(nameInput.value).toBe("existing-name"); }); }); });