From 5d778f2b01c348427f36a51e8c0ec8ed44207425 Mon Sep 17 00:00:00 2001 From: yucheng Date: Wed, 23 Sep 2026 22:30:55 +0000 Subject: [PATCH] test(e2e): browser contract for the otel_internal_spans dropdown Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../tests/integrationCritical/expected.json | 1 + .../otelInternalSpans.spec.ts | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/e2e/ui/tests/integrationCritical/otelInternalSpans.spec.ts diff --git a/tests/e2e/ui/tests/integrationCritical/expected.json b/tests/e2e/ui/tests/integrationCritical/expected.json index 0354c9f729c..aa2e17fa24f 100644 --- a/tests/e2e/ui/tests/integrationCritical/expected.json +++ b/tests/e2e/ui/tests/integrationCritical/expected.json @@ -1,5 +1,6 @@ [ "tests/e2e/ui/tests/integrationCritical/projectDetachment.spec.ts::project creation and explicit detachment preserve saved scope and restore serving", + "tests/e2e/ui/tests/integrationCritical/otelInternalSpans.spec.ts::team logging settings persist otel_internal_spans exclude through the callback editor", "tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts::per-user MCP env var stays updatable and clearable from the card after it is set", "tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts::cancelling the clear confirmation keeps the stored value and sends no delete", "tests/e2e/ui/tests/integrationCritical/mcpUserEnvVars.spec.ts::pressing Enter on Update opens the credentials modal instead of the server editor", diff --git a/tests/e2e/ui/tests/integrationCritical/otelInternalSpans.spec.ts b/tests/e2e/ui/tests/integrationCritical/otelInternalSpans.spec.ts new file mode 100644 index 00000000000..58ba64415a1 --- /dev/null +++ b/tests/e2e/ui/tests/integrationCritical/otelInternalSpans.spec.ts @@ -0,0 +1,79 @@ +import { test, expect } from "@playwright/test"; +import { randomUUID } from "node:crypto"; +import { Page } from "../../fixtures/pages"; +import { navigateToPage } from "../../helpers/navigation"; +import { captureRequestBody, readBack } from "../../helpers/roundTrip"; + +test("team logging settings persist otel_internal_spans exclude through the callback editor", async ({ + page, + request, +}) => { + const master = process.env.LITELLM_MASTER_KEY ?? "sk-integration-master"; + const headers = { Authorization: `Bearer ${master}` }; + const prefix = `integration-browser-${randomUUID()}`; + const post = async (url: string, data: object) => { + const response = await request.post(url, { headers, data }); + expect(response.ok(), `${url}: ${await response.text()}`).toBe(true); + return response.json(); + }; + const team = await post("/team/new", { team_alias: prefix }); + try { + await page.goto("/ui/login"); + await page.getByPlaceholder("Enter your username").fill("admin"); + await page.getByPlaceholder("Enter your password").fill(master); + await page.getByRole("button", { name: "Login", exact: true }).click(); + await expect(page).toHaveURL( + (url) => url.pathname.startsWith("/ui") && !url.pathname.includes("login"), + ); + await navigateToPage(page, Page.Teams); + await page.getByRole("button", { name: new RegExp(`^${prefix}`) }).click(); + await page.getByRole("tab", { name: "Settings" }).click(); + await page.getByRole("button", { name: "Edit Settings" }).click(); + await page + .getByRole("button", { name: "Add Integration", exact: true }) + .click(); + await page + .getByRole("combobox") + .filter({ hasText: "Select integration" }) + .click(); + await page + .getByRole("option", { name: /Langfuse OTEL/ }) + .click(); + const internalSpans = page.getByRole("combobox", { + name: "otel internal spans", + }); + await internalSpans.click(); + await expect( + page.getByRole("option", { name: "include", exact: true }), + ).toBeVisible(); + await page + .getByRole("option", { name: "exclude", exact: true }) + .click(); + const update = await captureRequestBody( + page, + { method: "POST", urlIncludes: "/team/update" }, + async () => { + await page.getByRole("button", { name: "Save Changes" }).click(); + }, + ); + const logging = (update.metadata as { logging: any[] }).logging; + expect(logging).toEqual([ + { + callback_name: "langfuse_otel", + callback_type: "success", + callback_vars: { otel_internal_spans: "exclude" }, + }, + ]); + await expect( + page.getByText("Team settings updated successfully"), + ).toBeVisible(); + const info = await readBack<{ + team_info: { metadata: { logging: any[] } }; + }>(page, `/team/info?team_id=${team.team_id}`); + expect( + info.team_info.metadata.logging[0].callback_vars.otel_internal_spans, + ).toBe("exclude"); + } finally { + await post("/team/delete", { team_ids: [team.team_id] }); + } +});