from __future__ import annotations import subprocess import textwrap from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] def run_node_scenario(source: str) -> subprocess.CompletedProcess[str]: return subprocess.run( ["node", "--input-type=module"], input=source, cwd=REPO_ROOT, text=True, capture_output=True, check=False, ) def test_sidebar_workflow_load_clone_gets_fresh_id_without_mutating_store_copy() -> None: script = textwrap.dedent( """ import assert from "node:assert/strict"; import { cloneWorkflowForTemporaryLoad } from "./web/sidebar/workflow_payload.js"; const stored = { id: "original-workflow-id", nodes: [{ id: 1, type: "KSampler", widgets_values: [42] }], links: [], extra: { ds: { scale: 1, offset: [0, 0] } }, version: 0.4, }; const loaded = cloneWorkflowForTemporaryLoad(stored); assert.notEqual(loaded, stored); assert.equal(stored.id, "original-workflow-id"); assert.notEqual(loaded.id, stored.id); assert.match(loaded.id, /^[0-9a-f-]{36}$/i); assert.deepEqual(loaded.nodes, stored.nodes); loaded.nodes[0].widgets_values[0] = 100; assert.equal(stored.nodes[0].widgets_values[0], 42); """ ) result = run_node_scenario(script) assert result.returncode == 0, result.stderr def test_sidebar_workflow_load_clone_can_use_stable_temp_id() -> None: script = textwrap.dedent( """ import assert from "node:assert/strict"; import { cloneWorkflowForTemporaryLoad } from "./web/sidebar/workflow_payload.js"; const stored = { id: "original-workflow-id", nodes: [{ id: 1, type: "KSampler", widgets_values: [42] }], links: [], extra: { ds: { scale: 1, offset: [0, 0] } }, version: 0.4, }; const first = cloneWorkflowForTemporaryLoad(stored, "Shots\\u0000Bear\\u0000Render"); const second = cloneWorkflowForTemporaryLoad(stored, "Shots\\u0000Bear\\u0000Render"); const other = cloneWorkflowForTemporaryLoad(stored, "Shots\\u0000Bear\\u0000Archived"); assert.equal(first.id, second.id); assert.notEqual(first.id, other.id); assert.notEqual(first.id, stored.id); assert.match(first.id, /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-8[0-9a-f]{3}-[0-9a-f]{12}$/i); assert.equal(stored.id, "original-workflow-id"); """ ) result = run_node_scenario(script) assert result.returncode == 0, result.stderr def test_sidebar_workflow_load_clone_treats_empty_key_as_stable() -> None: script = textwrap.dedent( """ import assert from "node:assert/strict"; import { cloneWorkflowForTemporaryLoad } from "./web/sidebar/workflow_payload.js"; const first = cloneWorkflowForTemporaryLoad({ id: "original" }, ""); const second = cloneWorkflowForTemporaryLoad({ id: "original" }, ""); const random = cloneWorkflowForTemporaryLoad({ id: "original" }); assert.equal(first.id, second.id); assert.notEqual(first.id, random.id); assert.match(first.id, /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-8[0-9a-f]{3}-[0-9a-f]{12}$/i); """ ) result = run_node_scenario(script) assert result.returncode == 0, result.stderr