From dfa17ef6218bf2df55120caedba471d845eaced9 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Thu, 28 May 2026 15:57:02 -0300 Subject: [PATCH] chore(cli): remove unused BaseUrlSelect/ApiKeySelect/ManualConfigModal (plan 14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Components were created by F4 per master-plan §3.7-§3.9 but never integrated: the `*ToolCard.tsx` files use the legacy `ManualConfigModal` from `@/shared/components` (barrel-export root), not the F4 versions in `@/shared/components/cli`. The 3 files were sitting as dead code. Removes: - src/shared/components/cli/BaseUrlSelect.tsx - src/shared/components/cli/ApiKeySelect.tsx - src/shared/components/cli/ManualConfigModal.tsx - tests/unit/ui/BaseUrlSelect.test.tsx - tests/unit/ui/ApiKeySelect.test.tsx - tests/unit/ui/ManualConfigModal.test.tsx Updates `src/shared/components/cli/index.ts` to drop the dead exports. Kept (actively used by page clients): - CliToolCard, CliConceptCard, CliComparisonCard Verified: - typecheck:core + noimplicit:core clean - npx eslint src/shared/components/cli/: 0 issues - check:cycles: clean (212 files, -3 from removed components) - 50/50 UI tests pass across the 3 kept components + 3 page clients - 0 residual imports of the 3 removed symbols anywhere in src/ or tests/ Closes code review v3 gap #1 (dead code). --- src/shared/components/cli/ApiKeySelect.tsx | 99 -------- src/shared/components/cli/BaseUrlSelect.tsx | 102 -------- .../components/cli/ManualConfigModal.tsx | 152 ----------- src/shared/components/cli/index.ts | 9 - tests/unit/ui/ApiKeySelect.test.tsx | 160 ------------ tests/unit/ui/BaseUrlSelect.test.tsx | 159 ------------ tests/unit/ui/ManualConfigModal.test.tsx | 238 ------------------ 7 files changed, 919 deletions(-) delete mode 100644 src/shared/components/cli/ApiKeySelect.tsx delete mode 100644 src/shared/components/cli/BaseUrlSelect.tsx delete mode 100644 src/shared/components/cli/ManualConfigModal.tsx delete mode 100644 tests/unit/ui/ApiKeySelect.test.tsx delete mode 100644 tests/unit/ui/BaseUrlSelect.test.tsx delete mode 100644 tests/unit/ui/ManualConfigModal.test.tsx diff --git a/src/shared/components/cli/ApiKeySelect.tsx b/src/shared/components/cli/ApiKeySelect.tsx deleted file mode 100644 index 1a7d51d9cd..0000000000 --- a/src/shared/components/cli/ApiKeySelect.tsx +++ /dev/null @@ -1,99 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { cn } from "@/shared/utils/cn"; - -export interface ApiKeyEntry { - id: string; - name: string; - prefix?: string; - createdAt?: string; -} - -export interface ApiKeySelectProps { - keys: ApiKeyEntry[]; - value: string; - onChange: (value: string) => void; - label?: string; - disabled?: boolean; -} - -const MANUAL_VALUE = "__manual__"; - -export default function ApiKeySelect({ - keys, - value, - onChange, - label = "API Key", - disabled = false, -}: ApiKeySelectProps) { - const isManual = !keys.some((k) => k.id === value) && value !== ""; - const [showManual, setShowManual] = useState(isManual); - const [manualValue, setManualValue] = useState(isManual ? value : ""); - - function handleSelectChange(e: React.ChangeEvent) { - const val = e.target.value; - if (val === MANUAL_VALUE) { - setShowManual(true); - onChange(manualValue); - } else { - setShowManual(false); - onChange(val); - } - } - - function handleManualInput(e: React.ChangeEvent) { - const val = e.target.value; - setManualValue(val); - onChange(val); - } - - const selectValue = showManual ? MANUAL_VALUE : (value || ""); - - return ( -
- {label && ( - - )} - - {showManual && ( - - )} -
- ); -} diff --git a/src/shared/components/cli/BaseUrlSelect.tsx b/src/shared/components/cli/BaseUrlSelect.tsx deleted file mode 100644 index 8c7e2e8f2c..0000000000 --- a/src/shared/components/cli/BaseUrlSelect.tsx +++ /dev/null @@ -1,102 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { cn } from "@/shared/utils/cn"; - -export interface BaseUrlSelectProps { - value: string; - onChange: (value: string) => void; - cloudEnabled: boolean; - cloudUrl?: string; - label?: string; - disabled?: boolean; -} - -type OptionKey = "local" | "cloud" | "custom"; - -function getDefaultLocal(): string { - if (typeof window !== "undefined") { - return window.location.origin; - } - return "http://localhost:20128"; -} - -export default function BaseUrlSelect({ - value, - onChange, - cloudEnabled, - cloudUrl, - label = "Base URL", - disabled = false, -}: BaseUrlSelectProps) { - const localUrl = getDefaultLocal(); - - function detectOption(val: string): OptionKey { - if (val === localUrl) return "local"; - if (cloudEnabled && cloudUrl && val === cloudUrl) return "cloud"; - return "custom"; - } - - const [selectedOption, setSelectedOption] = useState(() => detectOption(value)); - const [customValue, setCustomValue] = useState( - detectOption(value) === "custom" ? value : "" - ); - - function handleSelectChange(e: React.ChangeEvent) { - const opt = e.target.value as OptionKey; - setSelectedOption(opt); - if (opt === "local") { - onChange(localUrl); - } else if (opt === "cloud" && cloudUrl) { - onChange(cloudUrl); - } else if (opt === "custom") { - onChange(customValue); - } - } - - function handleCustomInput(e: React.ChangeEvent) { - const val = e.target.value; - setCustomValue(val); - onChange(val); - } - - return ( -
- {label && ( - - )} - - {selectedOption === "custom" && ( - - )} -
- ); -} diff --git a/src/shared/components/cli/ManualConfigModal.tsx b/src/shared/components/cli/ManualConfigModal.tsx deleted file mode 100644 index 5b41347896..0000000000 --- a/src/shared/components/cli/ManualConfigModal.tsx +++ /dev/null @@ -1,152 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { cn } from "@/shared/utils/cn"; -import type { CliCatalogEntry } from "@/shared/schemas/cliCatalog"; - -export interface ManualConfigModalCustomCode { - language: string; - code: string; -} - -export interface ManualConfigModalProps { - open: boolean; - onClose: () => void; - tool: CliCatalogEntry; - baseUrl: string; - apiKey: string; - model: string; - customCode?: ManualConfigModalCustomCode; -} - -function interpolate(template: string, vars: Record): string { - return template - .replace(/\{\{baseUrl\}\}/g, vars["baseUrl"] ?? "") - .replace(/\{\{apiKey\}\}/g, vars["apiKey"] ?? "") - .replace(/\{\{model\}\}/g, vars["model"] ?? ""); -} - -export default function ManualConfigModal({ - open, - onClose, - tool, - baseUrl, - apiKey, - model, - customCode, -}: ManualConfigModalProps) { - const [copied, setCopied] = useState(false); - - if (!open) return null; - - const source = customCode ?? tool.codeBlock; - const vars: Record = { baseUrl, apiKey, model }; - const rendered = source ? interpolate(source.code, vars) : ""; - - async function handleCopy() { - try { - await navigator.clipboard.writeText(rendered); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch { - // fallback: do nothing — clipboard unavailable in non-secure context - } - } - - return ( - /* Overlay */ -
- - ); -} diff --git a/src/shared/components/cli/index.ts b/src/shared/components/cli/index.ts index eea1c9f639..1b8dd28230 100644 --- a/src/shared/components/cli/index.ts +++ b/src/shared/components/cli/index.ts @@ -6,12 +6,3 @@ export type { CliConceptCardProps, CliConceptType } from "./CliConceptCard"; export { default as CliComparisonCard } from "./CliComparisonCard"; export type { CliComparisonCardProps } from "./CliComparisonCard"; - -export { default as BaseUrlSelect } from "./BaseUrlSelect"; -export type { BaseUrlSelectProps } from "./BaseUrlSelect"; - -export { default as ApiKeySelect } from "./ApiKeySelect"; -export type { ApiKeySelectProps, ApiKeyEntry } from "./ApiKeySelect"; - -export { default as ManualConfigModal } from "./ManualConfigModal"; -export type { ManualConfigModalProps, ManualConfigModalCustomCode } from "./ManualConfigModal"; diff --git a/tests/unit/ui/ApiKeySelect.test.tsx b/tests/unit/ui/ApiKeySelect.test.tsx deleted file mode 100644 index 2ca1518734..0000000000 --- a/tests/unit/ui/ApiKeySelect.test.tsx +++ /dev/null @@ -1,160 +0,0 @@ -// @vitest-environment jsdom -import React from "react"; -import { act } from "react"; -import { createRoot } from "react-dom/client"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { ApiKeyEntry, ApiKeySelectProps } from "@/shared/components/cli/ApiKeySelect"; - -// ── Import ──────────────────────────────────────────────────────────────────── - -const { default: ApiKeySelect } = await import("@/shared/components/cli/ApiKeySelect"); - -// ── Helpers ─────────────────────────────────────────────────────────────────── - -const containers: HTMLElement[] = []; - -function renderSelect(props: ApiKeySelectProps): HTMLElement { - const container = document.createElement("div"); - document.body.appendChild(container); - containers.push(container); - - const root = createRoot(container); - act(() => { - root.render(); - }); - return container; -} - -const SAMPLE_KEYS: ApiKeyEntry[] = [ - { id: "key1", name: "Production Key", prefix: "sk-prod" }, - { id: "key2", name: "Dev Key", prefix: "sk-dev" }, -]; - -// ── Lifecycle ───────────────────────────────────────────────────────────────── - -beforeEach(() => { - (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = - true; -}); - -afterEach(() => { - while (containers.length > 0) { - containers.pop()?.remove(); - } - document.body.innerHTML = ""; -}); - -// ── Tests ───────────────────────────────────────────────────────────────────── - -describe("ApiKeySelect", () => { - it("renders a select element", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - }); - const select = container.querySelector("select"); - expect(select).not.toBeNull(); - }); - - it("renders all provided keys as options", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - }); - expect(container.textContent).toContain("Production Key"); - expect(container.textContent).toContain("Dev Key"); - }); - - it("renders prefix in option text", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - }); - expect(container.textContent).toContain("sk-prod"); - }); - - it("always includes 'Inserir manualmente' option", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - }); - expect(container.textContent).toContain("Inserir manualmente"); - }); - - it("does NOT show manual input by default when a known key is selected", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - }); - const input = container.querySelector("input"); - expect(input).toBeNull(); - }); - - it("shows manual input when value is not in keys list", () => { - // Passing a value that's not in the keys array triggers manual mode - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "sk-somemanualvalue", - onChange: vi.fn(), - }); - const input = container.querySelector("input"); - expect(input).not.toBeNull(); - }); - - it("calls onChange when selecting a different key", () => { - const onChange = vi.fn(); - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange, - }); - const select = container.querySelector("select") as HTMLSelectElement; - act(() => { - select.value = "key2"; - select.dispatchEvent(new Event("change", { bubbles: true })); - }); - expect(onChange).toHaveBeenCalledWith("key2"); - }); - - it("selecting '__manual__' value reveals input", () => { - const onChange = vi.fn(); - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange, - }); - const select = container.querySelector("select") as HTMLSelectElement; - act(() => { - select.value = "__manual__"; - select.dispatchEvent(new Event("change", { bubbles: true })); - }); - const input = container.querySelector("input"); - expect(input).not.toBeNull(); - }); - - it("renders label when provided", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - label: "Auth Key", - }); - expect(container.textContent).toContain("Auth Key"); - }); - - it("disables select when disabled=true", () => { - const container = renderSelect({ - keys: SAMPLE_KEYS, - value: "key1", - onChange: vi.fn(), - disabled: true, - }); - const select = container.querySelector("select") as HTMLSelectElement; - expect(select.disabled).toBe(true); - }); -}); diff --git a/tests/unit/ui/BaseUrlSelect.test.tsx b/tests/unit/ui/BaseUrlSelect.test.tsx deleted file mode 100644 index f87715b50f..0000000000 --- a/tests/unit/ui/BaseUrlSelect.test.tsx +++ /dev/null @@ -1,159 +0,0 @@ -// @vitest-environment jsdom -import React from "react"; -import { act } from "react"; -import { createRoot } from "react-dom/client"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { BaseUrlSelectProps } from "@/shared/components/cli/BaseUrlSelect"; - -// ── Import ──────────────────────────────────────────────────────────────────── - -const { default: BaseUrlSelect } = await import("@/shared/components/cli/BaseUrlSelect"); - -// ── Helpers ─────────────────────────────────────────────────────────────────── - -const containers: HTMLElement[] = []; - -function renderSelect(props: BaseUrlSelectProps): HTMLElement { - const container = document.createElement("div"); - document.body.appendChild(container); - containers.push(container); - - const root = createRoot(container); - act(() => { - root.render(); - }); - return container; -} - -// ── Lifecycle ───────────────────────────────────────────────────────────────── - -beforeEach(() => { - (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = - true; - // Stub window.location.origin - Object.defineProperty(window, "location", { - value: { origin: "http://localhost:20128" }, - writable: true, - configurable: true, - }); -}); - -afterEach(() => { - while (containers.length > 0) { - containers.pop()?.remove(); - } - document.body.innerHTML = ""; -}); - -// ── Tests ───────────────────────────────────────────────────────────────────── - -describe("BaseUrlSelect", () => { - it("renders a select element", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - }); - const select = container.querySelector("select"); - expect(select).not.toBeNull(); - }); - - it("shows Local option always", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - }); - expect(container.textContent).toContain("Local"); - }); - - it("shows Cloud option when cloudEnabled=true and cloudUrl is set", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: true, - cloudUrl: "https://cloud.example.com", - }); - expect(container.textContent).toContain("Cloud"); - expect(container.textContent).toContain("cloud.example.com"); - }); - - it("does NOT show Cloud option when cloudEnabled=false", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - cloudUrl: "https://cloud.example.com", - }); - // "Cloud" option should not appear in select options - const select = container.querySelector("select"); - const options = Array.from(select?.options ?? []); - const cloudOption = options.find((o) => o.value === "cloud"); - expect(cloudOption).toBeUndefined(); - }); - - it("shows Custom option always", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - }); - const select = container.querySelector("select"); - const options = Array.from(select?.options ?? []); - const customOption = options.find((o) => o.value === "custom"); - expect(customOption).toBeDefined(); - }); - - it("reveals custom input when value does not match local or cloud", () => { - const container = renderSelect({ - value: "https://custom.example.com", - onChange: vi.fn(), - cloudEnabled: false, - }); - // Since value doesn't match local, it should be in custom mode showing an input - const input = container.querySelector("input"); - expect(input).not.toBeNull(); - }); - - it("calls onChange when custom input changes", () => { - const onChange = vi.fn(); - const container = renderSelect({ - value: "https://custom.example.com", - onChange, - cloudEnabled: false, - }); - const input = container.querySelector("input") as HTMLInputElement; - expect(input).not.toBeNull(); - // Use React's synthetic event via nativeInputValueSetter - const nativeInputValueSetter = Object.getOwnPropertyDescriptor( - window.HTMLInputElement.prototype, - "value" - )?.set; - act(() => { - nativeInputValueSetter?.call(input, "https://new.example.com"); - input.dispatchEvent(new Event("change", { bubbles: true })); - }); - expect(onChange).toHaveBeenCalledWith("https://new.example.com"); - }); - - it("renders label when provided", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - label: "Endpoint URL", - }); - expect(container.textContent).toContain("Endpoint URL"); - }); - - it("disables select when disabled=true", () => { - const container = renderSelect({ - value: "http://localhost:20128", - onChange: vi.fn(), - cloudEnabled: false, - disabled: true, - }); - const select = container.querySelector("select") as HTMLSelectElement; - expect(select.disabled).toBe(true); - }); -}); diff --git a/tests/unit/ui/ManualConfigModal.test.tsx b/tests/unit/ui/ManualConfigModal.test.tsx deleted file mode 100644 index 3d7b83d029..0000000000 --- a/tests/unit/ui/ManualConfigModal.test.tsx +++ /dev/null @@ -1,238 +0,0 @@ -// @vitest-environment jsdom -import React from "react"; -import { act } from "react"; -import { createRoot } from "react-dom/client"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { CliCatalogEntry } from "@/shared/schemas/cliCatalog"; -import type { - ManualConfigModalProps, - ManualConfigModalCustomCode, -} from "@/shared/components/cli/ManualConfigModal"; - -// ── Import ──────────────────────────────────────────────────────────────────── - -const { default: ManualConfigModal } = await import("@/shared/components/cli/ManualConfigModal"); - -// ── Helpers ─────────────────────────────────────────────────────────────────── - -const containers: HTMLElement[] = []; - -function makeTool(overrides: Partial = {}): CliCatalogEntry { - return { - id: "continue", - name: "Continue", - icon: "terminal", - color: "#7C3AED", - description: "Continue AI coding assistant", - docsUrl: "https://example.com", - configType: "guide", - category: "code", - vendor: "continue.dev", - acpSpawnable: false, - baseUrlSupport: "full", - codeBlock: { - language: "json", - code: '{\n "baseURL": "{{baseUrl}}",\n "apiKey": "{{apiKey}}",\n "model": "{{model}}"\n}', - }, - ...overrides, - }; -} - -function renderModal(props: ManualConfigModalProps): HTMLElement { - const container = document.createElement("div"); - document.body.appendChild(container); - containers.push(container); - - const root = createRoot(container); - act(() => { - root.render(); - }); - return container; -} - -// ── Lifecycle ───────────────────────────────────────────────────────────────── - -beforeEach(() => { - (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = - true; - // Mock clipboard - const writeText = vi.fn(() => Promise.resolve()); - Object.defineProperty(navigator, "clipboard", { - value: { writeText }, - writable: true, - configurable: true, - }); -}); - -afterEach(() => { - while (containers.length > 0) { - containers.pop()?.remove(); - } - document.body.innerHTML = ""; -}); - -// ── Tests ───────────────────────────────────────────────────────────────────── - -describe("ManualConfigModal", () => { - it("does not render when open=false", () => { - const container = renderModal({ - open: false, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - const dialog = container.querySelector('[role="dialog"]'); - expect(dialog).toBeNull(); - }); - - it("renders when open=true", () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - const dialog = container.querySelector('[role="dialog"]'); - expect(dialog).not.toBeNull(); - }); - - it("interpolates {{baseUrl}} in code block", () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - const pre = container.querySelector("pre"); - expect(pre?.textContent).toContain("http://localhost:20128"); - expect(pre?.textContent).not.toContain("{{baseUrl}}"); - }); - - it("interpolates {{apiKey}} in code block", () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test-key", - model: "gpt-4o", - }); - const pre = container.querySelector("pre"); - expect(pre?.textContent).toContain("sk-test-key"); - expect(pre?.textContent).not.toContain("{{apiKey}}"); - }); - - it("interpolates {{model}} in code block", () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "claude-sonnet-4-5", - }); - const pre = container.querySelector("pre"); - expect(pre?.textContent).toContain("claude-sonnet-4-5"); - expect(pre?.textContent).not.toContain("{{model}}"); - }); - - it("uses customCode when provided instead of tool.codeBlock", () => { - const customCode: ManualConfigModalCustomCode = { - language: "bash", - code: "export BASE_URL={{baseUrl}}", - }; - const tool = makeTool({ codeBlock: undefined }); - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool, - baseUrl: "https://custom.example.com", - apiKey: "sk-test", - model: "gpt-4o", - customCode, - }); - const pre = container.querySelector("pre"); - expect(pre?.textContent).toContain("https://custom.example.com"); - expect(pre?.textContent).toContain("export BASE_URL="); - }); - - it("calls navigator.clipboard.writeText when Copy button is clicked", async () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - - const copyButton = Array.from(container.querySelectorAll("button")).find((b) => - b.textContent?.includes("Copy") - ); - expect(copyButton).not.toBeUndefined(); - - await act(async () => { - copyButton!.click(); - await Promise.resolve(); - }); - - expect(navigator.clipboard.writeText).toHaveBeenCalled(); - }); - - it("shows Copied! feedback after copying", async () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - - const copyButton = Array.from(container.querySelectorAll("button")).find((b) => - b.textContent?.includes("Copy") - ); - - await act(async () => { - copyButton!.click(); - await Promise.resolve(); - }); - - expect(container.textContent).toContain("Copied!"); - }); - - it("calls onClose when backdrop is clicked", () => { - const onClose = vi.fn(); - const container = renderModal({ - open: true, - onClose, - tool: makeTool(), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - const overlay = container.querySelector('[aria-hidden="true"]') as HTMLElement; - act(() => { - overlay?.click(); - }); - expect(onClose).toHaveBeenCalled(); - }); - - it("shows tool name in header", () => { - const container = renderModal({ - open: true, - onClose: vi.fn(), - tool: makeTool({ name: "My CLI Tool" }), - baseUrl: "http://localhost:20128", - apiKey: "sk-test", - model: "gpt-4o", - }); - expect(container.textContent).toContain("My CLI Tool"); - }); -});