import { expect, test } from "@playwright/test" import { api, apiPage, deleteAll } from "./utils/api" /** * What a message carrying a dictionary looks like in a panel four hundred * pixels wide. * * The regression this exists for: a record or an artifact reference was * serialised into the row, and the panel widened until the type selects and * the buttons beside them were pushed off the edge. The shape shows instead, * and the contents unfold on request — so the check is both that the summary * is what appears, and that the panel is still the width it was told to be. */ const flowName = `test_values_${Date.now().toString(36)}` /** The panel's fixed width; the whole point is that a value cannot change it. */ const PANEL_WIDTH = 400 test.use({ storageState: "playwright/.auth/user.json" }) test.describe.configure({ mode: "serial" }) test.beforeAll(async ({ browser }) => { const page = await apiPage(browser) await api(page, `/flows/${flowName}`, { method: "PUT", data: { name: flowName, title: "Values", version: 1, nodes: [ { id: "emit", type: "python", provides: [ { name: "shape", dtype: "record" }, { name: "label", dtype: "str" }, ], }, ], }, }) // Saving writes a draft and moves the version on, so publish what is // actually there rather than what it was a moment ago. const draft = await (await api(page, `/flows/${flowName}?draft=true`)).json() await api(page, `/flows/${flowName}/publish`, { method: "POST", data: { version: draft.definition.version }, }) // Values a flow could plausibly hold: one structured, one longer than the // room a 400px panel has for it. await api(page, `/messages/${flowName}.shape`, { method: "POST", data: { value: { title: "Recovered", body: "R2 = 0.98", severity: "info" }, }, }) await api(page, `/messages/${flowName}.label`, { method: "POST", data: { value: "ubuntu-gpu-node-01.lab.internal (numpy 2.5.2, cuda 12.4)", }, }) await page.close() }) test.afterAll(async ({ browser }) => { await deleteAll(browser, [`/flows/${flowName}`]) }) test("a dictionary shows its shape, and its contents on request", async ({ page, }) => { await page.goto(`/flows/${flowName}`) const node = page.locator(".react-flow__node").first() await node.waitFor({ timeout: 20000 }) await node.click() const panel = page.locator('aside[role="complementary"]').first() await expect(panel).toBeVisible() // The shape, not the values. const summary = page.getByTestId("value-preview-toggle") await expect(summary).toContainText("record · 3 fields") await expect(panel).not.toContainText("Recovered") // A value cannot push the panel open, however long it is. expect((await panel.boundingBox())?.width).toBe(PANEL_WIDTH) // The contents are one click away. await summary.click() await expect(panel).toContainText("Recovered") expect((await panel.boundingBox())?.width).toBe(PANEL_WIDTH) })