Files
app/frontend/tests/drafts.spec.ts
T
stroblmeandClaude Fable 5 143395358a Delete the flows and users the Playwright specs create
The specs run against a development stack, so every run left a test_flow_*
in someone's flow list. Each spec now tears down what it made in an afterAll,
which runs whether or not the tests passed, and the three copies of the API
helper move into tests/utils/api.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7LwYgJfpkbLCTeiAf8U4A
2026-08-16 16:46:07 +02:00

88 lines
3.0 KiB
TypeScript

import { expect, test } from "@playwright/test"
import { api, deleteAll } from "./utils/api"
/**
* Editing writes a draft; only publishing hands it to the engine. The two
* things worth proving here are that the engine ignores a draft until it is
* published, and that a second client cannot quietly overwrite the first.
*/
const flowName = `test_draft_${Date.now().toString(36)}`
test.use({ storageState: "playwright/.auth/user.json" })
test.describe.configure({ mode: "serial" })
test.afterAll(async ({ browser }) => {
await deleteAll(browser, [`/flows/${flowName}`])
})
test("a draft stays off the engine until it is published", async ({ page }) => {
await page.goto("/flows")
await page.getByRole("button", { name: "New flow" }).click()
await page.getByTestId("flow-name-input").fill(flowName)
await page.getByRole("button", { name: "Create flow" }).click()
await page.waitForURL(`/flows/${flowName}`)
await page.getByTestId("add-node").click()
await page
.getByRole("option", { name: /function/i })
.first()
.click()
await expect(page.locator(".react-flow__node")).toHaveCount(1)
// Adding a node opens its panel, and the floating chrome steps aside for it.
await page.keyboard.press("Escape")
await expect(page.getByTestId("publish-flow")).toBeVisible()
// Nothing of this flow is loaded while it is only a draft.
await page.waitForTimeout(1500)
const before = await (await api(page, `/flows/${flowName}/state`)).json()
expect(before.nodes).toHaveLength(0)
await page.getByTestId("publish-flow").click()
await expect(page.getByTestId("publish-flow")).toBeHidden()
const after = await (await api(page, `/flows/${flowName}/state`)).json()
expect(after.nodes.length).toBeGreaterThan(0)
})
test("a save against a version someone else moved on from is refused", async ({
page,
}) => {
await page.goto(`/flows/${flowName}`)
await page.waitForSelector(".react-flow__node")
const detail = await (await api(page, `/flows/${flowName}`)).json()
// Stand in for a second client that saved first.
const first = await api(page, `/flows/${flowName}`, {
method: "PUT",
data: { ...detail.definition, title: "Theirs" },
})
expect(first.ok()).toBeTruthy()
const stale = await api(page, `/flows/${flowName}`, {
method: "PUT",
data: { ...detail.definition, title: "Mine" },
})
expect(stale.status()).toBe(409)
expect((await stale.json()).detail.current_version).toBe(
detail.definition.version + 1,
)
})
test("discarding a draft goes back to the published flow", async ({ page }) => {
await page.goto(`/flows/${flowName}`)
await page.waitForSelector(".react-flow__node")
await page.getByTestId("edit-flow").click()
await page.getByTestId("discard-draft").click()
await page.getByTestId("confirm-discard-draft").click()
await expect(page.getByTestId("publish-flow")).toBeHidden()
const detail = await (await api(page, `/flows/${flowName}`)).json()
expect(detail.has_draft).toBe(false)
expect(detail.definition.title).not.toBe("Theirs")
})