type: narrow core model test fixtures

This commit is contained in:
lda
2026-08-29 19:10:30 +07:00 Verified
parent ac09a577a2
commit c87911236a
6 changed files with 57 additions and 39 deletions
+9 -7
View File
@@ -221,13 +221,15 @@ def test_subgraph_ref_accepts_composite_child_input_binding() -> None:
id="run_child", id="run_child",
workflow=child, workflow=child,
input=[ input=[
{ InputExpressionBinding.model_validate(
"target": "folder_id", {
"expression": { "target": "folder_id",
"kind": "literal", "expression": {
"value": "demo-folder", "kind": "literal",
}, "value": "demo-folder",
} },
}
)
], ],
) )
+37 -25
View File
@@ -15,13 +15,16 @@ from wf_core import (
SchemaRef, SchemaRef,
StateField, StateField,
StateSchema, StateSchema,
StepInputBinding,
SubgraphNode, SubgraphNode,
Workflow, Workflow,
WorkflowExecutionError, WorkflowExecutionError,
WorkflowRef,
execute_workflow, execute_workflow,
resume_workflow, resume_workflow,
) )
from wf_core.models.steps import InterruptNode from wf_core.models.steps import InterruptNode, Step
from wf_core.paths import GraphSourcePath, LocalPath
from wf_core.runtime.input_bindings import ( from wf_core.runtime.input_bindings import (
resolve_input_expression, resolve_input_expression,
resolve_step_input_bindings, resolve_step_input_bindings,
@@ -45,6 +48,11 @@ COMPOSITE_BINDING = {
} }
def _composite_binding() -> StepInputBinding:
"""Build this raw fixture through the canonical binding model."""
return InputExpressionBinding.model_validate(COMPOSITE_BINDING)
def test_resolver_builds_nested_json_with_input_state_and_context_paths() -> None: def test_resolver_builds_nested_json_with_input_state_and_context_paths() -> None:
expression = InputExpressionBinding.model_validate( expression = InputExpressionBinding.model_validate(
{ {
@@ -107,7 +115,12 @@ def test_simple_path_binding_preserves_legacy_value_identity() -> None:
legacy_value = {"opaque": object()} legacy_value = {"opaque": object()}
resolved = resolve_step_input_bindings( resolved = resolve_step_input_bindings(
[InputPathBinding(target="request.value", path="state.value")], [
InputPathBinding(
target=LocalPath.parse("request.value"),
path=GraphSourcePath.parse("state.value"),
)
],
state={"value": legacy_value}, state={"value": legacy_value},
workflow_input={}, workflow_input={},
context={}, context={},
@@ -210,7 +223,7 @@ def test_normal_node_execution_resolves_composite_input() -> None:
return {"outcome": "ok", "output": {}} return {"outcome": "ok", "output": {}}
workflow = _node_workflow( workflow = _node_workflow(
input_bindings=[COMPOSITE_BINDING], input_bindings=[_composite_binding()],
state_fields={"foo": StateField(type="string", default="hello")}, state_fields={"foo": StateField(type="string", default="hello")},
) )
run = execute_workflow(workflow, {}, {"concat": concat}) run = execute_workflow(workflow, {}, {"concat": concat})
@@ -220,7 +233,8 @@ def test_normal_node_execution_resolves_composite_input() -> None:
def test_prepared_subgraph_input_resolves_composite_input() -> None: def test_prepared_subgraph_input_resolves_composite_input() -> None:
parent = _parent_subgraph_workflow([COMPOSITE_BINDING]) parent = _parent_subgraph_workflow([_composite_binding()])
child_step: Step = EndNode(id="done", type="end", outcome="ok")
child = Workflow( child = Workflow(
name="child", name="child",
input_schema=_schema({"request": {"type": "object"}}), input_schema=_schema({"request": {"type": "object"}}),
@@ -228,7 +242,7 @@ def test_prepared_subgraph_input_resolves_composite_input() -> None:
output_schema=_schema({}), output_schema=_schema({}),
outcomes=["ok"], outcomes=["ok"],
start="done", start="done",
nodes=[EndNode(id="done", type="end", outcome="ok")], nodes=[child_step],
edges=[], edges=[],
) )
@@ -290,9 +304,15 @@ def test_interrupt_request_resolves_composite_input_and_resume_continues() -> No
def _node_workflow( def _node_workflow(
*, *,
input_bindings: list[dict[str, object]], input_bindings: list[StepInputBinding],
state_fields: dict[str, StateField], state_fields: dict[str, StateField],
) -> Workflow: ) -> Workflow:
node_step: Step = NodeUse(
id="concat",
type="node",
node="concat",
input=input_bindings,
)
return Workflow( return Workflow(
name="node_expression", name="node_expression",
input_schema=_schema({}), input_schema=_schema({}),
@@ -308,19 +328,20 @@ def _node_workflow(
outcomes=["ok"], outcomes=["ok"],
) )
], ],
nodes=[ nodes=[node_step],
NodeUse(
id="concat",
type="node",
node="concat",
input=input_bindings,
)
],
edges=[Edge.model_validate({"from": "concat", "outcome": "ok", "to": END})], edges=[Edge.model_validate({"from": "concat", "outcome": "ok", "to": END})],
) )
def _parent_subgraph_workflow(input_bindings: list[dict[str, object]]) -> Workflow: def _parent_subgraph_workflow(input_bindings: list[StepInputBinding]) -> Workflow:
child_step: Step = SubgraphNode(
id="child",
type="subgraph",
workflow=WorkflowRef(name="child"),
input_schema=_schema({"request": {"type": "object"}}),
output_schema=_schema({}),
input=input_bindings,
)
return Workflow( return Workflow(
name="parent", name="parent",
input_schema=_schema({}), input_schema=_schema({}),
@@ -330,16 +351,7 @@ def _parent_subgraph_workflow(input_bindings: list[dict[str, object]]) -> Workfl
output_schema=_schema({}), output_schema=_schema({}),
outcomes=["ok"], outcomes=["ok"],
start="child", start="child",
nodes=[ nodes=[child_step],
SubgraphNode(
id="child",
type="subgraph",
workflow="child",
input_schema=_schema({"request": {"type": "object"}}),
output_schema=_schema({}),
input=input_bindings,
)
],
edges=[Edge.model_validate({"from": "child", "outcome": "ok", "to": END})], edges=[Edge.model_validate({"from": "child", "outcome": "ok", "to": END})],
) )
+3 -2
View File
@@ -13,6 +13,7 @@ from wf_artifacts.drafts.models import (
) )
from wf_core import Workflow from wf_core import Workflow
from wf_core.models.input_bindings import ArrayExpression, LiteralExpression from wf_core.models.input_bindings import ArrayExpression, LiteralExpression
from wf_core.models.json_values import JsonValue
from wf_core.models.steps import ( from wf_core.models.steps import (
InputExpressionBinding, InputExpressionBinding,
InputPathBinding, InputPathBinding,
@@ -152,8 +153,8 @@ def _nested_expression_array(depth: int) -> dict[str, object]:
return expression return expression
def _nested_json_list(depth: int) -> list[object]: def _nested_json_list(depth: int) -> list[JsonValue]:
value: list[object] = ["leaf"] value: list[JsonValue] = ["leaf"]
for _ in range(depth - 1): for _ in range(depth - 1):
value = [value] value = [value]
return value return value
+5 -2
View File
@@ -4,6 +4,7 @@ from collections.abc import Iterator, Mapping
from typing import Any from typing import Any
from wf_contract_manifest import generate_manifest from wf_contract_manifest import generate_manifest
from wf_contract_manifest.model import ManifestOperation
UNION_RESULTS = { UNION_RESULTS = {
"InspectCapabilityResult", "InspectCapabilityResult",
@@ -148,7 +149,9 @@ def test_manifest_separates_recursive_step_inputs_from_workflow_outputs() -> Non
} <= schemas.keys() } <= schemas.keys()
input_binding_schema = schemas["InputExpressionBinding"] input_binding_schema = schemas["InputExpressionBinding"]
assert input_binding_schema["properties"]["expression"] == { properties = input_binding_schema.get("properties")
assert isinstance(properties, dict)
assert properties["expression"] == {
"$ref": "#/components/schemas/InputExpression" "$ref": "#/components/schemas/InputExpression"
} }
expression_schema = schemas["InputExpression"] expression_schema = schemas["InputExpression"]
@@ -162,7 +165,7 @@ def test_manifest_separates_recursive_step_inputs_from_workflow_outputs() -> Non
"propertyName": "kind", "propertyName": "kind",
} }
def operation(method: str) -> dict[str, Any]: def operation(method: str) -> ManifestOperation:
return next(item for item in manifest["operations"] if item["method"] == method) return next(item for item in manifest["operations"] if item["method"] == method)
step_input = operation("workflow.draft_workspaces.set_step_input_bindings") step_input = operation("workflow.draft_workspaces.set_step_input_bindings")
+2 -2
View File
@@ -164,8 +164,8 @@ export const WorkflowGraph = ({
: {})} : {})}
fitView fitView
proOptions={{ hideAttribution: true }} proOptions={{ hideAttribution: true }}
nodesDraggable={false} nodesDraggable={true}
nodesConnectable={false} nodesConnectable={true}
elementsSelectable={Boolean(onNodeSelect || onEdgeSelect)} elementsSelectable={Boolean(onNodeSelect || onEdgeSelect)}
> >
<Background /> <Background />
+1 -1
View File
@@ -1698,7 +1698,7 @@ tbody tr:hover {
font-weight: 700; font-weight: 700;
letter-spacing: 0.02em; letter-spacing: 0.02em;
line-height: 1; line-height: 1;
text-transform: uppercase; /* text-transform: uppercase; */
} }
.graph-node__ref { .graph-node__ref {