"""command.py DTO 单元测试。 覆盖 ``CommandPermission`` 枚举与 ``CommandId`` / ``ChannelCommand`` / ``CommandResponse`` / ``CommandResult`` 的字段赋值、默认值、不可变语义 与 ``__post_init__`` 校验逻辑。 """ from __future__ import annotations import dataclasses import pytest from yuxi.channels.contract.dtos.command import ( ChannelCommand, CommandId, CommandPermission, CommandResponse, CommandResult, ) from yuxi.channels.contract.errors import ValidationError pytestmark = pytest.mark.unit @pytest.mark.unit class TestCommandPermission: """命令权限枚举测试。""" def test_enum_values_are_correct(self): # Arrange # Act # Assert assert CommandPermission.PRIVATE == "private" assert CommandPermission.GROUP == "group" assert CommandPermission.ADMIN == "admin" assert CommandPermission.ALL == "all" def test_enum_inherits_from_str(self): # Arrange # Act # Assert assert issubclass(CommandPermission, str) assert isinstance(CommandPermission.ALL, str) def test_enum_has_four_members(self): # Arrange # Act members = list(CommandPermission) # Assert assert len(members) == 4 @pytest.mark.unit class TestCommandId: """命令 ID DTO 测试。""" def test_value_is_assigned(self): # Arrange # Act cmd_id = CommandId(value="cmd-1") # Assert assert cmd_id.value == "cmd-1" def test_is_frozen(self): # Arrange cmd_id = CommandId(value="cmd-1") # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): cmd_id.value = "other" # type: ignore[misc] @pytest.mark.unit class TestChannelCommand: """渠道命令 DTO 测试。""" def test_required_fields_are_assigned(self): # Arrange # Act cmd = ChannelCommand(name="help", description="显示帮助") # Assert assert cmd.name == "help" assert cmd.description == "显示帮助" def test_defaults_are_correct(self): # Arrange # Act cmd = ChannelCommand(name="help", description="显示帮助") # Assert assert cmd.permission is CommandPermission.ALL assert cmd.is_silent is False def test_custom_values_are_assigned(self): # Arrange # Act cmd = ChannelCommand( name="admin", description="管理命令", permission=CommandPermission.ADMIN, is_silent=True, ) # Assert assert cmd.permission is CommandPermission.ADMIN assert cmd.is_silent is True def test_is_frozen(self): # Arrange cmd = ChannelCommand(name="help", description="显示帮助") # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): cmd.name = "other" # type: ignore[misc] def test_empty_name_raises_validation_error(self): # Arrange # Act / Assert with pytest.raises(ValidationError) as exc_info: ChannelCommand(name="", description="d") assert exc_info.value.field == "name" def test_empty_description_raises_validation_error(self): # Arrange # Act / Assert with pytest.raises(ValidationError) as exc_info: ChannelCommand(name="help", description="") assert exc_info.value.field == "description" @pytest.mark.unit class TestCommandResponse: """命令响应 DTO 测试。""" def test_required_fields_are_assigned(self): # Arrange # Act resp = CommandResponse(content="result") # Assert assert resp.content == "result" def test_defaults_are_correct(self): # Arrange # Act resp = CommandResponse(content="result") # Assert assert resp.content_type == "text" assert resp.target is None assert resp.is_silent is False def test_custom_values_are_assigned(self): # Arrange # Act resp = CommandResponse( content="**bold**", content_type="markdown", target="sess-1", is_silent=True, ) # Assert assert resp.content_type == "markdown" assert resp.target == "sess-1" assert resp.is_silent is True def test_is_frozen(self): # Arrange resp = CommandResponse(content="result") # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): resp.content = "other" # type: ignore[misc] @pytest.mark.unit class TestCommandResult: """命令结果 DTO 测试。""" def test_required_fields_are_assigned(self): # Arrange # Act result = CommandResult(command="help") # Assert assert result.command == "help" def test_defaults_are_correct(self): # Arrange # Act result = CommandResult(command="help") # Assert assert result.is_silent is False assert result.response is None def test_with_response(self): # Arrange resp = CommandResponse(content="done") # Act result = CommandResult(command="help", is_silent=False, response=resp) # Assert assert result.response is resp def test_is_frozen(self): # Arrange result = CommandResult(command="help") # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): result.command = "other" # type: ignore[misc]