ForcePilot/backend/test/unit/channel/capabilities/test_capabilities.py
Kris bab30f2715
Some checks failed
Deploy VitePress site to Pages / build (push) Has been cancelled
Ruff Format Check / Ruff Format & Lint (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
feat:0715
2026-07-15 12:30:58 +08:00

308 lines
11 KiB
Python

from __future__ import annotations
from yuxi.channel.capabilities import CapabilityMatrix
from yuxi.channel.capabilities.levels import (
EditSupport,
InteractiveSupport,
MarkdownSupport,
MediaSupport,
StreamingSupport,
ThreadSupport,
)
from yuxi.channel.capabilities.negotiation import (
CapabilityRequirement,
get_required_ports,
negotiate,
supports,
)
from yuxi.channel.plugins.protocol import ChannelCapability, ChannelMeta
from yuxi.channel.ports import AuthPort, InboundPort, OutboundPort, SessionPort
class TestCapabilityMatrixDefaults:
def test_defaults(self):
matrix = CapabilityMatrix()
assert matrix.text is True
assert matrix.markdown == MarkdownSupport.NONE
assert matrix.media == {MediaSupport.NONE}
assert matrix.interactive == InteractiveSupport.NONE
assert matrix.reactions is False
assert matrix.threads == ThreadSupport.NONE
assert matrix.edits == EditSupport.NONE
assert matrix.streaming == StreamingSupport.NONE
assert matrix.batch_send is False
assert matrix.qr_login is False
assert matrix.scan_pairing is False
assert matrix.pin is False
assert matrix.directory is False
class TestCapabilityMatrixFromChannelCapability:
def test_text_only(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.TEXT)
assert matrix.text is True
assert matrix.markdown == MarkdownSupport.NONE
assert matrix.media == {MediaSupport.NONE}
def test_markdown(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.MARKDOWN)
assert matrix.markdown == MarkdownSupport.BASIC
def test_image_and_file(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.IMAGE | ChannelCapability.FILE)
assert matrix.media == {MediaSupport.IMAGE, MediaSupport.FILE}
def test_interactive(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.INTERACTIVE)
assert matrix.interactive == InteractiveSupport.STATIC
def test_reaction(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.REACTION)
assert matrix.reactions is True
def test_thread(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.THREAD)
assert matrix.threads == ThreadSupport.REPLY
def test_edit(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.EDIT)
assert matrix.edits == EditSupport.WITHIN_MINUTE
def test_streaming(self):
matrix = CapabilityMatrix.from_channel_capability(ChannelCapability.STREAMING)
assert matrix.streaming == StreamingSupport.TYPING
def test_combined_flags(self):
caps = (
ChannelCapability.TEXT
| ChannelCapability.MARKDOWN
| ChannelCapability.IMAGE
| ChannelCapability.INTERACTIVE
| ChannelCapability.THREAD
)
matrix = CapabilityMatrix.from_channel_capability(caps)
assert matrix.text is True
assert matrix.markdown == MarkdownSupport.BASIC
assert MediaSupport.IMAGE in matrix.media
assert matrix.interactive == InteractiveSupport.STATIC
assert matrix.threads == ThreadSupport.REPLY
class TestCapabilityMatrixSupports:
def test_text_supported_by_default(self):
matrix = CapabilityMatrix()
assert matrix.supports("text") is True
def test_markdown_when_none(self):
matrix = CapabilityMatrix()
assert matrix.supports("markdown") is False
def test_markdown_when_basic(self):
matrix = CapabilityMatrix(markdown=MarkdownSupport.BASIC)
assert matrix.supports("markdown") is True
def test_media_when_none(self):
matrix = CapabilityMatrix()
assert matrix.supports("media") is False
def test_media_when_image(self):
matrix = CapabilityMatrix(media={MediaSupport.IMAGE})
assert matrix.supports("media") is True
def test_interactive_when_static(self):
matrix = CapabilityMatrix(interactive=InteractiveSupport.STATIC)
assert matrix.supports("interactive") is True
def test_reactions(self):
matrix = CapabilityMatrix(reactions=True)
assert matrix.supports("reactions") is True
def test_threads(self):
matrix = CapabilityMatrix(threads=ThreadSupport.REPLY)
assert matrix.supports("threads") is True
def test_edits(self):
matrix = CapabilityMatrix(edits=EditSupport.FOREVER)
assert matrix.supports("edits") is True
def test_streaming(self):
matrix = CapabilityMatrix(streaming=StreamingSupport.FULL)
assert matrix.supports("streaming") is True
def test_batch_send(self):
matrix = CapabilityMatrix(batch_send=True)
assert matrix.supports("batch_send") is True
def test_qr_login(self):
matrix = CapabilityMatrix(qr_login=True)
assert matrix.supports("qr_login") is True
def test_scan_pairing(self):
matrix = CapabilityMatrix(scan_pairing=True)
assert matrix.supports("scan_pairing") is True
def test_unknown_capability(self):
matrix = CapabilityMatrix()
assert matrix.supports("unknown") is False
class TestCapabilityMatrixOverrides:
def test_override_disabled(self):
matrix = CapabilityMatrix(text=True, markdown=MarkdownSupport.BASIC)
config = {"capability_overrides": {"text": "disabled", "markdown": "disabled"}}
assert matrix.supports("text", config) is False
assert matrix.supports("markdown", config) is False
def test_override_enabled(self):
matrix = CapabilityMatrix()
config = {"capability_overrides": {"text": "enabled", "markdown": "enabled"}}
assert matrix.supports("text", config) is True
assert matrix.supports("markdown", config) is True
def test_override_level(self):
matrix = CapabilityMatrix(markdown=MarkdownSupport.BASIC)
config = {"capability_overrides": {"markdown": "extended"}}
assert matrix.supports("markdown", config) is True
def test_override_invalid_level_returns_false(self):
matrix = CapabilityMatrix(markdown=MarkdownSupport.BASIC)
config = {"capability_overrides": {"markdown": "not-a-level"}}
assert matrix.supports("markdown", config) is False
def test_override_media(self):
matrix = CapabilityMatrix()
config = {"capability_overrides": {"media": "image"}}
assert matrix.supports("media", config) is True
def test_override_ignores_unrelated_keys(self):
matrix = CapabilityMatrix(text=True)
config = {"capability_overrides": {"unknown": "enabled"}}
assert matrix.supports("text", config) is True
class TestSupportsFunction:
def test_supports_when_matrix_present(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(text=True),
)
assert supports(FakeChannel(), "text") is True
def test_supports_false_when_not_supported(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(),
)
assert supports(FakeChannel(), "markdown") is False
def test_supports_with_config_override(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(markdown=MarkdownSupport.BASIC),
)
config = {"capability_overrides": {"markdown": "disabled"}}
assert supports(FakeChannel(), "markdown", config) is False
def test_supports_returns_false_without_meta(self):
class FakeChannel:
pass
assert supports(FakeChannel(), "text") is False # type: ignore[arg-type]
def test_supports_returns_false_without_matrix(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
meta = ChannelMeta(channel_type="test", display_name="Test")
meta.capability_matrix = None # type: ignore[assignment]
return meta
assert supports(FakeChannel(), "text") is False
class TestNegotiateFunction:
def test_negotiate_supported(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(text=True),
)
req = CapabilityRequirement(capability="text")
result = negotiate(FakeChannel(), req)
assert result.supported is True
assert result.fallback == "ignore"
def test_negotiate_unsupported(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(),
)
req = CapabilityRequirement(capability="markdown", fallback="text")
result = negotiate(FakeChannel(), req)
assert result.supported is False
assert result.fallback == "text"
def test_negotiate_level_met(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(markdown=MarkdownSupport.EXTENDED),
)
req = CapabilityRequirement(capability="markdown", level="basic")
result = negotiate(FakeChannel(), req)
assert result.supported is True
def test_negotiate_level_not_met(self):
class FakeChannel:
def get_meta(self) -> ChannelMeta:
return ChannelMeta(
channel_type="test",
display_name="Test",
capability_matrix=CapabilityMatrix(markdown=MarkdownSupport.BASIC),
)
req = CapabilityRequirement(capability="markdown", level="extended")
result = negotiate(FakeChannel(), req)
assert result.supported is False
class TestGetRequiredPorts:
def test_text_requires_outbound(self):
assert get_required_ports("text") == {OutboundPort}
def test_media_requires_outbound(self):
assert get_required_ports("media") == {OutboundPort}
def test_threads_requires_outbound_and_session(self):
assert get_required_ports("threads") == {OutboundPort, SessionPort}
def test_qr_login_requires_auth(self):
assert get_required_ports("qr_login") == {AuthPort}
def test_scan_pairing_requires_inbound(self):
assert get_required_ports("scan_pairing") == {InboundPort}
def test_unknown_capability_returns_empty(self):
assert get_required_ports("unknown") == set()