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: "research-gpu-worker.example.test (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)
|
|
})
|