1+ from typing import Optional
2+
13import pytest
4+ from pydantic import BaseModel , ValidationError
25
36from tests .utils import fixture_text
4- from workflowai .core .client .models import RunResponse
7+ from workflowai .core .client .models import RunResponse , RunStreamChunk
8+ from workflowai .core .domain .task import Task
9+ from workflowai .core .domain .task_run import Run , RunChunk
510
611
712@pytest .mark .parametrize (
@@ -14,3 +19,74 @@ def test_task_run_response(fixture: str):
1419 txt = fixture_text (fixture )
1520 task_run = RunResponse .model_validate_json (txt )
1621 assert task_run
22+
23+
24+ class _TaskOutput (BaseModel ):
25+ a : int
26+ b : str
27+
28+
29+ class _TaskOutputOpt (BaseModel ):
30+ a : Optional [int ] = None
31+ b : Optional [str ] = None
32+
33+
34+ class _Task (Task [_TaskOutput , _TaskOutput ]):
35+ id : str = "test-task"
36+ schema_id : int = 1
37+ input_class : type [_TaskOutput ] = _TaskOutput
38+ output_class : type [_TaskOutput ] = _TaskOutput
39+
40+
41+ class _TaskOpt (Task [_TaskOutputOpt , _TaskOutputOpt ]):
42+ id : str = "test-task"
43+ schema_id : int = 1
44+ input_class : type [_TaskOutputOpt ] = _TaskOutputOpt
45+ output_class : type [_TaskOutputOpt ] = _TaskOutputOpt
46+
47+
48+ class TestRunStreamChunkToDomain :
49+ def test_no_version_not_optional (self ):
50+ # Check that partial model is ok
51+ chunk = RunStreamChunk .model_validate_json ('{"id": "1", "task_output": {"a": 1}}' )
52+ assert chunk .task_output == {"a" : 1 }
53+
54+ with pytest .raises (ValidationError ): # sanity
55+ _TaskOutput .model_validate ({"a" : 1 })
56+
57+ parsed = chunk .to_domain (_Task ())
58+ assert isinstance (parsed , RunChunk )
59+ assert parsed .task_output .a == 1
60+ # b is not defined
61+ with pytest .raises (AttributeError ):
62+ assert parsed .task_output .b
63+
64+ def test_no_version_optional (self ):
65+ chunk = RunStreamChunk .model_validate_json ('{"id": "1", "task_output": {"a": 1}}' )
66+ assert chunk
67+
68+ parsed = chunk .to_domain (_TaskOpt ())
69+ assert isinstance (parsed , RunChunk )
70+ assert parsed .task_output .a == 1
71+ assert parsed .task_output .b is None
72+
73+ def test_with_version (self ):
74+ chunk = RunStreamChunk .model_validate_json (
75+ '{"id": "1", "task_output": {"a": 1, "b": "test"}, "cost_usd": 0.1, "duration_seconds": 1, "version": {"properties": {"a": 1, "b": "test"}}}' , # noqa: E501
76+ )
77+ assert chunk
78+
79+ parsed = chunk .to_domain (_Task ())
80+ assert isinstance (parsed , Run )
81+ assert parsed .task_output .a == 1
82+ assert parsed .task_output .b == "test"
83+
84+ assert parsed .cost_usd == 0.1
85+ assert parsed .duration_seconds == 1
86+
87+ def test_with_version_validation_fails (self ):
88+ chunk = RunStreamChunk .model_validate_json (
89+ '{"id": "1", "task_output": {"a": 1}, "version": {"properties": {"a": 1, "b": "test"}}}' ,
90+ )
91+ with pytest .raises (ValidationError ):
92+ chunk .to_domain (_Task ())
0 commit comments