test_card_builder.py
5.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""Unit tests for card_builder module."""
import json
import pytest
from hermes_feishu.card_builder import (
build_content_card,
build_mixed_card,
build_table_card,
card_to_json,
)
from hermes_feishu.table_parser import ParsedTable, TableColumn, TableCell
class TestBuildTableCard:
def _make_table(self):
return ParsedTable(
headers=[
TableColumn(name="Name", index=0, field_type="text"),
TableColumn(name="Score", index=1, field_type="number"),
],
rows=[
[TableCell(text="Alice"), TableCell(text="95")],
[TableCell(text="Bob"), TableCell(text="87.5")],
],
raw_markdown="| Name | Score |\n| --- | --- |\n| Alice | 95 |\n| Bob | 87.5 |",
)
def test_basic_structure(self):
table = self._make_table()
card = build_table_card(table)
assert card["config"]["wide_screen_mode"] is True
assert card["header"]["title"]["content"] == "📊 数据表格"
assert card["header"]["template"] == "blue"
def test_table_element(self):
table = self._make_table()
card = build_table_card(table)
elements = card["elements"]
assert len(elements) == 1
assert elements[0]["tag"] == "table"
def test_columns(self):
table = self._make_table()
card = build_table_card(table)
columns = card["elements"][0]["columns"]
assert len(columns) == 2
assert columns[0]["field_type"] == "text"
assert columns[0]["name"] == "Name"
assert columns[1]["field_type"] == "number"
assert columns[1]["name"] == "Score"
def test_rows(self):
table = self._make_table()
card = build_table_card(table)
rows = card["elements"][0]["rows"]
assert len(rows) == 2
assert rows[0][0]["text"] == "Alice"
assert rows[0][1]["text"] == "95"
assert rows[0][1]["value"] == 95
# 87.5 stays as float
assert rows[1][1]["value"] == 87.5
def test_custom_title(self):
table = self._make_table()
card = build_table_card(table, title="Custom Title")
assert card["header"]["title"]["content"] == "Custom Title"
def test_custom_template(self):
table = self._make_table()
card = build_table_card(table, template="green")
assert card["header"]["template"] == "green"
class TestBuildContentCard:
def test_basic_markdown(self):
card = build_content_card("**Hello** World")
assert len(card["elements"]) == 1
assert card["elements"][0]["tag"] == "markdown"
assert card["elements"][0]["content"] == "**Hello** World"
def test_with_title(self):
card = build_content_card("Content", title="Title")
assert card["header"]["title"]["content"] == "Title"
assert len(card["elements"]) == 1
def test_without_title(self):
card = build_content_card("Content")
assert "header" not in card
assert len(card["elements"]) == 1
def test_wide_screen(self):
card = build_content_card("Content")
assert card["config"]["wide_screen_mode"] is True
class TestBuildMixedCard:
def test_with_table_returns_card(self):
md = "Intro text\n| A | B |\n| --- | --- |\n| 1 | 2 |\nOutro"
card = build_mixed_card(md)
assert card is not None
# Should have 3 elements: markdown (intro) + table + markdown (outro)
assert len(card["elements"]) == 3
assert card["elements"][0]["tag"] == "markdown"
assert card["elements"][1]["tag"] == "table"
assert card["elements"][2]["tag"] == "markdown"
def test_without_table_returns_none(self):
md = "Just text here, no tables"
card = build_mixed_card(md)
assert card is None
def test_with_title(self):
md = "| A | B |\n| --- | --- |\n| 1 | 2 |"
card = build_mixed_card(md, title="Report")
assert card is not None
assert card["header"]["title"]["content"] == "Report"
def test_only_table(self):
md = "| Name | Value |\n| --- | --- |\n| X | 100 |"
card = build_mixed_card(md)
assert card is not None
assert len(card["elements"]) == 1
assert card["elements"][0]["tag"] == "table"
def test_text_between_tables(self):
md = "| A | B |\n| --- | --- |\n| 1 | 2 |\nMiddle text\n| X | Y |\n| --- | --- |\n| a | b |"
card = build_mixed_card(md)
assert card is not None
# table + markdown + table
assert len(card["elements"]) == 3
assert card["elements"][0]["tag"] == "table"
assert card["elements"][1]["tag"] == "markdown"
assert "Middle" in card["elements"][1]["content"]
assert card["elements"][2]["tag"] == "table"
class TestCardToJson:
def test_serialization(self):
card = build_content_card("Test")
json_str = card_to_json(card)
assert isinstance(json_str, str)
parsed = json.loads(json_str)
assert parsed["config"]["wide_screen_mode"] is True
def test_cjk_support(self):
card = build_content_card("你好世界", title="测试标题")
json_str = card_to_json(card)
assert "你好世界" in json_str
assert "测试标题" in json_str
# ensure_ascii=False means CJK characters are not escaped
assert "\\u" not in json_str