"""streaming.py DTO 单元测试。 覆盖 ``ChunkMode`` / ``RenderStrategy`` / ``StreamChunk`` / ``ChunkResult`` / ``StreamingCompleted`` / ``StreamingCapability`` / ``StreamingConfig`` 的 字段赋值、默认值、不可变语义与 ``__post_init__`` 校验逻辑。 """ from __future__ import annotations import dataclasses import pytest from yuxi.channels.contract.dtos.streaming import ( ChunkMode, ChunkResult, RenderStrategy, StreamChunk, StreamingCapability, StreamingCompleted, StreamingConfig, ) from yuxi.channels.contract.errors import ValidationError pytestmark = pytest.mark.unit @pytest.mark.unit class TestChunkMode: """分块模式枚举测试。""" def test_str_values(self): assert ChunkMode.NONE == "none" assert ChunkMode.TEXT == "text" assert ChunkMode.BLOCK == "block" assert ChunkMode.FULL_UPDATE == "full_update" assert ChunkMode.PARTIAL_UPDATE == "partial_update" @pytest.mark.unit class TestRenderStrategy: """卡片渲染策略枚举测试。""" def test_str_values(self): assert RenderStrategy.APPEND == "append" assert RenderStrategy.REPLACE == "replace" assert RenderStrategy.MERGE == "merge" @pytest.mark.unit class TestStreamChunk: """流式分块 DTO 测试。""" def test_fields_are_assigned_with_defaults(self): # Act chunk = StreamChunk(content="hello", sequence=0) # Assert assert chunk.is_final is False def test_is_frozen(self): # Arrange chunk = StreamChunk(content="hello", sequence=0) # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): chunk.content = "other" # type: ignore[misc] def test_empty_content_raises(self): # Act / Assert with pytest.raises(ValidationError) as exc_info: StreamChunk(content="", sequence=0) assert exc_info.value.field == "content" def test_negative_sequence_raises(self): # Act / Assert with pytest.raises(ValidationError) as exc_info: StreamChunk(content="hello", sequence=-1) assert exc_info.value.field == "sequence" @pytest.mark.unit class TestChunkResult: """分块结果 DTO 测试。""" def test_fields_are_assigned_with_defaults(self): # Act result = ChunkResult( chunk=StreamChunk(content="hello", sequence=0), success=True, ) # Assert assert result.error is None @pytest.mark.unit class TestStreamingCompleted: """流式完成结果 DTO 测试。""" def test_valid_construction(self): # Act result = StreamingCompleted(total_chunks=5, duration_ms=1000) # Assert assert result.total_chunks == 5 def test_zero_total_chunks_raises(self): # Act / Assert with pytest.raises(ValidationError) as exc_info: StreamingCompleted(total_chunks=0, duration_ms=100) assert exc_info.value.field == "total_chunks" def test_negative_duration_raises(self): # Act / Assert with pytest.raises(ValidationError) as exc_info: StreamingCompleted(total_chunks=1, duration_ms=-1) assert exc_info.value.field == "duration_ms" @pytest.mark.unit class TestStreamingCapability: """流式能力 DTO 测试。""" def test_defaults(self): # Act cap = StreamingCapability() # Assert assert cap.supports_streaming is False assert cap.supports_typing_indicator is False assert cap.chunk_mode == ChunkMode.NONE assert cap.min_chunk_interval_ms == 0 assert cap.max_chunk_length == 0 @pytest.mark.unit class TestStreamingConfig: """流式配置 DTO 测试。""" def test_defaults(self): # Act config = StreamingConfig() # Assert assert config.streaming_enabled is False assert config.enable_typing is True assert config.min_chunk_interval_ms == 200 assert config.streaming_ttl_ms == 60000 assert config.typing_ttl_ms == 10000