From 8bb496154a7b45c225cb4de5cbf62051ff3d950b Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 15 Sep 2026 22:18:42 -0700 Subject: [PATCH] test(ui): scope lifecycle assertions with within instead of parentElement The four .parentElement reads in the new lifecycle tests pushed testing-library/no-node-access to 712 against a 707 budget, failing frontend-lint. The rows now carry data-testid="lifecycle-row" and the test picks a row with within(), which keeps the assertion tied to the specific row rather than the whole panel and takes the count back to 707. --- .../GuardrailViewer/GuardrailViewer.test.tsx | 20 ++++++++++++------- .../GuardrailViewer/GuardrailViewer.tsx | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx index 7d597fa13dd..0f4ad206b1d 100644 --- a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx @@ -1,7 +1,7 @@ import React from "react"; import { describe, it, expect, vi, beforeEach } from "vitest"; import userEvent from "@testing-library/user-event"; -import { renderWithProviders, screen, waitFor } from "../../../../tests/test-utils"; +import { renderWithProviders, screen, waitFor, within } from "../../../../tests/test-utils"; import { GuardrailInformation, makeBedrockResponse, @@ -122,13 +122,19 @@ describe("GuardrailViewer", () => { const ran = makeGuardrailInformation(ranPostCall); renderWithProviders(); - expect(screen.getByText("Request received").parentElement).toHaveTextContent("T+0ms"); - expect(screen.getByText(/Post-call guardrail: ran-rail/).parentElement).toHaveTextContent("T+250ms"); - expect(screen.getByText("Response returned").parentElement).toHaveTextContent("T+251ms"); + const lifecycleRow = (label: string | RegExp): HTMLElement => { + const row = screen.getAllByTestId("lifecycle-row").find((r) => within(r).queryByText(label) !== null); + if (row === undefined) throw new Error(`no lifecycle row labelled ${label}`); + return row; + }; - const untimedRow = screen.getByText(/Pre-call guardrail: conduct/).parentElement; - expect(untimedRow).toHaveTextContent("—"); - expect(untimedRow).not.toHaveTextContent(/T\+/); + expect(within(lifecycleRow("Request received")).getByText("T+0ms")).toBeInTheDocument(); + expect(within(lifecycleRow(/Post-call guardrail: ran-rail/)).getByText("T+250ms")).toBeInTheDocument(); + expect(within(lifecycleRow("Response returned")).getByText("T+251ms")).toBeInTheDocument(); + + const untimedRow = within(lifecycleRow(/Pre-call guardrail: conduct/)); + expect(untimedRow.getByText("—")).toBeInTheDocument(); + expect(untimedRow.queryByText(/^T\+/)).not.toBeInTheDocument(); }); it("calculates and displays masked entity totals", async () => { diff --git a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx index cb1dc25b551..bf7b4355962 100644 --- a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx @@ -454,7 +454,7 @@ const RequestLifecycle = ({ entries }: { entries: GuardrailInformation[] }) => {

Request Lifecycle

{timeline.map((item, idx) => ( -
+
{/* Vertical line */}