From ca77b324547df08704dd6a8e01cb3d8f2ce04047 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 25 Aug 2026 23:19:22 -0700 Subject: [PATCH 1/2] refactor(ui): move every page header onto PageHeader and drop the legacy one Virtual Keys, Budgets, Projects, Access Groups, Guardrails Monitor and Cost Optimization all move onto the shared PageHeader, matching the Teams page. That empties LegacyPageHeader, so it and its test are deleted. Each page now uses its own sidebar icon, so the nav and the page agree: Virtual Keys keeps KeyRound and Budgets keeps Wallet, Projects picks up Folder and Access Groups picks up Boxes, and Guardrails Monitor swaps the indigo Shield for the sidebar's HeartPulse. Cost Optimization keeps PiggyBank but drops its hardcoded size and stroke, which PageHeader owns. Control rows follow the spec instead of each page inventing one. Virtual Keys had its create button rendered as a sibling below the header, Budgets hand-rolled a row with a bottom border that closed the header off, and Projects and Access Groups sat their button next to the title. All four now pass primaryAction. Guardrails Monitor's date picker moves out of the parent and joins Export Data in utilities. Cost Optimization's tabs move into the tabs slot with the standard 22px spacing. Page insets go to p-8 with a 24px gap to content, replacing p-6 px-12, p-6, mx-4 and py-2. Every page test now asserts its heading, subtext and sidebar icon. Swapping any of the six icons fails its suite. --- .../_components/AccessGroupsPage.test.tsx | 2 + .../_components/AccessGroupsPage.tsx | 35 +++--- .../budgets/_components/budget_panel.test.tsx | 8 ++ .../budgets/_components/budget_panel.tsx | 52 ++++---- .../_components/CostOptimizationView.test.tsx | 8 ++ .../_components/CostOptimizationView.tsx | 111 +++++++++--------- .../_components/GuardrailsMonitorView.tsx | 29 +++-- .../_components/GuardrailsOverview.test.tsx | 2 + .../_components/GuardrailsOverview.tsx | 36 +++--- .../_components/ProjectsPage.test.tsx | 2 + .../projects/_components/ProjectsPage.tsx | 31 +++-- .../VirtualKeysPage/VirtualKeysTable.test.tsx | 2 + .../VirtualKeysPage/VirtualKeysTable.tsx | 10 +- .../shared/LegacyPageHeader.test.tsx | 33 ------ .../components/shared/LegacyPageHeader.tsx | 25 ---- .../src/components/user_dashboard.tsx | 38 +++--- 16 files changed, 198 insertions(+), 226 deletions(-) delete mode 100644 ui/litellm-dashboard/src/components/shared/LegacyPageHeader.test.tsx delete mode 100644 ui/litellm-dashboard/src/components/shared/LegacyPageHeader.tsx diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx index 55ce5061af7..56287ba6582 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx @@ -99,6 +99,8 @@ describe("AccessGroupsPage", () => { renderWithProviders(); expect(screen.getByRole("heading", { name: "Access Groups" })).toBeInTheDocument(); expect(screen.getByText("Manage resource permissions for your organization")).toBeInTheDocument(); + expect(document.querySelector(".lucide-boxes")).not.toBeNull(); + expect(screen.getByText("Manage resource permissions for your organization")).toBeInTheDocument(); }); it("shows the Create Access Group button for an admin", () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx index 4fc51910161..2e82fe3c418 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx @@ -1,9 +1,9 @@ import { AccessGroupResponse, useAccessGroups } from "@/app/(dashboard)/hooks/accessGroups/useAccessGroups"; import { useDeleteAccessGroup } from "@/app/(dashboard)/hooks/accessGroups/useDeleteAccessGroup"; -import { Plus, SearchIcon, X } from "lucide-react"; +import { Boxes, Plus, SearchIcon, X } from "lucide-react"; import { useMemo, useState } from "react"; import DeleteResourceModal from "@/components/common_components/DeleteResourceModal"; -import { LegacyPageHeader } from "@/components/shared/LegacyPageHeader"; +import { PageHeader } from "@/components/shared/PageHeader"; import { Button } from "@/components/ui/button"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group"; import { AccessGroupDetail } from "./AccessGroupsDetailsPage"; @@ -59,23 +59,22 @@ export function AccessGroupsPage() { } return ( -
-
- setIsCreateModalVisible(true)}> - - Create Access Group - - ) : undefined - } - /> -
+
+ } + title="Access Groups" + subtitle="Manage resource permissions for your organization" + primaryAction={ + canModify ? ( + + ) : undefined + } + /> -
+
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.test.tsx index 60e886754ce..f2608c1221f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.test.tsx @@ -85,6 +85,14 @@ describe("Budget Panel", () => { respondWith(DEFAULT_ROWS, 1); }); + it("renders the standard page header with the sidebar's Budgets icon", async () => { + const { container } = renderPanel(); + + expect(await screen.findByRole("heading", { level: 1, name: "Budgets" })).toBeInTheDocument(); + expect(screen.getByText("Spend, TPM and RPM limits you can assign to customers.")).toBeInTheDocument(); + expect(container.querySelector(".lucide-wallet")).not.toBeNull(); + }); + it("loads the first page of budgets, newest first", async () => { renderPanel(); await waitFor(() => expect(getMock).toHaveBeenCalled()); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.tsx b/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.tsx index 18b8e774aae..25344c52847 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/budgets/_components/budget_panel.tsx @@ -9,8 +9,7 @@ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { prism } from "react-syntax-highlighter/dist/esm/styles/prism"; import { useSyntaxTheme } from "@/hooks/useSyntaxTheme"; -import { LegacyPageHeader } from "@/components/shared/LegacyPageHeader"; -import { ToolbarSeparator } from "@/components/shared/ToolbarSeparator"; +import { PageHeader } from "@/components/shared/PageHeader"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import DeleteResourceModal from "@/components/common_components/DeleteResourceModal"; @@ -79,34 +78,37 @@ const BudgetPanel: React.FC = ({ accessToken }) => { }; return ( -
- } - title="Budgets" - subtitle="Spend, TPM and RPM limits you can assign to customers." - /> - -
- {canModify && ( - <> +
+ + } + title="Budgets" + subtitle="Spend, TPM and RPM limits you can assign to customers." + primaryAction={ + canModify ? ( - - + ) : undefined + } + tabs={({ leadingControls }) => ( + + {leadingControls} + + Budgets + + + Examples + + )} - - - Budgets - - - Examples - - -
+ /> -
+
{selectedBudget && ( = ({ accessToken }) => {
-
+ ); }; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.test.tsx index 384c6cdbc8f..d5df5aa75da 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.test.tsx @@ -44,6 +44,14 @@ describe("CostOptimizationView", () => { useAuthorizedMock.mockReturnValue({ accessToken: "test-token", userId: "u1", userRole: "Admin" }); }); + it("renders the standard page header with the sidebar's Cost Optimization icon", () => { + const { container, getByRole, getByText } = renderView(); + + expect(getByRole("heading", { level: 1, name: "Cost Optimization" })).toBeInTheDocument(); + expect(getByText(/Track and configure the mechanisms that save you money/)).toBeInTheDocument(); + expect(container.querySelector(".lucide-piggy-bank")).not.toBeNull(); + }); + it("renders the four cost-optimization tabs", () => { const { getByText } = renderView(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx index 165c63ea969..8094fa2e8b6 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx @@ -6,6 +6,7 @@ import { Info, PiggyBank } from "lucide-react"; import useCan from "@/app/(dashboard)/hooks/useCan"; import PaginationStatusAlerts from "@/components/shared/PaginationStatusAlerts"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { PageHeader } from "@/components/shared/PageHeader"; import UsageTab from "./UsageTab"; import PromptCompressionTab from "./PromptCompressionTab"; import PromptCachingTab from "./PromptCachingTab"; @@ -32,63 +33,63 @@ const CostOptimizationView: React.FC = ({ accessToken }; return ( -
-
-
- -

Cost Optimization

-
-

- Track and configure the mechanisms that save you money: prompt compression and prompt caching. Auto routers - live under Models + Endpoints, on the Auto-Routers tab -

-
- -
-
- - - - - - Overall - - {canViewProxyWideCostData && ( - <> - - Prompt Compression +
+ + } + title="Cost Optimization" + subtitle="Track and configure the mechanisms that save you money: prompt compression and prompt caching. Auto routers live under Models + Endpoints, on the Auto-Routers tab" + tabs={({ leadingControls }) => ( + + {leadingControls} + + Overall - - Prompt Caching - - - Auto-Router - - + {canViewProxyWideCostData && ( + <> + + Prompt Compression + + + Prompt Caching + + + Auto-Router + + + )} + )} - + /> +
+
+ + @@ -106,7 +107,7 @@ const CostOptimizationView: React.FC = ({ accessToken )}
-
+ ); }; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.tsx index 3b5cc156242..a9acf3e6377 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.tsx @@ -41,27 +41,32 @@ export default function GuardrailsMonitorView({ accessToken = null }: Guardrails setView({ type: "overview" }); }; + const dateRangeControl = ( + + ); + return ( -
-
- -
+
{view.type === "overview" ? ( ) : ( - + <> +
{dateRangeControl}
+ + )} -
+ ); } diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx index b616982d69b..69ec4d29d3b 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx @@ -110,6 +110,8 @@ describe("GuardrailsOverview", () => { expect(await screen.findByRole("heading", { name: "Guardrails Monitor", level: 1 })).toBeInTheDocument(); expect(screen.getByText("Monitor guardrail performance across all requests")).toBeInTheDocument(); + expect(document.querySelector(".lucide-heart-pulse")).not.toBeNull(); + expect(screen.getByText("Monitor guardrail performance across all requests")).toBeInTheDocument(); expect(screen.getByRole("button", { name: /Export Data/i })).toBeInTheDocument(); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.tsx index 42de8e2707b..5bc9eb16cee 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.tsx @@ -1,11 +1,12 @@ import { useQuery } from "@tanstack/react-query"; import type { ColumnDef, OnChangeFn, SortingState } from "@tanstack/react-table"; -import { Download, Settings, Shield, TrendingUp, TriangleAlert } from "lucide-react"; +import { Download, HeartPulse, Settings, TrendingUp, TriangleAlert } from "lucide-react"; import React, { useMemo, useState } from "react"; import { DataTable, DataTableSortHeader } from "@/components/shared/DataTable"; import { getGuardrailsUsageOverview } from "@/components/networking"; import { type PerformanceRow } from "@/components/GuardrailsMonitor/mockData"; import { Button } from "@/components/ui/button"; +import { PageHeader } from "@/components/shared/PageHeader"; import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner"; import { EvaluationSettingsModal } from "./EvaluationSettingsModal"; import { MetricCard } from "@/components/GuardrailsMonitor/MetricCard"; @@ -16,6 +17,7 @@ interface GuardrailsOverviewProps { startDate: string; endDate: string; onSelectGuardrail: (id: string) => void; + dateRangeControl?: React.ReactNode; } type SortKey = "failRate" | "requestsEvaluated" | "avgLatency" | "falsePositiveRate" | "falseNegativeRate"; @@ -43,6 +45,7 @@ export function GuardrailsOverview({ startDate, endDate, onSelectGuardrail, + dateRangeControl, }: GuardrailsOverviewProps) { const [sortBy, setSortBy] = useState("failRate"); const [sortDir, setSortDir] = useState<"asc" | "desc">("desc"); @@ -197,23 +200,22 @@ export function GuardrailsOverview({ return (
-
-
-
- -

Guardrails Monitor

-
-

Monitor guardrail performance across all requests

-
-
- -
-
+ } + title="Guardrails Monitor" + subtitle="Monitor guardrail performance across all requests" + utilities={ + <> + {dateRangeControl} + + + } + /> -
+
{ mockUseProjects.mockReturnValue({ data: [], isLoading: false }); renderWithProviders(); expect(screen.getByRole("heading", { name: /projects/i })).toBeInTheDocument(); + expect(screen.getByText("Manage projects within your teams")).toBeInTheDocument(); + expect(document.querySelector(".lucide-folder")).not.toBeNull(); }); it("should show a 'Create Project' button", () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectsPage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectsPage.tsx index dc18a05edca..4aba2bb627d 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectsPage.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/projects/_components/ProjectsPage.tsx @@ -1,9 +1,9 @@ import { useProjects } from "@/app/(dashboard)/hooks/projects/useProjects"; import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; -import { Plus, SearchIcon, X } from "lucide-react"; +import { Folder, Plus, SearchIcon, X } from "lucide-react"; import { parseAsString, useQueryState } from "nuqs"; import { useMemo, useState } from "react"; -import { LegacyPageHeader } from "@/components/shared/LegacyPageHeader"; +import { PageHeader } from "@/components/shared/PageHeader"; import { Button } from "@/components/ui/button"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group"; import { CreateProjectModal } from "./ProjectModals/CreateProjectModal"; @@ -54,21 +54,20 @@ export function ProjectsPage() { } return ( -
-
- setIsCreateModalVisible(true)}> - - Create Project - - } - /> -
+
+ } + title="Projects" + subtitle="Manage projects within your teams" + primaryAction={ + + } + /> -
+
diff --git a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.test.tsx b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.test.tsx index 643da71e8b1..d09ccbf8826 100644 --- a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.test.tsx +++ b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.test.tsx @@ -207,6 +207,8 @@ it("left-anchors the create-key CTA below the title, between the header and the renderWithProviders(Create New Key} />); const heading = screen.getByRole("heading", { name: "Virtual Keys" }); + expect(screen.getByText("Every key that authenticates requests to the gateway.")).toBeInTheDocument(); + expect(document.querySelector(".lucide-key-round")).not.toBeNull(); const ctas = screen.getAllByRole("button", { name: "Create New Key" }); expect(ctas).toHaveLength(1); const cta = ctas[0]; diff --git a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx index fbdcf2d8d83..7dd25ca1fd0 100644 --- a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx +++ b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx @@ -12,7 +12,7 @@ import { DataTableToolbar, } from "@/components/shared/DataTable"; import { SearchSelect } from "@/components/shared/SearchSelect"; -import { LegacyPageHeader } from "@/components/shared/LegacyPageHeader"; +import { PageHeader } from "@/components/shared/PageHeader"; import { Input } from "@/components/ui/input"; import { useDebouncedValue } from "@tanstack/react-pacer/debouncer"; import { ColumnFiltersState, OnChangeFn, PaginationState, SortingState } from "@tanstack/react-table"; @@ -182,13 +182,13 @@ export function VirtualKeysTable({ headerActions }: VirtualKeysTableProps) { } return ( -
- } +
+ } title="Virtual Keys" subtitle="Every key that authenticates requests to the gateway." + primaryAction={headerActions} /> - {headerActions} { - it("should render the title as a heading", () => { - renderWithProviders(); - - expect(screen.getByRole("heading", { name: "Virtual Keys" })).toBeInTheDocument(); - }); - - it("should render the optional identity and actions", () => { - renderWithProviders( - Key icon} - actions={} - />, - ); - - expect(screen.getByText("Every key that authenticates requests")).toBeInTheDocument(); - expect(screen.getByText("Key icon")).toBeInTheDocument(); - expect(screen.getByRole("button", { name: "Create New Key" })).toBeInTheDocument(); - }); - - it("should omit optional actions when none are provided", () => { - renderWithProviders(); - - expect(screen.queryByRole("button")).not.toBeInTheDocument(); - }); -}); diff --git a/ui/litellm-dashboard/src/components/shared/LegacyPageHeader.tsx b/ui/litellm-dashboard/src/components/shared/LegacyPageHeader.tsx deleted file mode 100644 index 43979ad00b4..00000000000 --- a/ui/litellm-dashboard/src/components/shared/LegacyPageHeader.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import * as React from "react"; - -interface LegacyPageHeaderProps { - title: React.ReactNode; - subtitle?: React.ReactNode; - icon?: React.ReactNode; - actions?: React.ReactNode; -} - -export function LegacyPageHeader({ title, subtitle, icon, actions }: LegacyPageHeaderProps) { - return ( -
-
- {icon != null && {icon}} -
-

{title}

- {subtitle != null &&

{subtitle}

} -
-
- {actions != null &&
{actions}
} -
- ); -} diff --git a/ui/litellm-dashboard/src/components/user_dashboard.tsx b/ui/litellm-dashboard/src/components/user_dashboard.tsx index ce5337aa7a7..614b3b7af62 100644 --- a/ui/litellm-dashboard/src/components/user_dashboard.tsx +++ b/ui/litellm-dashboard/src/components/user_dashboard.tsx @@ -216,27 +216,25 @@ const UserDashboard: React.FC = ({ const canCreateKey = userRole !== "Admin Viewer" && userRole !== "proxy_admin_viewer"; return ( -
-
-
- - ) : undefined - } - /> -
+
+
+ + ) : undefined + } + />
-
+ ); }; From 41e6e589159f19fd3ac079fb7b5b97f30dd69c22 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 25 Aug 2026 23:30:17 -0700 Subject: [PATCH 2/2] test(ui): drop duplicated subtitle assertions in the header tests --- .../access-groups/_components/AccessGroupsPage.test.tsx | 1 - .../guardrails-monitor/_components/GuardrailsOverview.test.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx index 56287ba6582..63ff0f4100f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.test.tsx @@ -100,7 +100,6 @@ describe("AccessGroupsPage", () => { expect(screen.getByRole("heading", { name: "Access Groups" })).toBeInTheDocument(); expect(screen.getByText("Manage resource permissions for your organization")).toBeInTheDocument(); expect(document.querySelector(".lucide-boxes")).not.toBeNull(); - expect(screen.getByText("Manage resource permissions for your organization")).toBeInTheDocument(); }); it("shows the Create Access Group button for an admin", () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx index 69ec4d29d3b..c62505cc74f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx @@ -111,7 +111,6 @@ describe("GuardrailsOverview", () => { expect(await screen.findByRole("heading", { name: "Guardrails Monitor", level: 1 })).toBeInTheDocument(); expect(screen.getByText("Monitor guardrail performance across all requests")).toBeInTheDocument(); expect(document.querySelector(".lucide-heart-pulse")).not.toBeNull(); - expect(screen.getByText("Monitor guardrail performance across all requests")).toBeInTheDocument(); expect(screen.getByRole("button", { name: /Export Data/i })).toBeInTheDocument(); });