11 deleted/transferred tests because wf_api has some

This commit is contained in:
lda
2026-06-02 03:53:05 +07:00 Verified
parent 69de023a89
commit 4e28c8db5d
8 changed files with 769 additions and 333 deletions
+12
View File
@@ -157,6 +157,11 @@ def test_list_capabilities_includes_saved_wrapper() -> None:
assert row["kind"] == "wrapper_artifact"
assert row["artifact_id"] == "echo_wrapper"
assert row["version"] == 1
assert row["title"] == "Echo"
assert row["description"] == "Reusable echo wrapper."
assert row["outcomes"] == ["completed"]
assert row["input_fields"] == ["text"]
assert row["output_fields"] == ["echoed"]
def test_inspect_capability_saved_wrapper() -> None:
@@ -177,8 +182,15 @@ def test_inspect_capability_saved_wrapper() -> None:
assert detail["kind"] == "wrapper_artifact"
assert detail["artifact_id"] == "echo_wrapper"
assert detail["outcomes"] == ["completed"]
assert "input_schema" in detail
assert detail["input_schema"]["properties"]["text"]["type"] == "string"
assert detail["output_schema"]["properties"]["echoed"]["type"] == "string"
hints = detail["wrapper_hints"]
assert hints["capability_name"] == "workflow.echo_wrapper.v1"
assert hints["declared_outcomes"] == ["completed"]
assert hints["suggested_wrapper_outcomes"] == ["completed"]
assert hints["input_map"] == {"input.text": "text"}
assert hints["output_map"] == {"echoed": "state.echoed"}
def test_call_capability_saved_wrapper() -> None:
+129
View File
@@ -108,6 +108,67 @@ def test_create_draft_workspace_creates_workspace() -> None:
assert result["workspace_id"] == "echo_ws"
assert result["revision"] == 1
fetched = asyncio.run(
api.get_draft_workspace(workspace_id="echo_ws", include_draft=True)
)
assert fetched["workspace_id"] == "echo_ws"
assert fetched["title"] == "Echo Workspace"
assert fetched["draft"]["steps"]["echo"]["use"] == "demo.personal.echo_tool"
def test_list_draft_workspaces_returns_sorted_summaries_without_drafts() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "drafts_list_workspaces"
)
api, _service = _draft_api(artifact_store)
asyncio.run(
api.create_draft_workspace(
workspace_id="b_draft",
title="B Draft",
draft=_echo_draft(),
)
)
asyncio.run(
api.create_draft_workspace(
workspace_id="a_draft",
title="A Draft",
draft=_echo_draft(),
)
)
result = asyncio.run(api.list_draft_workspaces())
assert [workspace["workspace_id"] for workspace in result["workspaces"]] == [
"a_draft",
"b_draft",
]
assert result["workspaces"][0]["title"] == "A Draft"
assert "draft" not in result["workspaces"][0]
def test_delete_draft_workspace_is_idempotent() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "drafts_delete_workspace"
)
api, _service = _draft_api(artifact_store)
asyncio.run(
api.create_draft_workspace(
workspace_id="echo_ws",
draft=_echo_draft(),
)
)
deleted = asyncio.run(api.delete_draft_workspace(workspace_id="echo_ws"))
deleted_again = asyncio.run(api.delete_draft_workspace(workspace_id="echo_ws"))
listed = asyncio.run(api.list_draft_workspaces())
assert deleted["workspace_id"] == "echo_ws"
assert deleted["deleted"] is True
assert deleted["status"] == "deleted"
assert deleted_again["workspace_id"] == "echo_ws"
assert deleted_again["deleted"] is False
assert deleted_again["status"] == "not_found"
assert listed["workspaces"] == []
def test_patch_draft_workspace_updates_revision() -> None:
@@ -134,6 +195,74 @@ def test_patch_draft_workspace_updates_revision() -> None:
assert patched["status"] == "valid"
def test_draft_workspace_patch_helpers_update_revision_and_bindings() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "drafts_patch_helpers"
)
api, _service = _draft_api(artifact_store)
asyncio.run(
api.create_draft_workspace(
workspace_id="echo_ws",
draft=_echo_draft(),
)
)
named = asyncio.run(
api.set_draft_name(
workspace_id="echo_ws",
revision=1,
name="echo_v2",
)
)
routed = asyncio.run(
api.set_draft_route(
workspace_id="echo_ws",
revision=2,
step_id="echo",
outcome="error",
target="__end__",
)
)
input_mapped = asyncio.run(
api.set_step_input_map(
workspace_id="echo_ws",
revision=3,
step_id="echo",
input_map={"input.text": "message"},
)
)
output_mapped = asyncio.run(
api.set_step_output_map(
workspace_id="echo_ws",
revision=4,
step_id="echo",
output_map={"echoed": "state.echoed"},
)
)
fetched = asyncio.run(
api.get_draft_workspace(workspace_id="echo_ws", include_draft=True)
)
assert named["revision"] == 2
assert routed["revision"] == 3
assert input_mapped["revision"] == 4
assert output_mapped["revision"] == 5
assert fetched["draft"]["name"] == "echo_v2"
assert fetched["draft"]["routes"]["echo"]["error"] == "__end__"
assert fetched["draft"]["steps"]["echo"]["input"] == [
{
"target": {"root": "local", "parts": ["message"]},
"path": {"root": "input", "parts": ["text"]},
}
]
assert fetched["draft"]["steps"]["echo"]["output"] == [
{
"source": {"root": "local", "parts": ["echoed"]},
"target": {"root": "state", "parts": ["echoed"]},
}
]
def test_validate_draft_workspace_refreshes_status() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "drafts_validate_workspace"
@@ -16,56 +16,8 @@ def test_workflow_surface_lists_artifact_catalog_entries() -> None:
payload = asyncio.run(h.list_artifacts())
nodes = payload["nodes"]
assert len(nodes) == 1
assert payload["total"] == 1
assert payload["next_cursor"] is None
assert nodes[0]["name"] == "workflow.summarize_docs.v1"
assert nodes[0]["artifact_id"] == "summarize_docs"
assert nodes[0]["version"] == 1
assert nodes[0]["kind"] == "workflow"
assert nodes[0]["required_sources"] == ["context7"]
assert "plan" not in nodes[0]
def test_workflow_surface_pages_and_filters_artifact_catalog_entries() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_artifact_pages"
)
artifact_store.save_artifact(artifact())
artifact_store.save_artifact(
artifact().model_copy(
update={
"id": "echo_wrapper",
"version": 2,
"kind": "wrapper",
"title": "Echo Wrapper",
"description": "Reusable echo wrapper.",
}
)
)
artifact_store.save_artifact(
artifact().model_copy(
update={
"id": "browser_click",
"title": "Browser Click",
"description": "Open a page and wait for a click.",
}
)
)
h = handlers(artifact_store)
first_page = asyncio.run(h.list_artifacts(limit=2))
second_page = asyncio.run(
h.list_artifacts(cursor=first_page["next_cursor"], limit=2)
)
wrappers = asyncio.run(h.list_artifacts(kind="wrapper", query="echo"))
assert first_page["total"] == 3
assert first_page["next_cursor"] == "2"
assert len(first_page["nodes"]) == 2
assert len(second_page["nodes"]) == 1
assert second_page["next_cursor"] is None
assert wrappers["total"] == 1
assert wrappers["nodes"][0]["artifact_id"] == "echo_wrapper"
assert wrappers["nodes"][0]["kind"] == "wrapper"
assert "plan" not in wrappers["nodes"][0]
@@ -11,7 +11,6 @@ from wf_mcp.workflow_surface import WorkflowSurfaceHandlers
from ..test_support import echo_tool, local_temp_root
from .conftest import (
ContentOnlyOutputAdapter,
echo_artifact,
failing_tool,
handlers,
)
@@ -21,30 +20,13 @@ def test_workflow_surface_lists_planner_visible_capabilities() -> None:
h = handlers(FileWorkflowArtifactStore(local_temp_root() / "surface_caps"))
payload = asyncio.run(h.list_capabilities(limit=2))
names = [capability["name"] for capability in payload["capabilities"]]
first = payload["capabilities"][0]
assert len(names) == 2
assert len(payload["capabilities"]) == 2
assert payload["total"] >= 2
assert payload["next_cursor"] == "2"
assert "description" in first
assert "source_id" in first
assert first["kind"] == "node_spec"
assert "input_fields" in first
assert "output_fields" in first
assert "input_schema" not in first
assert "wf.admin.list_sources" not in names
def test_workflow_surface_filters_stdlib_capabilities_by_source() -> None:
h = handlers(FileWorkflowArtifactStore(local_temp_root() / "surface_filtered_caps"))
payload = asyncio.run(h.list_capabilities(source_id="wf.std", query="truthy"))
assert [capability["name"] for capability in payload["capabilities"]] == [
"wf.std.truthy"
]
assert payload["capabilities"][0]["source_id"] == "wf.std"
def test_workflow_surface_call_capability_returns_structured_error() -> None:
@@ -78,36 +60,6 @@ def test_workflow_surface_call_capability_returns_structured_error() -> None:
assert "upstream exploded" in payload["diagnostics"][0]["message"]
def test_workflow_surface_lists_saved_wrapper_capabilities() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_wrapper_caps"
)
artifact_store.save_artifact(
echo_artifact().model_copy(
update={
"id": "echo_wrapper",
"kind": "wrapper",
"description": "Reusable echo wrapper.",
}
)
)
artifact_store.save_artifact(echo_artifact())
h = handlers(artifact_store)
payload = asyncio.run(h.list_capabilities(source_id="workflow", query="echo"))
names = [capability["name"] for capability in payload["capabilities"]]
assert names == ["workflow.echo_wrapper.v1"]
assert payload["capabilities"][0]["source_id"] == "workflow"
assert payload["capabilities"][0]["kind"] == "wrapper_artifact"
assert payload["capabilities"][0]["artifact_id"] == "echo_wrapper"
assert payload["capabilities"][0]["version"] == 1
assert payload["capabilities"][0]["title"] == "Echo"
assert payload["capabilities"][0]["outcomes"] == ["completed"]
assert payload["capabilities"][0]["input_fields"] == ["text"]
assert payload["capabilities"][0]["output_fields"] == ["echoed"]
def test_workflow_surface_inspects_one_capability() -> None:
h = handlers(FileWorkflowArtifactStore(local_temp_root() / "surface_inspect_cap"))
@@ -143,33 +95,6 @@ def test_workflow_surface_inspect_capability_includes_wrapper_hints() -> None:
assert hints["outcome_policy"] == "preserve_declared"
def test_workflow_surface_inspects_saved_wrapper_capability() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_inspect_wrapper_cap"
)
artifact_store.save_artifact(
echo_artifact().model_copy(update={"id": "echo_wrapper", "kind": "wrapper"})
)
h = handlers(artifact_store)
payload = asyncio.run(
h.inspect_capability(qualified_name="workflow.echo_wrapper.v1")
)
assert payload["name"] == "workflow.echo_wrapper.v1"
assert payload["source_id"] == "workflow"
assert payload["kind"] == "wrapper_artifact"
assert payload["artifact_id"] == "echo_wrapper"
assert payload["outcomes"] == ["completed"]
assert "input_schema" in payload
hints = payload["wrapper_hints"]
assert hints["capability_name"] == "workflow.echo_wrapper.v1"
assert hints["declared_outcomes"] == ["completed"]
assert hints["suggested_wrapper_outcomes"] == ["completed"]
assert hints["input_map"] == {"input.text": "text"}
assert hints["output_map"] == {"echoed": "state.echoed"}
def test_workflow_surface_does_not_auto_map_raw_mcp_content_blocks() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_content_only_content_hint"
@@ -20,20 +20,6 @@ from .conftest import (
)
def test_workflow_surface_validates_draft_without_saving() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_draft_validate"
)
h = handlers(artifact_store)
payload = asyncio.run(h.validate_draft(draft=echo_draft()))
assert payload["status"] == "valid"
assert payload["diagnostics"] == []
assert payload["compiled_plan"]["nodes"][0]["type"] == "node"
assert not artifact_store.list_artifacts()
def test_workflow_surface_rejects_unknown_draft_route_outcome_when_spec_is_known() -> (
None
):
@@ -129,177 +115,6 @@ def test_workflow_surface_draft_artifact_requires_std_self_binding() -> None:
assert payload["diagnostics"][0]["logical_ref"] == "wf.std.replace"
def test_workflow_surface_patches_draft_without_saving() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_draft_patch"
)
h = handlers(artifact_store)
payload = asyncio.run(
h.patch_draft(
draft=echo_draft(),
patch=[
{
"op": "replace",
"path": "/steps/echo/input/0/target/parts/0",
"value": "message",
}
],
)
)
assert payload["status"] == "valid"
assert payload["draft"]["steps"]["echo"]["input"][0]["target"] == {
"root": "local",
"parts": ["message"],
}
assert not artifact_store.list_artifacts()
def test_workflow_surface_creates_and_gets_draft_workspace() -> None:
artifact_store = FileWorkflowArtifactStore(local_temp_root() / "surface_workspace")
h = handlers(artifact_store)
created = asyncio.run(
h.create_draft_workspace(
workspace_id="echo_draft",
title="Echo Draft",
draft=echo_draft(),
)
)
fetched = asyncio.run(
h.get_draft_workspace(
workspace_id="echo_draft",
include_draft=True,
)
)
assert created["workspace_id"] == "echo_draft"
assert created["revision"] == 1
assert fetched["draft"]["steps"]["echo"]["use"] == "demo.personal.echo_tool"
def test_workflow_surface_lists_draft_workspaces() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_workspace_list"
)
h = handlers(artifact_store)
asyncio.run(
h.create_draft_workspace(
workspace_id="b_draft",
draft=echo_draft(),
title="B Draft",
)
)
asyncio.run(
h.create_draft_workspace(
workspace_id="a_draft",
draft=echo_draft(),
title="A Draft",
)
)
payload = asyncio.run(h.list_draft_workspaces())
assert [workspace["workspace_id"] for workspace in payload["workspaces"]] == [
"a_draft",
"b_draft",
]
assert payload["workspaces"][0]["title"] == "A Draft"
assert "draft" not in payload["workspaces"][0]
def test_workflow_surface_deletes_draft_workspace() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_workspace_delete"
)
h = handlers(artifact_store)
asyncio.run(
h.create_draft_workspace(
workspace_id="echo_draft",
draft=echo_draft(),
)
)
deleted = asyncio.run(h.delete_draft_workspace(workspace_id="echo_draft"))
deleted_again = asyncio.run(h.delete_draft_workspace(workspace_id="echo_draft"))
listed = asyncio.run(h.list_draft_workspaces())
assert deleted["deleted"] is True
assert deleted["status"] == "deleted"
assert deleted_again["deleted"] is False
assert deleted_again["status"] == "not_found"
assert listed["workspaces"] == []
def test_workflow_surface_patch_helpers_update_draft_workspace() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_workspace_patch_helpers"
)
h = handlers(artifact_store)
asyncio.run(
h.create_draft_workspace(
workspace_id="echo_draft",
draft=echo_draft(),
)
)
named = asyncio.run(
h.set_draft_name(
workspace_id="echo_draft",
revision=1,
name="echo_v2",
)
)
routed = asyncio.run(
h.set_draft_route(
workspace_id="echo_draft",
revision=2,
step_id="echo",
outcome="error",
target="__end__",
)
)
input_mapped = asyncio.run(
h.set_step_input_map(
workspace_id="echo_draft",
revision=3,
step_id="echo",
input_map={"input.text": "message"},
)
)
output_mapped = asyncio.run(
h.set_step_output_map(
workspace_id="echo_draft",
revision=4,
step_id="echo",
output_map={"echoed": "state.echoed"},
)
)
fetched = asyncio.run(
h.get_draft_workspace(workspace_id="echo_draft", include_draft=True)
)
assert named["revision"] == 2
assert routed["revision"] == 3
assert input_mapped["revision"] == 4
assert output_mapped["revision"] == 5
assert fetched["draft"]["name"] == "echo_v2"
assert fetched["draft"]["routes"]["echo"]["error"] == "__end__"
assert fetched["draft"]["steps"]["echo"]["input"] == [
{
"target": {"root": "local", "parts": ["message"]},
"path": {"root": "input", "parts": ["text"]},
}
]
assert fetched["draft"]["steps"]["echo"]["output"] == [
{
"source": {"root": "local", "parts": ["echoed"]},
"target": {"root": "state", "parts": ["echoed"]},
}
]
def test_workflow_surface_validates_draft_workspace_with_live_outcomes() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_workspace_validate"
@@ -331,30 +146,6 @@ def test_workflow_surface_validates_draft_workspace_with_live_outcomes() -> None
assert fetched["status"] == "invalid"
def test_workflow_surface_patches_draft_workspace_by_revision() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_workspace_patch"
)
h = handlers(artifact_store)
asyncio.run(
h.create_draft_workspace(
workspace_id="echo_draft",
draft=echo_draft(),
)
)
patched = asyncio.run(
h.patch_draft_workspace(
workspace_id="echo_draft",
revision=1,
patch=[{"op": "replace", "path": "/name", "value": "echo_v2"}],
)
)
assert patched["revision"] == 2
assert patched["status"] == "valid"
def test_workflow_surface_creates_minimal_draft_workspace_with_error_route() -> None:
artifact_store = FileWorkflowArtifactStore(
local_temp_root() / "surface_minimal_workspace"