Skip to content

Commit c8fc815

Browse files
Merge pull request #1343 from oriontech-me/fix/issue-1342-auto-save-off-use-open-flow-by-id
fix(flow-functionality): enter the flow through openFlowById (#1342)
2 parents ebb3c80 + 1687442 commit c8fc815

2 files changed

Lines changed: 57 additions & 11 deletions

File tree

docs/flow-functionality/auto-save-off.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ before anything else runs.
5858
3. Leave via the back button (`icon-ChevronLeft`); the unsaved-changes dialog
5959
("Unsaved changes will be permanently lost.") appears — click **Exit Anyway**;
6060
assert the editor was left
61-
4. Re-open the flow **by id** (`/flow/<id>`, waiting for its
62-
`GET /api/v1/flows/<id>` to resolve and the canvas to mount); assert the
61+
4. Re-open the flow **by id** via `openFlowById` (`/flow/<id>`; the helper gates
62+
on the canvas mounting and on the flow being writable, and the spec
63+
additionally waits for the flow's own `GET /api/v1/flows/<id>` so the count
64+
below cannot read a canvas whose graph has not been applied); assert the
6365
canvas has **0** nodes (`div-generic-node` count = 0) — the edit was discarded
6466
5. Add the Chat Input component again (hover the sidebar entry →
6567
`add-component-button-chat-input`)
@@ -107,8 +109,12 @@ fails if either save did not persist (see Notes on the hardening).
107109
search. Adds use the draggable wrapper hover → add button (the sidebar row is
108110
briefly `pointer-events-none`; dragging it is unreliable).
109111
- `data-testid="title-Chat Input"` / `div-generic-node` — node presence on canvas.
110-
- `GET /api/v1/flows/{id}` and the `/flow/{id}` route — the re-open path (see the
111-
#1336 note below for why this is not the flows-list card).
112+
- `GET /api/v1/flows/{id}` and the `/flow/{id}` route — the re-open path, entered
113+
through `helpers/flows/open-flow-by-id.ts` (see the #1336 note below for why
114+
this is not the flows-list card).
115+
- `helpers/ui/assistant-onboarding.ts` — the onboarding flag is seeded before the
116+
first navigation, so the tooltip upstream arms at canvas mount + 10 s cannot
117+
land over the canvas-controls bar this spec clicks four times.
112118
- No API key — the Chat Input / Chat Output components are added to the graph,
113119
never executed.
114120

@@ -151,6 +157,22 @@ fails if either save did not persist (see Notes on the hardening).
151157
again, from the other side). The re-open is therefore by URL, and each exit now
152158
asserts the editor was left — verified by forcing the save PATCH to 500, which
153159
now fails at the exit step instead of 45 s later on an unrelated locator.
160+
- **#1342 (the re-open uses the repo's by-id entry, not a local `goto`).** #1336's
161+
fix hand-rolled `page.goto('/flow/{id}')` + a canvas wait, which was the fourth
162+
copy of the block `helpers/flows/open-flow-by-id.ts` (#1214) was extracted to
163+
stop. Migrated to `openFlowById`, which adds two guarantees the copy did not
164+
have: the onboarding overlay cannot appear, and the editor is not handed back
165+
while `POST /api/v1/authz/me/permissions` is still in flight — the #1005 window
166+
in which a mutation is silently swallowed, and this spec adds a component
167+
immediately after two of the three re-opens. **One thing did not come from the
168+
helper and must stay**: the wait on the flow's own `GET /api/v1/flows/{id}`.
169+
`openFlowById` returns on `canvas_controls_dropdown` + writability, neither of
170+
which implies the graph has been applied — and the discard assertion
171+
(`div-generic-node` count = 0) is the one check that PASSES VACUOUSLY on a
172+
canvas that has not painted its nodes yet. The seed is called at the top of the
173+
test rather than left to the helper, because upstream arms the tooltip at canvas
174+
mount + 10 s over the bar `adjustScreenView` clicks, and the first editing phase
175+
(two of those calls, plus the on-canvas save) happens before any re-open.
154176
- **#790 (load-collateral, critical clicks hardened).** On load-degraded /
155177
guard-tripped dailies (2026-07-15/16) the spec failed with
156178
`locator.click: Timeout 20000ms exceeded` on a manual-save click target. Not a

tests/tests-automations/regression/flow-functionality/auto-save-off.spec.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { adjustScreenView } from "../../../helpers/ui/adjust-screen-view";
44
import { awaitBootstrapTest } from "../../../helpers/other/await-bootstrap-test";
55
import { getAuthToken } from "../../../helpers/auth/get-auth-token";
66
import { deleteFlow } from "../../../helpers/flows/delete-flow";
7+
import { openFlowById } from "../../../helpers/flows/open-flow-by-id";
8+
import { seedAssistantDiscovered } from "../../../helpers/ui/assistant-onboarding";
79

810
// Capture every flow THIS page creates from its POST /api/v1/flows → 201
911
// responses and delete them id-scoped in afterEach. awaitBootstrapTest runs
@@ -98,23 +100,35 @@ async function expectLeftEditor(page: Page): Promise<void> {
98100
* reload proves that more strictly than an SPA route change. The
99101
* "open a flow from its list card" path stays covered by the specs whose
100102
* subject it is (`bulk-actions`, `mcp-server`).
103+
*
104+
* The entry itself is `openFlowById` (#1214/#1342), not a local `goto` — #1336's
105+
* fix hand-rolled this block and became the fourth copy of exactly what that
106+
* helper was extracted to stop. Two of its guarantees matter here and the copy
107+
* had neither: the onboarding overlay cannot appear, and the editor is not handed
108+
* back while `POST /api/v1/authz/me/permissions` is still in flight — the #1005
109+
* window where a mutation is silently swallowed, and this spec adds a component
110+
* immediately after two of the three re-opens.
111+
*
112+
* What does NOT come from the helper is the flow-load wait below. Keep it.
101113
*/
102114
async function reopenFlow(page: Page, flowId: string): Promise<void> {
103-
// The graph is applied to the canvas only after this GET resolves; waiting on
104-
// it is what keeps the `div-generic-node` counts below from reading an empty
105-
// canvas that simply had not rendered yet.
115+
// Ordering gate, registered BEFORE the navigation the helper performs.
116+
//
117+
// `openFlowById` returns on `canvas_controls_dropdown` + writability, and
118+
// neither implies the graph has been applied — the canvas chrome renders before
119+
// the nodes do. That matters for exactly one assertion and it is the one most
120+
// easily fooled: the discard check is `div-generic-node` count === 0, which
121+
// PASSES VACUOUSLY on a canvas that has not painted its nodes yet. So the count
122+
// is ordered after the flow's own GET, which is what applies the graph.
106123
const flowLoaded = page.waitForResponse(
107124
(resp) =>
108125
new URL(resp.url()).pathname === `/api/v1/flows/${flowId}` &&
109126
resp.request().method() === "GET" &&
110127
resp.status() === 200,
111128
{ timeout: 45000 },
112129
);
113-
await page.goto(`/flow/${flowId}`);
130+
await openFlowById(page, flowId);
114131
await flowLoaded;
115-
await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
116-
timeout: 45000,
117-
});
118132
}
119133

120134
test(
@@ -123,6 +137,16 @@ test(
123137
async ({ page }) => {
124138
trackCreatedFlows(page);
125139

140+
// Seeded HERE, not left to `openFlowById`'s own call, and the difference is
141+
// measurable rather than tidiness: upstream arms the onboarding tooltip at
142+
// canvas mount + 10 s and paints it OVER the canvas-controls bar, which is
143+
// what `adjustScreenView` clicks (#1220's measurement). This test calls
144+
// `adjustScreenView` four times across a ~15–25 s run, so the first editing
145+
// phase — before any re-open — is inside that window. `addInitScript` only
146+
// applies to loads that follow it, so it has to precede the bootstrap's
147+
// navigation; the helper's later calls are idempotent per page.
148+
await seedAssistantDiscovered(page);
149+
126150
await page.route("**/api/v1/config", (route) => {
127151
route.fulfill({
128152
status: 200,

0 commit comments

Comments
 (0)