The clipboard spec selected text in the previous node's panel while it was still sliding out after the paste, so the selection collapsed when it unmounted and the canvas took the copy. The values spec read the panel's box mid-slide-in, where the translate leaves the width a float off 400. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
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. Polled, because
|
|
// the panel slides in and a box read mid-slide is a hair off 400.
|
|
await expect
|
|
.poll(async () => (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)
|
|
})
|