Skip to content

Commit 6b97e5a

Browse files
committed
tests: add units for shortcut (only)
1 parent b0006bb commit 6b97e5a

10 files changed

+491
-1
lines changed

.cursorignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
2+
# NOTE: 不对旧飞书sdk进行索引
3+
src/lark_oapi_compact/remaintain

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
[![image](https://img.shields.io/pypi/pyversions/lark-oapi-compact.svg)](https://pypi.python.org/pypi/lark-oapi-compact)
55
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff)
66
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
7+
[![codecov](https://codecov.io/gh/StrayDragon/oapi-sdk-python-compact/branch/main/graph/badge.svg)](https://codecov.io/gh/StrayDragon/oapi-sdk-python-compact)
78

89

910
- 上游 https://github.com/larksuite/oapi-sdk-python 的默认分支 [v2_main](https://github.com/larksuite/oapi-sdk-python/tree/v2_main) 提供的API不全, 但是老分支 [main](https://github.com/larksuite/oapi-sdk-python/tree/main) 有一部分可以利用, 这个包将老分支的代码进行合并并兼容处理
1011
- 增加一些方便使用的快捷函数, 见 [src/lark_oapi_compact/shortcut](./src/lark_oapi_compact/shortcut/README.md)
12+
- 归档并弃用 https://github.com/StrayDragon/oapi-sdk-python

pyproject.toml

+8
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ build-backend = "hatchling.build"
4646
dev-dependencies = [
4747
"ipython>=7.34.0",
4848
"pre-commit>=2.21.0",
49+
"pytest-cov>=4.1.0",
4950
"pytest>=7.4.4",
5051
"ruff>=0.6.8",
5152
]
53+
54+
[tool.pytest.ini_options]
55+
minversion = "6.0"
56+
addopts = "-ra -q"
57+
testpaths = [
58+
"tests",
59+
]

tests/conftest.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import os
2+
3+
import pytest
4+
from lark_oapi_compact.shortcut.compact import FeishuOpenAPICompactSettings
5+
from lark_oapi_compact.shortcut.driver import FeishuDriverShortcut
6+
from lark_oapi_compact.shortcut.sheets import FeishuSheetsShortcut
7+
8+
9+
@pytest.fixture(scope="session")
10+
def feishu_settings():
11+
app_id = os.environ.get("FEISHU_APP_ID", "")
12+
app_secret = os.environ.get("FEISHU_APP_SECRET", "")
13+
if not app_id or not app_secret:
14+
raise ValueError("FEISHU_APP_ID and FEISHU_APP_SECRET must be set")
15+
return FeishuOpenAPICompactSettings(
16+
app_id=app_id,
17+
app_secret=app_secret,
18+
name="Test Feishu OAPI App",
19+
)
20+
21+
22+
@pytest.fixture(scope="session")
23+
def driver_shortcut(feishu_settings):
24+
return FeishuDriverShortcut(feishu_settings)
25+
26+
27+
@pytest.fixture(scope="session")
28+
def sheets_shortcut(feishu_settings):
29+
return FeishuSheetsShortcut(feishu_settings)
30+
31+
32+
@pytest.fixture
33+
def testing_folder_token(driver_shortcut):
34+
folder_meta = driver_shortcut.get_self_root_folder_meta()
35+
return folder_meta.token

tests/test_driver.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def test_get_self_root_folder_meta(driver_shortcut):
2+
result = driver_shortcut.get_self_root_folder_meta()
3+
assert result is not None
4+
5+
6+
def test_get_folder_meta(driver_shortcut):
7+
folder_token = driver_shortcut.get_self_root_folder_meta().token
8+
result = driver_shortcut.get_folder_meta(folder_token)
9+
assert result is not None

tests/test_group_robot.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import os
2+
3+
import pytest
4+
from lark_oapi_compact.shortcut.group_robot import FeishuGroupRobotShortCut
5+
6+
7+
@pytest.fixture
8+
def group_robot_shortcut():
9+
web_hook_url = os.environ.get("FEISHU_GROUP_ROBOT_WEBHOOK_URL", "")
10+
sign_secret = os.environ.get("FEISHU_GROUP_ROBOT_SIGN_SECRET", "")
11+
if not all([web_hook_url, sign_secret]):
12+
raise ValueError("FEISHU_GROUP_ROBOT_WEBHOOK_URL and FEISHU_GROUP_ROBOT_SIGN_SECRET must be set")
13+
return FeishuGroupRobotShortCut(
14+
web_hook_url=web_hook_url,
15+
sign_secret=sign_secret,
16+
)
17+
18+
19+
def test_send_message(group_robot_shortcut):
20+
message_data = {"msg_type": "text", "content": {"text": "This is a test message"}}
21+
group_robot_shortcut.send_message(message_data)
22+
assert True

tests/test_message.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
from lark_oapi_compact.shortcut.message import FeishuMessageShortcut
3+
4+
5+
@pytest.fixture
6+
def message_shortcut(feishu_settings):
7+
return FeishuMessageShortcut(feishu_settings)
8+
9+
10+
@pytest.mark.skip(reason="TODO: Not total implemented!")
11+
def test_send_group_robot_message(message_shortcut):
12+
body = {"msg_type": "text", "content": {"text": "This is a test message"}}
13+
result = message_shortcut.send_group_robot_message(body)
14+
assert result is not None

tests/test_sheets.py

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import time
2+
3+
import pytest
4+
from lark_oapi_compact.shortcut.sheets.models import CellPos, CellsRange, SheetRange
5+
6+
SPREADSHEET_TITLE = "Test Spreadsheet"
7+
SHEET_TITLE = f"Testing Sheet {time.time()}"
8+
9+
10+
@pytest.fixture
11+
def testing_spreadsheet(sheets_shortcut, testing_folder_token):
12+
spreadsheet = sheets_shortcut.create_spreadsheet(testing_folder_token, SPREADSHEET_TITLE)
13+
yield spreadsheet
14+
15+
16+
@pytest.fixture
17+
def testing_sheet_id(sheets_shortcut, testing_spreadsheet):
18+
sheet_id = sheets_shortcut.create_sheet(
19+
testing_spreadsheet.spreadsheet_token,
20+
title=SHEET_TITLE,
21+
).get(SHEET_TITLE, "")
22+
assert sheet_id, f"Failed to create sheet {SHEET_TITLE}"
23+
yield sheet_id
24+
sheets_shortcut.remove_sheet(testing_spreadsheet.spreadsheet_token, sheet_id)
25+
26+
27+
def test_create_spreadsheet(testing_spreadsheet):
28+
assert testing_spreadsheet is not None
29+
assert testing_spreadsheet.title == SPREADSHEET_TITLE
30+
31+
32+
def test_change_spreadsheet_permission(sheets_shortcut, testing_spreadsheet):
33+
sheets_shortcut.change_spreadsheet_permission(testing_spreadsheet.spreadsheet_token, "tenant_editable")
34+
35+
36+
def test_get_spreadsheet_sheets(sheets_shortcut, testing_spreadsheet):
37+
sheets = sheets_shortcut.get_spreadsheet_sheets(testing_spreadsheet.spreadsheet_token)
38+
assert isinstance(sheets, list)
39+
assert len(sheets) > 0
40+
41+
42+
def test_find_cell_locations_in_sheet(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
43+
sheets_shortcut.batch_update_values(
44+
testing_spreadsheet.spreadsheet_token,
45+
testing_sheet_id,
46+
[(CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="A", y=1)), [["test_value"]])],
47+
)
48+
result = sheets_shortcut.find_cell_locations_in_sheet(
49+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, "test_value"
50+
)
51+
assert result is not None
52+
assert len(result.matched_cells) > 0
53+
54+
55+
def test_recursive_find_cell_locations_in_sheet(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
56+
sheets_shortcut.batch_update_values(
57+
testing_spreadsheet.spreadsheet_token,
58+
testing_sheet_id,
59+
[
60+
(
61+
CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="A", y=3)),
62+
[["value1"], ["value2"], ["value3"]],
63+
)
64+
],
65+
)
66+
result = sheets_shortcut.recursive_find_cell_locations_in_sheet(
67+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, ["value1", "value2", "value3"]
68+
)
69+
assert result is not None
70+
71+
72+
def test_batch_handle_sheets(sheets_shortcut, testing_spreadsheet):
73+
new_sheet = sheets_shortcut.create_sheet(testing_spreadsheet.spreadsheet_token, "New Sheet")
74+
assert len(new_sheet) > 0
75+
for sheet_id in new_sheet.values():
76+
sheets_shortcut.remove_sheet(testing_spreadsheet.spreadsheet_token, sheet_id)
77+
sheets = sheets_shortcut.get_spreadsheet_sheets(testing_spreadsheet.spreadsheet_token)
78+
assert all(sheet.title != "New Sheet" for sheet in sheets)
79+
80+
81+
def test_merge_and_unmerge_cells(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
82+
merge_range = CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="B", y=2))
83+
sheets_shortcut.merge_cells(testing_spreadsheet.spreadsheet_token, testing_sheet_id, merge_range)
84+
85+
sheet_range = SheetRange(sheet_id=testing_sheet_id, start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="B", y=2))
86+
sheets_shortcut.unmerge_cells(testing_spreadsheet.spreadsheet_token, sheet_range)
87+
88+
89+
def test_prepend_and_append_insert_values(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
90+
values = [["prepend1"], ["prepend2"]]
91+
sheets_shortcut.prepend_insert_values(testing_spreadsheet.spreadsheet_token, testing_sheet_id, values=values)
92+
93+
values = [["append1"], ["append2"]]
94+
sheets_shortcut.append_insert_values(testing_spreadsheet.spreadsheet_token, testing_sheet_id, values=values)
95+
96+
result = sheets_shortcut.batch_read_values(
97+
testing_spreadsheet.spreadsheet_token,
98+
testing_sheet_id,
99+
[CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="A", y=4))],
100+
)
101+
assert list(result.values())[0] == [["prepend1"], ["prepend2"], ["append1"], ["append2"]]
102+
103+
104+
def test_batch_update_and_read_values(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
105+
update_range = CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="B", y=2))
106+
values = [["A1", "B1"], ["A2", "B2"]]
107+
sheets_shortcut.batch_update_values(
108+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, [(update_range, values)]
109+
)
110+
111+
read_result = sheets_shortcut.batch_read_values(
112+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, [update_range]
113+
)
114+
assert list(read_result.values())[0] == values
115+
116+
117+
def test_update_formula_value_cell(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
118+
formula = "=SUM(A1:A2)"
119+
result_cell = CellPos(x="B", y=3)
120+
sheets_shortcut.update_formula_value_cell(
121+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, formula, result_cell
122+
)
123+
read_result = sheets_shortcut.batch_read_values(
124+
testing_spreadsheet.spreadsheet_token,
125+
testing_sheet_id,
126+
[CellsRange(start_pos=result_cell, end_pos=result_cell)],
127+
value_render_option="Formula",
128+
)
129+
assert list(read_result.values())[0] == [[formula]]
130+
131+
132+
def test_update_formula_value_cell_using_sum_of_cell_range(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
133+
target_range = CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="A", y=2))
134+
result_cell = CellPos(x="B", y=3)
135+
sheets_shortcut.update_formula_value_cell_using_sum_of_cell_range(
136+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, target_range, result_cell
137+
)
138+
read_result = sheets_shortcut.batch_read_values(
139+
testing_spreadsheet.spreadsheet_token,
140+
testing_sheet_id,
141+
[CellsRange(start_pos=result_cell, end_pos=result_cell)],
142+
value_render_option="Formula",
143+
)
144+
assert list(read_result.values())[0] == [["=SUM(A1:A2)"]]
145+
146+
147+
def test_insert_and_delete_dimension(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
148+
sheets_shortcut.insert_dimension(testing_spreadsheet.spreadsheet_token, testing_sheet_id, "ROWS", 0, 1)
149+
sheets_shortcut.delete_dimension(testing_spreadsheet.spreadsheet_token, testing_sheet_id, "ROWS", 1, 2)
150+
151+
152+
def test_truncate_and_replace_sheet(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
153+
sheets_shortcut.truncate_sheet(testing_spreadsheet.spreadsheet_token, testing_sheet_id)
154+
155+
new_values = [["new1"], ["new2"]]
156+
sheets_shortcut.replace_sheet_by_values(testing_spreadsheet.spreadsheet_token, testing_sheet_id, new_values)
157+
158+
read_result = sheets_shortcut.batch_read_values(
159+
testing_spreadsheet.spreadsheet_token,
160+
testing_sheet_id,
161+
[CellsRange(start_pos=CellPos(x="A", y=1), end_pos=CellPos(x="A", y=2))],
162+
)
163+
assert list(read_result.values())[0] == new_values
164+
165+
166+
def test_insert_image_to_cell(sheets_shortcut, testing_spreadsheet, testing_sheet_id):
167+
cell_pos = CellPos(x="A", y=1)
168+
# 5x5的纯黑色图片
169+
# fmt: off
170+
image_byte_array = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 2, 0, 0, 0, 2, 13, 177, 178, 0, 0, 0, 12, 73, 68, 65, 84, 120, 156, 99, 96, 160, 46, 0, 0, 0, 80, 0, 1, 243, 48, 247, 42, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130] # noqa: E501
171+
# fmt: on
172+
sheets_shortcut.insert_image_to_cell(
173+
testing_spreadsheet.spreadsheet_token, testing_sheet_id, cell_pos, image_byte_array, "test_image.png"
174+
)
175+
assert True

0 commit comments

Comments
 (0)