78 lines
1.9 KiB
Python
78 lines
1.9 KiB
Python
"""Boundary tests for pure WebSocket protocol helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from nanobot.channels.websocket import (
|
|
_extract_data_url_mime,
|
|
_is_valid_chat_id,
|
|
_parse_envelope,
|
|
)
|
|
|
|
|
|
def test_chat_id_validator_accepts_only_compact_capability_keys() -> None:
|
|
valid = [
|
|
"a",
|
|
"A-Z_09:chat-id",
|
|
"x" * 64,
|
|
]
|
|
invalid = [
|
|
"",
|
|
"x" * 65,
|
|
"../escape",
|
|
"chat/id",
|
|
"chat id",
|
|
"chat\nid",
|
|
None,
|
|
123,
|
|
]
|
|
|
|
for value in valid:
|
|
assert _is_valid_chat_id(value), value
|
|
for value in invalid:
|
|
assert not _is_valid_chat_id(value), repr(value)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("raw", "expected_type"),
|
|
[
|
|
("plain text", None),
|
|
("{not json", None),
|
|
("[]", None),
|
|
("{}", None),
|
|
('{"type": 42}', None),
|
|
('{"type": "message", "content": "hi"}', "message"),
|
|
(' {"type": "new_chat"} ', "new_chat"),
|
|
],
|
|
)
|
|
def test_parse_envelope_only_accepts_typed_json_objects(
|
|
raw: str,
|
|
expected_type: str | None,
|
|
) -> None:
|
|
parsed = _parse_envelope(raw)
|
|
if expected_type is None:
|
|
assert parsed is None
|
|
else:
|
|
assert parsed is not None
|
|
assert parsed["type"] == expected_type
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("url", "expected"),
|
|
[
|
|
("data:image/png;base64,AAAA", "image/png"),
|
|
("data:IMAGE/JPEG;charset=utf-8;base64,AAAA", "image/jpeg"),
|
|
("data:video/webm;codecs=vp9;base64,AAAA", "video/webm"),
|
|
("data:image/svg+xml;base64,AAAA", "image/svg+xml"),
|
|
("data:image/png,AAAA", None),
|
|
("data:;base64,AAAA", None),
|
|
("https://example.invalid/image.png", None),
|
|
],
|
|
)
|
|
def test_extract_data_url_mime_normalizes_only_base64_data_urls(
|
|
url: str,
|
|
expected: str | None,
|
|
) -> None:
|
|
assert _extract_data_url_mime(url) == expected
|