158 lines
4.9 KiB
Python
158 lines
4.9 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
from pydantic import BaseModel, ValidationError
|
|
|
|
from wf_artifacts import (
|
|
WorkflowArtifact,
|
|
WorkflowCapabilityRef,
|
|
workflow_capability_ref_from_workflow_ref,
|
|
workflow_ref_from_artifact,
|
|
workflow_ref_from_capability,
|
|
)
|
|
from wf_core import WorkflowRef
|
|
|
|
|
|
class CoreWorkflowRefPayload(BaseModel):
|
|
ref: WorkflowRef
|
|
|
|
|
|
def test_workflow_capability_ref_round_trips() -> None:
|
|
ref = WorkflowCapabilityRef(artifact_id="echo_wrapper", version=2)
|
|
|
|
assert str(ref) == "workflow.echo_wrapper.v2"
|
|
assert WorkflowCapabilityRef.parse(str(ref)) == ref
|
|
|
|
|
|
def test_workflow_capability_ref_preserves_dotted_artifact_ids() -> None:
|
|
ref = WorkflowCapabilityRef.parse("workflow.crm.lookup.v3")
|
|
|
|
assert ref.artifact_id == "crm.lookup"
|
|
assert ref.version == 3
|
|
|
|
|
|
def test_workflow_capability_ref_validates_legacy_string_input() -> None:
|
|
class Payload(BaseModel):
|
|
ref: WorkflowCapabilityRef
|
|
|
|
payload = Payload.model_validate({"ref": "workflow.echo_wrapper.v1"})
|
|
|
|
assert payload.ref.artifact_id == "echo_wrapper"
|
|
assert payload.ref.version == 1
|
|
|
|
|
|
def test_workflow_capability_ref_validates_structural_input() -> None:
|
|
class Payload(BaseModel):
|
|
ref: WorkflowCapabilityRef
|
|
|
|
payload = Payload.model_validate(
|
|
{"ref": {"artifact_id": "echo_wrapper", "version": 1}}
|
|
)
|
|
|
|
assert payload.ref.artifact_id == "echo_wrapper"
|
|
assert payload.ref.version == 1
|
|
|
|
|
|
def test_workflow_capability_ref_serializes_structurally() -> None:
|
|
class Payload(BaseModel):
|
|
ref: WorkflowCapabilityRef
|
|
|
|
payload = Payload(ref=WorkflowCapabilityRef("echo_wrapper", 1))
|
|
|
|
assert payload.model_dump(mode="json")["ref"] == {
|
|
"artifact_id": "echo_wrapper",
|
|
"version": 1,
|
|
}
|
|
|
|
|
|
def test_workflow_capability_ref_rejects_other_namespaces() -> None:
|
|
try:
|
|
WorkflowCapabilityRef.parse("demo.echo.v1")
|
|
except ValueError as exc:
|
|
assert "workflow" in str(exc)
|
|
else:
|
|
raise AssertionError("expected non-workflow ref to be rejected")
|
|
|
|
|
|
def test_core_workflow_ref_accepts_local_name_string() -> None:
|
|
payload = CoreWorkflowRefPayload.model_validate({"ref": "child_workflow"})
|
|
|
|
assert payload.ref.name == "child_workflow"
|
|
assert payload.ref.artifact_id is None
|
|
assert payload.model_dump(mode="json")["ref"]["name"] == "child_workflow"
|
|
|
|
|
|
def test_core_workflow_ref_accepts_legacy_saved_artifact_display_string() -> None:
|
|
payload = CoreWorkflowRefPayload.model_validate({"ref": "workflow.echo.wrapper.v2"})
|
|
|
|
assert payload.ref.name is None
|
|
assert payload.ref.artifact_id == "echo.wrapper"
|
|
assert payload.ref.version == 2
|
|
assert payload.model_dump(mode="json")["ref"]["artifact_id"] == "echo.wrapper"
|
|
assert payload.model_dump(mode="json")["ref"]["version"] == 2
|
|
|
|
|
|
def test_core_workflow_ref_accepts_structural_saved_artifact_ref() -> None:
|
|
payload = CoreWorkflowRefPayload.model_validate(
|
|
{"ref": {"artifact_id": "echo_wrapper", "version": 2}}
|
|
)
|
|
|
|
assert payload.ref.artifact_id == "echo_wrapper"
|
|
assert payload.ref.version == 2
|
|
assert payload.ref.display == "workflow.echo_wrapper.v2"
|
|
|
|
|
|
def test_core_workflow_ref_rejects_mixed_name_and_artifact_ref() -> None:
|
|
with pytest.raises(ValidationError, match="exactly one"):
|
|
CoreWorkflowRefPayload.model_validate(
|
|
{"ref": {"name": "child", "artifact_id": "echo", "version": 1}}
|
|
)
|
|
|
|
|
|
def test_workflow_ref_from_artifact_uses_artifact_identity() -> None:
|
|
ref = workflow_ref_from_artifact(_artifact("echo_wrapper", 2))
|
|
|
|
assert ref.artifact_id == "echo_wrapper"
|
|
assert ref.version == 2
|
|
assert ref.name is None
|
|
|
|
|
|
def test_workflow_ref_from_capability_uses_saved_workflow_identity() -> None:
|
|
ref = workflow_ref_from_capability(
|
|
WorkflowCapabilityRef(artifact_id="echo_wrapper", version=2)
|
|
)
|
|
|
|
assert ref.artifact_id == "echo_wrapper"
|
|
assert ref.version == 2
|
|
|
|
|
|
def test_workflow_capability_ref_from_workflow_ref_requires_artifact_ref() -> None:
|
|
capability = workflow_capability_ref_from_workflow_ref(
|
|
WorkflowRef(artifact_id="echo_wrapper", version=2)
|
|
)
|
|
|
|
assert capability == WorkflowCapabilityRef(artifact_id="echo_wrapper", version=2)
|
|
|
|
with pytest.raises(ValueError, match="artifact"):
|
|
workflow_capability_ref_from_workflow_ref(WorkflowRef(name="local_child"))
|
|
|
|
|
|
def _artifact(artifact_id: str, version: int) -> WorkflowArtifact:
|
|
return WorkflowArtifact(
|
|
id=artifact_id,
|
|
version=version,
|
|
title="Echo Wrapper",
|
|
input_schema={"type": "object"},
|
|
output_schema={"type": "object"},
|
|
outcomes=("ok",),
|
|
plan={
|
|
"name": "echo_wrapper",
|
|
"input_schema": {"type": "object"},
|
|
"state_schema": {"type": "object", "properties": {}},
|
|
"output_schema": {"type": "object"},
|
|
"start": "end",
|
|
"nodes": [{"id": "end", "type": "end", "outcome": "ok"}],
|
|
"edges": [],
|
|
},
|
|
)
|