160 lines
5.0 KiB
Python
160 lines
5.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, cast
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from wf_core.models.steps import InputExpressionBinding
|
|
from wf_transport_rpc_http.models import (
|
|
CreateScheduleParams,
|
|
InspectCapabilityParams,
|
|
ListCapabilitiesParams,
|
|
ReadRunTraceParams,
|
|
SetStepInputBindingsParams,
|
|
SetWorkflowOutputBindingsParams,
|
|
StartRunParams,
|
|
TraceRangeParams,
|
|
UpdateScheduleParams,
|
|
)
|
|
|
|
|
|
def test_trace_range_params_converts_to_api_trace_range() -> None:
|
|
trace_range = TraceRangeParams(start=2, limit=5).to_api_trace_range()
|
|
|
|
assert trace_range.start == 2
|
|
assert trace_range.limit == 5
|
|
|
|
|
|
def test_trace_range_params_rejects_invalid_values() -> None:
|
|
with pytest.raises(ValidationError):
|
|
TraceRangeParams(start=-1, limit=5)
|
|
|
|
with pytest.raises(ValidationError):
|
|
TraceRangeParams(start=0, limit=0)
|
|
|
|
with pytest.raises(ValidationError):
|
|
TraceRangeParams(start=0, limit=101)
|
|
|
|
|
|
def test_capability_params_are_explicit_models() -> None:
|
|
listed = ListCapabilitiesParams(query="echo", source_id="wf.std", limit=10)
|
|
inspected = InspectCapabilityParams(qualified_name="wf.std.constant")
|
|
|
|
assert listed.query == "echo"
|
|
assert listed.source_id == "wf.std"
|
|
assert listed.limit == 10
|
|
assert inspected.qualified_name == "wf.std.constant"
|
|
|
|
|
|
def test_run_params_are_explicit_models() -> None:
|
|
started = StartRunParams(
|
|
deployment_id="demo.default",
|
|
workflow_input={"message": "hello"},
|
|
trace_range=TraceRangeParams(start=0, limit=3),
|
|
)
|
|
trace = ReadRunTraceParams(
|
|
run_id="run_demo",
|
|
trace_range=TraceRangeParams(start=0, limit=1),
|
|
)
|
|
|
|
assert started.deployment_id == "demo.default"
|
|
assert started.workflow_input["message"] == "hello"
|
|
assert started.trace_range is not None
|
|
assert trace.run_id == "run_demo"
|
|
assert trace.trace_range.limit == 1
|
|
|
|
|
|
def test_update_schedule_params_match_create_numeric_constraints() -> None:
|
|
valid = UpdateScheduleParams(
|
|
schedule_id="schedule",
|
|
expected_revision=1,
|
|
max_active_runs=2,
|
|
lateness_allowance_s=0,
|
|
max_steps=10,
|
|
)
|
|
assert valid.max_active_runs == 2
|
|
assert valid.lateness_allowance_s == 0
|
|
assert valid.max_steps == 10
|
|
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=1, max_active_runs=0
|
|
)
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=1, lateness_allowance_s=-1
|
|
)
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(schedule_id="schedule", expected_revision=1, max_steps=0)
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=1, max_steps=True
|
|
)
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=1, max_steps=cast(Any, "10")
|
|
)
|
|
for revision in (0, -1):
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=revision
|
|
)
|
|
|
|
|
|
def test_schedule_policy_params_reject_unknown_values() -> None:
|
|
with pytest.raises(ValidationError):
|
|
CreateScheduleParams(
|
|
schedule_id="schedule",
|
|
deployment_id="deployment",
|
|
trigger={"kind": "oneshot", "at": "2026-09-08T12:00:00+00:00"},
|
|
overlap=cast(Any, "queue"),
|
|
)
|
|
with pytest.raises(ValidationError):
|
|
UpdateScheduleParams(
|
|
schedule_id="schedule", expected_revision=1, misfire=cast(Any, "replay")
|
|
)
|
|
|
|
|
|
def test_step_input_params_accept_composite_bindings_but_workflow_output_does_not() -> (
|
|
None
|
|
):
|
|
params = SetStepInputBindingsParams.model_validate(
|
|
{
|
|
"workspace_id": "concat",
|
|
"revision": 1,
|
|
"step_id": "call",
|
|
"bindings": [
|
|
{
|
|
"target": "items",
|
|
"expression": {
|
|
"kind": "array",
|
|
"items": [
|
|
{"kind": "path", "path": "state.value"},
|
|
{"kind": "literal", "value": "!"},
|
|
],
|
|
},
|
|
}
|
|
],
|
|
}
|
|
)
|
|
|
|
assert isinstance(params.bindings[0], InputExpressionBinding)
|
|
|
|
with pytest.raises(ValidationError):
|
|
SetWorkflowOutputBindingsParams.model_validate(
|
|
{
|
|
"workspace_id": "concat",
|
|
"revision": 1,
|
|
"bindings": [
|
|
{
|
|
"target": "items",
|
|
"expression": {
|
|
"kind": "literal",
|
|
"value": "not-a-workflow-output-binding",
|
|
},
|
|
}
|
|
],
|
|
}
|
|
)
|