Let a function node's own settings be edited
A python node's params reach process() as whatever its author put there, but there was no way to put anything there: the settings form is built from a type's declared schema, and a function node declares none. Node types now say whether they take settings beyond their schema, and the panel offers a key/value editor for the ones that do — named, typed as text, number, on/off or JSON, and laid out like the port list beside it. Rows are keyed by position rather than by name, so renaming a setting does not remount the row and lose what was being typed into it. Verified in the running app in both themes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/** Feature check: the free-form settings editor on a function node. */
|
||||
import { mkdir } from "node:fs/promises"
|
||||
import { chromium } from "@playwright/test"
|
||||
|
||||
const APP_URL = process.env.APP_URL || "http://app.localhost"
|
||||
const EMAIL = process.env.FIRST_SUPERUSER
|
||||
const PASSWORD = process.env.FIRST_SUPERUSER_PASSWORD
|
||||
const OUT = process.env.SCREENSHOT_DIR || "screenshots"
|
||||
|
||||
const browser = await chromium.launch()
|
||||
for (const theme of ["light", "dark"]) {
|
||||
const dir = `${OUT}/${theme}`
|
||||
await mkdir(dir, { recursive: true })
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1440, height: 900 },
|
||||
colorScheme: theme,
|
||||
})
|
||||
await context.addInitScript((t) => {
|
||||
localStorage.setItem("fluksio-ui-theme", t)
|
||||
}, theme)
|
||||
const page = await context.newPage()
|
||||
|
||||
await page.goto(`${APP_URL}/login`, { waitUntil: "networkidle" })
|
||||
await page.getByTestId("email-input").fill(EMAIL)
|
||||
await page.getByTestId("password-input").fill(PASSWORD)
|
||||
await page.getByRole("button", { name: /log in/i }).click()
|
||||
await page.waitForURL(`${APP_URL}/`, { timeout: 15000 })
|
||||
|
||||
await page.goto(`${APP_URL}/flows`, { waitUntil: "networkidle" })
|
||||
const seed = page.getByTestId("create-first-flow")
|
||||
if (await seed.count()) {
|
||||
await seed.click()
|
||||
await page.waitForURL(/\/flows\/.+/, { timeout: 15000 })
|
||||
}
|
||||
if (!(await page.locator(".react-flow__node").count())) {
|
||||
await page.getByTestId("add-node").click()
|
||||
await page
|
||||
.getByRole("option", { name: /function/i })
|
||||
.first()
|
||||
.click()
|
||||
await page.waitForSelector(".react-flow__node")
|
||||
}
|
||||
await page.locator(".react-flow__node").first().click()
|
||||
await page.waitForSelector("[data-testid=node-panel]", { timeout: 15000 })
|
||||
|
||||
// Add two settings and give them values.
|
||||
await page.getByTestId("add-param").click()
|
||||
await page.waitForTimeout(300)
|
||||
const names = page.getByLabel("Setting name")
|
||||
const values = page.getByLabel("Setting value")
|
||||
await names.first().fill("threshold")
|
||||
await names.first().blur()
|
||||
await page.waitForTimeout(200)
|
||||
await page.getByLabel("Type").first().click()
|
||||
await page.getByRole("option", { name: "number" }).click()
|
||||
await page.waitForTimeout(200)
|
||||
await values.first().fill("21.5")
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await page.getByTestId("add-param").click()
|
||||
await page.waitForTimeout(300)
|
||||
await names.nth(1).fill("label")
|
||||
await names.nth(1).blur()
|
||||
await page.waitForTimeout(200)
|
||||
await values.nth(1).fill("living room")
|
||||
await page.waitForTimeout(1200)
|
||||
|
||||
await page.screenshot({ path: `${dir}/app-node-params.png` })
|
||||
console.log(` wrote ${dir}/app-node-params.png`)
|
||||
await context.close()
|
||||
}
|
||||
await browser.close()
|
||||
Reference in New Issue
Block a user