116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
"""Tests for FeishuChannel._split_elements_by_table_limit.
|
|
|
|
Feishu cards reject messages that contain more than one table element
|
|
(API error 11310: card table number over limit). The helper splits a flat
|
|
list of card elements into groups so that each group contains at most one
|
|
table, allowing nanobot to send multiple cards instead of failing.
|
|
"""
|
|
|
|
# Check optional Feishu dependencies before running tests
|
|
try:
|
|
from nanobot.channels import feishu
|
|
FEISHU_AVAILABLE = getattr(feishu, "FEISHU_AVAILABLE", False)
|
|
except ImportError:
|
|
FEISHU_AVAILABLE = False
|
|
|
|
if not FEISHU_AVAILABLE:
|
|
import pytest
|
|
pytest.skip("Feishu dependencies not installed (lark-oapi)", allow_module_level=True)
|
|
|
|
from nanobot.channels.feishu import FeishuChannel
|
|
|
|
|
|
def _md(text: str) -> dict:
|
|
return {"tag": "markdown", "content": text}
|
|
|
|
|
|
def _table() -> dict:
|
|
return {
|
|
"tag": "table",
|
|
"columns": [{"tag": "column", "name": "c0", "display_name": "A", "width": "auto"}],
|
|
"rows": [{"c0": "v"}],
|
|
"page_size": 2,
|
|
}
|
|
|
|
|
|
split = FeishuChannel._split_elements_by_table_limit
|
|
|
|
|
|
def test_empty_list_returns_single_empty_group() -> None:
|
|
assert split([]) == [[]]
|
|
|
|
|
|
def test_no_tables_returns_single_group() -> None:
|
|
els = [_md("hello"), _md("world")]
|
|
result = split(els)
|
|
assert result == [els]
|
|
|
|
|
|
def test_single_table_stays_in_one_group() -> None:
|
|
els = [_md("intro"), _table(), _md("outro")]
|
|
result = split(els)
|
|
assert len(result) == 1
|
|
assert result[0] == els
|
|
|
|
|
|
def test_two_tables_split_into_two_groups() -> None:
|
|
# Use different row values so the two tables are not equal
|
|
t1 = {
|
|
"tag": "table",
|
|
"columns": [{"tag": "column", "name": "c0", "display_name": "A", "width": "auto"}],
|
|
"rows": [{"c0": "table-one"}],
|
|
"page_size": 2,
|
|
}
|
|
t2 = {
|
|
"tag": "table",
|
|
"columns": [{"tag": "column", "name": "c0", "display_name": "B", "width": "auto"}],
|
|
"rows": [{"c0": "table-two"}],
|
|
"page_size": 2,
|
|
}
|
|
els = [_md("before"), t1, _md("between"), t2, _md("after")]
|
|
result = split(els)
|
|
assert len(result) == 2
|
|
# First group: text before table-1 + table-1
|
|
assert t1 in result[0]
|
|
assert t2 not in result[0]
|
|
# Second group: text between tables + table-2 + text after
|
|
assert t2 in result[1]
|
|
assert t1 not in result[1]
|
|
|
|
|
|
def test_three_tables_split_into_three_groups() -> None:
|
|
tables = [
|
|
{"tag": "table", "columns": [], "rows": [{"c0": f"t{i}"}], "page_size": 1}
|
|
for i in range(3)
|
|
]
|
|
els = tables[:]
|
|
result = split(els)
|
|
assert len(result) == 3
|
|
for i, group in enumerate(result):
|
|
assert tables[i] in group
|
|
|
|
|
|
def test_leading_markdown_stays_with_first_table() -> None:
|
|
intro = _md("intro")
|
|
t = _table()
|
|
result = split([intro, t])
|
|
assert len(result) == 1
|
|
assert result[0] == [intro, t]
|
|
|
|
|
|
def test_trailing_markdown_after_second_table() -> None:
|
|
t1, t2 = _table(), _table()
|
|
tail = _md("end")
|
|
result = split([t1, t2, tail])
|
|
assert len(result) == 2
|
|
assert result[1] == [t2, tail]
|
|
|
|
|
|
def test_non_table_elements_before_first_table_kept_in_first_group() -> None:
|
|
head = _md("head")
|
|
t1, t2 = _table(), _table()
|
|
result = split([head, t1, t2])
|
|
# head + t1 in group 0; t2 in group 1
|
|
assert result[0] == [head, t1]
|
|
assert result[1] == [t2]
|