feat: export draft documents

This commit is contained in:
lda
2026-07-29 09:39:55 +07:00 Verified
parent 2e98ece805
commit 8b9c11e87b
4 changed files with 209 additions and 1 deletions
+106
View File
@@ -2874,3 +2874,109 @@ def test_wf_draft_set_workflow_output_merge_keeps_compatibility_map_handler(
"merge": True,
}
]
def test_wf_draft_export_writes_only_formatted_draft_document(
monkeypatch,
tmp_path,
) -> None:
calls: list[dict[str, Any]] = []
expected_draft = {
"name": "report",
"steps": {"finish": {"end": {}}},
"routes": {},
}
class FakeHandlers:
async def get_draft_workspace(self, **kwargs: Any) -> dict[str, Any]:
calls.append(kwargs)
return {
"workspace_id": "report",
"revision": 4,
"draft": expected_draft,
}
context = SimpleNamespace(handlers=FakeHandlers(), verbose=False)
monkeypatch.setattr("wf_cli.commands.drafts.load_cli_context", lambda _ctx: context)
output_path = tmp_path / "report-draft.json"
result = runner.invoke(
app,
[
"draft",
"export",
"report",
"--output",
str(output_path),
],
)
assert result.exit_code == 0, result.output
assert calls == [{"workspace_id": "report", "include_draft": True}]
assert json.loads(output_path.read_text(encoding="utf-8")) == expected_draft
assert output_path.read_text(encoding="utf-8") == (
json.dumps(expected_draft, indent=2, sort_keys=True) + "\n"
)
def test_wf_draft_export_requires_force_to_replace_existing_file(
monkeypatch,
tmp_path,
) -> None:
class FakeHandlers:
async def get_draft_workspace(self, **_kwargs: Any) -> dict[str, Any]:
return {"draft": {"name": "replacement"}}
context = SimpleNamespace(handlers=FakeHandlers(), verbose=False)
monkeypatch.setattr("wf_cli.commands.drafts.load_cli_context", lambda _ctx: context)
output_path = tmp_path / "report-draft.json"
output_path.write_text('{"name": "existing"}\n', encoding="utf-8")
refused = runner.invoke(
app,
["draft", "export", "report", "--output", str(output_path)],
)
replaced = runner.invoke(
app,
[
"draft",
"export",
"report",
"--output",
str(output_path),
"--force",
],
)
assert refused.exit_code == 2
assert "already exists" in refused.output
assert replaced.exit_code == 0, replaced.output
assert json.loads(output_path.read_text(encoding="utf-8")) == {
"name": "replacement"
}
def test_wf_draft_export_reports_missing_parent_directory(
monkeypatch,
tmp_path,
) -> None:
class FakeHandlers:
async def get_draft_workspace(self, **_kwargs: Any) -> dict[str, Any]:
return {"draft": {"name": "report"}}
context = SimpleNamespace(handlers=FakeHandlers(), verbose=False)
monkeypatch.setattr("wf_cli.commands.drafts.load_cli_context", lambda _ctx: context)
result = runner.invoke(
app,
[
"draft",
"export",
"report",
"--output",
str(tmp_path / "missing" / "report-draft.json"),
],
)
assert result.exit_code == 2
assert "could not write file" in result.output
+52
View File
@@ -820,6 +820,58 @@ def test_wf_remote_capability_free_draft_lifecycle(monkeypatch, tmp_path) -> Non
assert set(payload["draft"]["steps"]) == {"gate", "finish"}
def test_wf_draft_export_uses_remote_get_and_writes_only_draft(
monkeypatch, tmp_path
) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
_patch_rpc_client_to_server(monkeypatch, server)
rpc_calls: list[tuple[str, dict[str, Any]]] = []
original_call = RpcClientTransport._call
async def recording_call(
self: RpcClientTransport, method: str, params: dict[str, Any]
) -> dict[str, Any]:
rpc_calls.append((method, params))
return await original_call(self, method, params)
monkeypatch.setattr(RpcClientTransport, "_call", recording_call)
config_path = tmp_path / "wf.json"
config_path.write_text('{"version": 1}', encoding="utf-8")
runner = CliRunner()
base_args = ["--config", str(config_path), "--url", "http://test/rpc"]
created = runner.invoke(
app,
[*base_args, "draft", "create", "export_ws", "--name", "report"],
)
assert created.exit_code == 0, created.output
rpc_calls.clear()
output_path = tmp_path / "exported-draft.json"
exported = runner.invoke(
app,
[
*base_args,
"draft",
"export",
"export_ws",
"--output",
str(output_path),
],
)
assert exported.exit_code == 0, exported.output
assert rpc_calls == [
(
"workflow.draft_workspaces.get",
{"workspace_id": "export_ws", "include_draft": True},
)
]
payload = json.loads(output_path.read_text(encoding="utf-8"))
assert payload["name"] == "report"
assert "workspace_id" not in payload
assert "revision" not in payload
def test_wf_remote_run_resume_interrupted_deployment(monkeypatch, tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
asyncio.run(