test: prove browser click workflow lifecycle

This commit is contained in:
lda
2026-06-15 00:27:33 +07:00 Verified
parent bc543519e1
commit 58dc54cf87
3 changed files with 212 additions and 0 deletions
@@ -0,0 +1,6 @@
{
"button_label": "Launch Workflow",
"open_browser": false,
"simulate": true,
"timeout_seconds": 2
}
@@ -0,0 +1,33 @@
{
"version": 1,
"client": {
"target": {
"kind": "rpc_http",
"url": "http://127.0.0.1:8772/rpc",
"timeout_seconds": 30
}
},
"server": {
"store": {
"kind": "filesystem",
"root": ".wf_browser_click_store"
},
"transports": [
{
"kind": "rpc_http",
"host": "127.0.0.1",
"port": 8772,
"path": "/rpc"
}
],
"sources": [
{
"kind": "python",
"id": "local.browser_click",
"path": ".",
"module": "ops",
"registry": "registry"
}
]
}
}
@@ -62,3 +62,176 @@ def test_browser_click_source_human_timeout_cleans_up() -> None:
)
)
assert _active_session_count() == 0
from pathlib import Path
from wf_config import load_workflow_config
from wf_server.config import build_workflow_server_from_workflow_config
EXAMPLE_DIR = Path(__file__).resolve().parents[2] / "examples" / "browser_click_workflow"
async def test_browser_click_workflow_artifact_deployment_run_path(tmp_path) -> None:
config = load_workflow_config(EXAMPLE_DIR / "wf.config.json")
config.server.store.root = tmp_path / "store"
server = build_workflow_server_from_workflow_config(config)
plan = {
"name": "browser_click_case_study",
"input_schema": {
"type": "object",
"properties": {
"button_label": {"type": "string"},
"open_browser": {"type": "boolean"},
"simulate": {"type": "boolean"},
"timeout_seconds": {"type": "number"},
},
"required": ["button_label", "open_browser", "simulate", "timeout_seconds"],
},
"state_schema": {
"type": "object",
"properties": {
"opened": {"type": "object", "reducer": "wf.std.replace"},
"clicked": {"type": "object", "reducer": "wf.std.replace"},
"result": {"type": "object", "reducer": "wf.std.replace"},
},
},
"output_schema": {
"type": "object",
"properties": {
"before": {"type": "object"},
"after": {"type": "object"},
"closed": {"type": "boolean"},
},
"required": ["before", "after", "closed"],
},
"outcomes": ["ok"],
"start": "open",
"nodes": [
{
"id": "open",
"type": "node",
"node": "local.browser_click.open_click_page",
"input": [
{
"path": {"root": "input", "parts": ["button_label"]},
"target": {"root": "local", "parts": ["button_label"]},
},
{
"path": {"root": "input", "parts": ["open_browser"]},
"target": {"root": "local", "parts": ["open_browser"]},
},
],
"output": [
{
"source": {"root": "local", "parts": []},
"target": {"root": "state", "parts": ["opened"]},
}
],
},
{
"id": "wait",
"type": "node",
"node": "local.browser_click.wait_for_click",
"input": [
{
"path": {"root": "state", "parts": ["opened", "session_id"]},
"target": {"root": "local", "parts": ["session_id"]},
},
{
"path": {"root": "input", "parts": ["simulate"]},
"target": {"root": "local", "parts": ["simulate"]},
},
{
"path": {"root": "input", "parts": ["timeout_seconds"]},
"target": {"root": "local", "parts": ["timeout_seconds"]},
},
],
"output": [
{
"source": {"root": "local", "parts": []},
"target": {"root": "state", "parts": ["clicked"]},
}
],
},
{
"id": "collect",
"type": "node",
"node": "local.browser_click.collect_snapshots",
"input": [
{
"path": {"root": "state", "parts": ["opened", "session_id"]},
"target": {"root": "local", "parts": ["session_id"]},
},
{
"path": {"root": "state", "parts": ["opened", "before"]},
"target": {"root": "local", "parts": ["before"]},
},
{
"path": {"root": "state", "parts": ["clicked", "after"]},
"target": {"root": "local", "parts": ["after"]},
},
],
"output": [
{
"source": {"root": "local", "parts": []},
"target": {"root": "state", "parts": ["result"]},
}
],
},
],
"edges": [
{"from": "open", "outcome": "ok", "to": "wait"},
{"from": "wait", "outcome": "ok", "to": "collect"},
{"from": "collect", "outcome": "ok", "to": "__end__"},
],
"output": [
{
"path": {"root": "state", "parts": ["result", "before"]},
"target": {"root": "local", "parts": ["before"]},
},
{
"path": {"root": "state", "parts": ["result", "after"]},
"target": {"root": "local", "parts": ["after"]},
},
{
"path": {"root": "state", "parts": ["result", "closed"]},
"target": {"root": "local", "parts": ["closed"]},
},
],
}
await server.api.create_artifact_from_plan(
artifact_id="browser_click_case_study",
version=1,
title="Browser Click Case Study",
plan=plan,
outcomes=["ok"],
source_bindings={"local.browser_click": "local.browser_click"},
)
await server.api.save_deployment(
{
"id": "browser_click_case_study.default",
"artifact_id": "browser_click_case_study",
"artifact_version": 1,
"bindings": {"local.browser_click": "local.browser_click"},
}
)
run = await server.api.run_deployment(
deployment_id="browser_click_case_study.default",
workflow_input={
"button_label": "Launch Workflow",
"open_browser": False,
"simulate": True,
"timeout_seconds": 2,
},
)
assert run["status"] == "completed"
assert run["output"]["before"]["clicked"] is False
assert run["output"]["after"]["clicked"] is True
assert run["output"]["after"]["status_text"] == "Button clicked"
assert run["output"]["closed"] is True
assert run["trace_count"] >= 3