202 lines
5.5 KiB
Python
202 lines
5.5 KiB
Python
|
|
"""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]
|