From 2417e87299d1b3121df60442cfbb6fdd8d27d014 Mon Sep 17 00:00:00 2001 From: BigOrangeQWQ <2284086963@qq.com> Date: Thu, 26 Sep 2024 21:05:51 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E4=BA=86=20publish?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/github/models/__init__.py | 4 + .../github/plugins/publish/__init__.py | 2 +- .../github/plugins/publish/validation.py | 2 +- src/plugins/github/plugins/remove/__init__.py | 2 +- .../github/plugins/remove/validation.py | 2 +- src/plugins/github/utils.py | 15 ++ src/providers/validation/__init__.py | 15 -- tests/publish/process/test_auto_merge.py | 10 +- tests/publish/process/test_publish_check.py | 134 ++++++++---------- tests/publish/process/test_pull_request.py | 40 +++--- tests/publish/utils.py | 28 ++++ tests/publish/utils/test_comment_issue.py | 42 ++---- .../utils/test_ensure_issue_content.py | 15 +- .../test_resolve_conflict_pull_requests.py | 25 +++- .../utils/test_trigger_registry_update.py | 26 ++-- 15 files changed, 207 insertions(+), 155 deletions(-) diff --git a/src/plugins/github/models/__init__.py b/src/plugins/github/models/__init__.py index 30c706a1..dd9c36f3 100644 --- a/src/plugins/github/models/__init__.py +++ b/src/plugins/github/models/__init__.py @@ -4,6 +4,7 @@ from pydantic import ( BaseModel, ConfigDict, + Field, model_validator, ) from nonebot.adapters.github import Bot @@ -240,6 +241,9 @@ def issuehandler_validator(cls, data): if data.get("author") is None and data.get("issue"): issue = data["issue"] data["author"] = issue.user.login if issue.user else "" + if data.get("issue_number") is None and data.get("issue"): + issue = data["issue"] + data["issue_number"] = issue.number return data async def update_issue_title( diff --git a/src/plugins/github/plugins/publish/__init__.py b/src/plugins/github/plugins/publish/__init__.py index 9ba8e314..6bab3dd2 100644 --- a/src/plugins/github/plugins/publish/__init__.py +++ b/src/plugins/github/plugins/publish/__init__.py @@ -189,7 +189,7 @@ async def handle_publish_plugin_check( # 验证之后创建拉取请求和修改议题的标题 await process_pull_request(handler, result, branch_name, title) - + # 确保插件重测按钮存在 await ensure_issue_test_button(handler) comment = await render_comment(result, True) diff --git a/src/plugins/github/plugins/publish/validation.py b/src/plugins/github/plugins/publish/validation.py index dba1575a..590d203f 100644 --- a/src/plugins/github/plugins/publish/validation.py +++ b/src/plugins/github/plugins/publish/validation.py @@ -7,9 +7,9 @@ from src.providers.validation import ( PublishType, ValidationDict, - extract_publish_info_from_issue, validate_info, ) +from src.plugins.github.utils import extract_publish_info_from_issue from src.providers.constants import DOCKER_IMAGES from src.providers.docker_test import DockerPluginTest from src.providers.store_test.models import DockerTestResult, Metadata diff --git a/src/plugins/github/plugins/remove/__init__.py b/src/plugins/github/plugins/remove/__init__.py index 862f9639..78ebba75 100644 --- a/src/plugins/github/plugins/remove/__init__.py +++ b/src/plugins/github/plugins/remove/__init__.py @@ -36,7 +36,7 @@ async def pr_close_rule( - is_remove: bool = check_labels("remove"), + is_remove: bool = check_labels(REMOVE_LABEL), related_issue_number: int | None = Depends(get_related_issue_number), ) -> bool: if not is_remove: diff --git a/src/plugins/github/plugins/remove/validation.py b/src/plugins/github/plugins/remove/validation.py index 3038fdc0..1dea9bb0 100644 --- a/src/plugins/github/plugins/remove/validation.py +++ b/src/plugins/github/plugins/remove/validation.py @@ -2,7 +2,7 @@ from githubkit.rest import Issue from pydantic_core import PydanticCustomError -from src.providers.validation import extract_publish_info_from_issue +from src.plugins.github.utils import extract_publish_info_from_issue from src.providers.validation.models import ValidationDict from .constants import REMOVE_HOMEPAGE_PATTERN, PUBLISH_PATH diff --git a/src/plugins/github/utils.py b/src/plugins/github/utils.py index 29288426..125cb9b5 100644 --- a/src/plugins/github/utils.py +++ b/src/plugins/github/utils.py @@ -1,5 +1,6 @@ import json from pathlib import Path +from re import Pattern import subprocess from typing import Any from nonebot import logger @@ -40,3 +41,17 @@ def dump_json(path: Path, data: Any, indent: int = 4): # 结尾加上换行符,不然会被 pre-commit fix json.dump(to_jsonable_python(data), f, ensure_ascii=False, indent=indent) f.write("\n") + + +def extract_publish_info_from_issue( + patterns: dict[str, Pattern[str]], body: str +) -> dict[str, str | None]: + """ + 根据提供的正则表达式和议题内容来提取所需的信息 + """ + matchers = {key: pattern.search(body) for key, pattern in patterns.items()} + data = { + key: match.group(1).strip() if match else None + for key, match in matchers.items() + } + return data diff --git a/src/providers/validation/__init__.py b/src/providers/validation/__init__.py index fef94622..21b86e60 100644 --- a/src/providers/validation/__init__.py +++ b/src/providers/validation/__init__.py @@ -1,6 +1,5 @@ """验证数据是否符合规范""" -from re import Pattern from typing import Any from pydantic import ValidationError from pydantic_core import ErrorDetails @@ -22,20 +21,6 @@ } -def extract_publish_info_from_issue( - patterns: dict[str, Pattern[str]], body: str -) -> dict[str, str | None]: - """ - 根据提供的正则表达式和议题内容来提取所需的信息 - """ - matchers = {key: pattern.search(body) for key, pattern in patterns.items()} - data = { - key: match.group(1).strip() if match else None - for key, match in matchers.items() - } - return data - - def validate_info( publish_type: PublishType, raw_data: dict[str, Any], diff --git a/tests/publish/process/test_auto_merge.py b/tests/publish/process/test_auto_merge.py index 77580279..2a54713d 100644 --- a/tests/publish/process/test_auto_merge.py +++ b/tests/publish/process/test_auto_merge.py @@ -92,6 +92,8 @@ async def test_auto_merge_need_rebase(app: App, mocker: MockerFixture) -> None: 需要 rebase 的情况 """ from src.plugins.github.plugins.publish import auto_merge_matcher + from src.plugins.github.models import GithubHandler, RepoInfo + from nonebot.adapters.github import Bot mock_subprocess_run = mocker.patch("subprocess.run") mock_resolve_conflict_pull_requests = mocker.patch( @@ -162,7 +164,13 @@ async def test_auto_merge_need_rebase(app: App, mocker: MockerFixture) -> None: ], any_order=True, ) - mock_resolve_conflict_pull_requests.assert_called_once_with([mock_pull]) + mock_resolve_conflict_pull_requests.assert_called_once_with( + GithubHandler( + bot=bot, + repo_info=RepoInfo(owner="he0119", repo="action-test"), + ), + [mock_pull], + ) async def test_auto_merge_not_publish(app: App, mocker: MockerFixture) -> None: diff --git a/tests/publish/process/test_publish_check.py b/tests/publish/process/test_publish_check.py index 0602dbc5..aca6763d 100644 --- a/tests/publish/process/test_publish_check.py +++ b/tests/publish/process/test_publish_check.py @@ -20,7 +20,11 @@ from pytest_mock import MockerFixture from respx import MockRouter -from tests.publish.utils import generate_issue_body_bot, generate_issue_body_plugin +from tests.publish.utils import ( + MockIssue, + generate_issue_body_bot, + generate_issue_body_plugin, +) def check_json_data(file: Path, data: Any) -> None: @@ -34,6 +38,8 @@ async def test_process_publish_check( """测试一个正常的发布流程""" from src.plugins.github.plugins.publish import publish_check_matcher from src.plugins.github import plugin_config + from githubkit.rest import Issue + from githubkit.rest import SimpleUser mock_subprocess_run = mocker.patch( "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock() @@ -44,13 +50,7 @@ async def test_process_publish_check( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 80 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot(name="test") - mock_issue.user.login = "test" + mock_issue = MockIssue().as_mock(mocker) mock_event = mocker.MagicMock() mock_event.issue = mock_issue @@ -147,6 +147,7 @@ async def test_process_publish_check( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -250,13 +251,7 @@ async def test_edit_title( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 80 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot(name="test1") - mock_issue.user.login = "test" + mock_issue = MockIssue(body=generate_issue_body_bot(name="test1")).as_mock(mocker) mock_event = mocker.MagicMock() mock_event.issue = mock_issue @@ -379,6 +374,7 @@ async def test_edit_title( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -482,15 +478,11 @@ async def test_edit_title_too_long( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 80 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot( - name="looooooooooooooooooooooooooooooooooooooooooooooooooooooong" - ) - mock_issue.user.login = "test" + mock_issue = MockIssue( + body=generate_issue_body_bot( + name="looooooooooooooooooooooooooooooooooooooooooooooooooooooong" + ) + ).as_mock(mocker) mock_event = mocker.MagicMock() mock_event.issue = mock_issue @@ -585,6 +577,7 @@ async def test_edit_title_too_long( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -629,15 +622,9 @@ async def test_process_publish_check_not_pass( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 1 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot( - name="test", homepage="https://www.baidu.com" - ) - mock_issue.user.login = "test" + mock_issue = MockIssue( + body=generate_issue_body_bot(name="test", homepage="https://www.baidu.com") + ).as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -719,6 +706,7 @@ async def test_process_publish_check_not_pass( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -801,9 +789,7 @@ async def test_issue_state_closed( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.state = "closed" + mock_issue = MockIssue(state="closed").as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -914,6 +900,8 @@ async def test_skip_plugin_check( from src.plugins.github.plugins.publish import publish_check_matcher from src.plugins.github import plugin_config + from githubkit.rest import SimpleUser, Issue + mock_subprocess_run = mocker.patch( "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock() ) @@ -923,13 +911,20 @@ async def test_skip_plugin_check( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() + mock_issue = mocker.MagicMock(spec=Issue) mock_issue.pull_request = None mock_issue.title = "Plugin: project_link" mock_issue.number = 70 mock_issue.state = "open" mock_issue.body = generate_issue_body_plugin() - mock_issue.user.login = "test" + + mock_user = mocker.MagicMock(spec=SimpleUser) + mock_user.login = "test" + mock_user.id = 1 + mock_issue.user = mock_user + # mock_issue = MockIssue( + # title="Plugin: project_link", number=70, body=generate_issue_body_plugin() + # ).as_mock(mocker) mock_event = mocker.MagicMock() mock_event.issue = mock_issue @@ -997,17 +992,7 @@ async def test_skip_plugin_check( }, mock_pulls_resp, ) - # 修改标题 - ctx.should_call_api( - "rest.issues.async_update", - { - "owner": "he0119", - "repo": "action-test", - "issue_number": 70, - "title": "Plugin: ", - }, - True, - ) + # 增加重测按钮 ctx.should_call_api( "rest.issues.async_update", { @@ -1042,6 +1027,17 @@ async def test_skip_plugin_check( }, True, ) + # 修改标题 + ctx.should_call_api( + "rest.issues.async_update", + { + "owner": "he0119", + "repo": "action-test", + "issue_number": 70, + "title": "Plugin: ", + }, + True, + ) ctx.should_call_api( "rest.issues.async_list_comments", {"owner": "he0119", "repo": "action-test", "issue_number": 70}, @@ -1073,6 +1069,7 @@ async def test_skip_plugin_check( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -1122,15 +1119,10 @@ async def test_convert_pull_request_to_draft( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 1 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot( - name="test", homepage="https://www.baidu.com" - ) - mock_issue.user.login = "test" + mock_issue = MockIssue( + number=1, + body=generate_issue_body_bot(name="test", homepage="https://www.baidu.com"), + ).as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -1232,6 +1224,7 @@ async def test_convert_pull_request_to_draft( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) @@ -1281,13 +1274,7 @@ async def test_process_publish_check_ready_for_review( mock_installation_resp = mocker.MagicMock() mock_installation_resp.parsed_data = mock_installation - mock_issue = mocker.MagicMock() - mock_issue.pull_request = None - mock_issue.title = "Bot: test" - mock_issue.number = 80 - mock_issue.state = "open" - mock_issue.body = generate_issue_body_bot(name="test") - mock_issue.user.login = "test" + mock_issue = MockIssue().as_mock(mocker) mock_event = mocker.MagicMock() mock_event.issue = mock_issue @@ -1335,11 +1322,7 @@ async def test_process_publish_check_ready_for_review( {"owner": "he0119", "repo": "action-test", "issue_number": 80}, mock_issues_resp, ) - # ctx.should_call_api( - # "rest.issues.async_list_comments", - # {"owner": "he0119", "repo": "action-test", "issue_number": 80}, - # mock_list_comments_resp, - # ) + ctx.should_call_api( "rest.pulls.async_create", { @@ -1369,7 +1352,15 @@ async def test_process_publish_check_ready_for_review( ctx.should_call_api( "async_graphql", { - "query": "mutation markPullRequestReadyForReview($pullRequestId: ID!) {\n markPullRequestReadyForReview(input: {pullRequestId: $pullRequestId}) {\n clientMutationId\n }\n }", + "query": snapshot( + """\ +mutation markPullRequestReadyForReview($pullRequestId: ID!) { + markPullRequestReadyForReview(input: {pullRequestId: $pullRequestId}) { + clientMutationId + } + }\ +""" + ), "variables": {"pullRequestId": "123"}, }, True, @@ -1404,6 +1395,7 @@ async def test_process_publish_check_ready_for_review( 💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。 💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。 +♻️ 评论已更新至最新检查结果 💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow) diff --git a/tests/publish/process/test_pull_request.py b/tests/publish/process/test_pull_request.py index a1cf4b73..68b80fac 100644 --- a/tests/publish/process/test_pull_request.py +++ b/tests/publish/process/test_pull_request.py @@ -1,6 +1,7 @@ from pathlib import Path from typing import cast +from inline_snapshot import snapshot from nonebot import get_adapter from nonebot.adapters.github import Adapter, GitHubBot, PullRequestClosed from nonebot.adapters.github.config import GitHubApp @@ -8,7 +9,11 @@ from pytest_mock import MockerFixture from respx import MockRouter -from tests.publish.utils import generate_issue_body_plugin_skip_test +from tests.publish.utils import ( + MockIssue, + MockUser, + generate_issue_body_plugin_skip_test, +) async def test_process_pull_request(app: App, mocker: MockerFixture) -> None: @@ -20,10 +25,9 @@ async def test_process_pull_request(app: App, mocker: MockerFixture) -> None: mock_sleep = mocker.patch("asyncio.sleep") mock_sleep.return_value = None - mock_issue = mocker.MagicMock() - mock_issue.state = "open" - mock_issue.body = "### PyPI 项目名\n\nproject_link1\n\n### 插件 import 包名\n\nmodule_name1\n\n### 插件配置项\n\n```dotenv\nlog_level=DEBUG\n```" - mock_issue.number = 80 + mock_issue = MockIssue( + body="### PyPI 项目名\n\nproject_link1\n\n### 插件 import 包名\n\nmodule_name1\n\n### 插件配置项\n\n```dotenv\nlog_level=DEBUG\n```" + ).as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -132,8 +136,7 @@ async def test_process_pull_request_not_merged(app: App, mocker: MockerFixture) mock_subprocess_run = mocker.patch("subprocess.run") - mock_issue = mocker.MagicMock() - mock_issue.state = "open" + mock_issue = MockIssue().as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -209,11 +212,10 @@ async def test_process_pull_request_skip_plugin_test( mock_sleep = mocker.patch("asyncio.sleep") mock_sleep.return_value = None - mock_issue = mocker.MagicMock() - mock_issue.state = "open" - mock_issue.body = generate_issue_body_plugin_skip_test() - mock_issue.number = 80 - mock_issue.user.login = "user" + mock_issue = MockIssue( + body=generate_issue_body_plugin_skip_test(), + user=MockUser(login="user", id=1), + ).as_mock(mocker) mock_issues_resp = mocker.MagicMock() mock_issues_resp.parsed_data = mock_issue @@ -282,12 +284,14 @@ async def test_process_pull_request_skip_plugin_test( "repo": "registry", "owner": "owner", "event_type": "registry_update", - "client_payload": { - "type": "Plugin", - "key": "project_link:module_name", - "config": "log_level=DEBUG\n", - "data": '{"module_name": "module_name", "project_link": "project_link", "name": "name", "desc": "desc", "author": "user", "author_id": 1, "homepage": "https://nonebot.dev", "tags": [{"label": "test", "color": "#ffffff"}], "is_official": false, "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"], "load": false, "metadata": {"name": "name", "description": "desc", "homepage": "https://nonebot.dev", "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"]}}', - }, + "client_payload": snapshot( + { + "type": "Plugin", + "key": "project_link:module_name", + "config": "log_level=DEBUG\n", + "data": '{"module_name": "module_name", "project_link": "project_link", "name": "name", "desc": "desc", "author": "user", "author_id": 1, "homepage": "https://nonebot.dev", "tags": [{"label": "test", "color": "#ffffff"}], "is_official": false, "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"], "load": false, "metadata": {"name": "name", "desc": "desc", "homepage": "https://nonebot.dev", "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"]}}', + } + ), }, True, ) diff --git a/tests/publish/utils.py b/tests/publish/utils.py index b9a1d2f1..fc406105 100644 --- a/tests/publish/utils.py +++ b/tests/publish/utils.py @@ -1,4 +1,8 @@ +from dataclasses import dataclass, field import json +from typing import Any, Literal + +from pytest_mock import MockFixture def generate_issue_body_adapter( @@ -44,3 +48,27 @@ def generate_issue_body_plugin_skip_test( config: str = "log_level=DEBUG", ): return f"""### 插件名称\n\n{name}\n\n### 插件描述\n\n{desc}\n\n### PyPI 项目名\n\n{project_link}\n\n### 插件 import 包名\n\n{module_name}\n\n### 插件项目仓库/主页链接\n\n{homepage}\n\n### 标签\n\n{json.dumps(tags)}\n\n### 插件类型\n\n{tyoe}\n\n### 插件支持的适配器\n\n{json.dumps(supported_adapters)}\n\n### 插件配置项\n\n```dotenv\n{config}\n```""" + + +from githubkit.rest import Issue + + +@dataclass +class MockUser: + login: str = "test" + id: int = 1 + + +@dataclass +class MockIssue: + number: int = 80 + title: str = "Bot: test" + state: Literal["open", "closed"] = "open" + body: str = field(default=generate_issue_body_bot("test")) + pull_request: Any = None + user: MockUser = field(default_factory=MockUser) + + def as_mock(self, mocker: MockFixture): + mocker_issue = mocker.MagicMock(spec=Issue) + mocker_issue.configure_mock(**self.__dict__) + return mocker_issue diff --git a/tests/publish/utils/test_comment_issue.py b/tests/publish/utils/test_comment_issue.py index 374986e6..f8e90755 100644 --- a/tests/publish/utils/test_comment_issue.py +++ b/tests/publish/utils/test_comment_issue.py @@ -8,13 +8,9 @@ async def test_comment_issue(app: App, mocker: MockerFixture): - from src.plugins.github.models import RepoInfo - from src.plugins.github.plugins.publish.utils import comment_issue + from src.plugins.github.models import RepoInfo, GithubHandler - mock_render_comment = mocker.patch( - "src.plugins.github.plugins.publish.utils.render_comment" - ) - mock_render_comment.return_value = "test" + render_comment = "test" mock_result = mocker.AsyncMock() mock_result.render_issue_comment.return_value = "test" @@ -51,20 +47,16 @@ async def test_comment_issue(app: App, mocker: MockerFixture): True, ) - await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, mock_result) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) - mock_render_comment.assert_called_once_with(mock_result, False) + await handler.comment_issue(render_comment, 1) async def test_comment_issue_reuse(app: App, mocker: MockerFixture): - from src.plugins.github.plugins.publish.constants import NONEFLOW_MARKER - from src.plugins.github.models import RepoInfo - from src.plugins.github.plugins.publish.utils import comment_issue + from src.plugins.github.constants import NONEFLOW_MARKER + from src.plugins.github.models import RepoInfo, GithubHandler - mock_render_comment = mocker.patch( - "src.plugins.github.plugins.publish.utils.render_comment" - ) - mock_render_comment.return_value = "test" + render_comment = "test" mock_result = mocker.AsyncMock() mock_result.render_issue_comment.return_value = "test" @@ -102,22 +94,16 @@ async def test_comment_issue_reuse(app: App, mocker: MockerFixture): True, ) - await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, mock_result) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) - mock_render_comment.assert_called_once_with(mock_result, True) + await handler.comment_issue(render_comment, 1) async def test_comment_issue_reuse_same(app: App, mocker: MockerFixture): """测试评论内容相同时不会更新评论""" - from src.plugins.github.models import RepoInfo - from src.plugins.github.plugins.publish.utils import comment_issue + from src.plugins.github.models import RepoInfo, GithubHandler - mock_render_comment = mocker.patch( - "src.plugins.github.plugins.publish.utils.render_comment" - ) - mock_render_comment.return_value = "test\n\n" - - mock_result = mocker.AsyncMock() + render_comment = "test\n\n" mock_comment = mocker.MagicMock() mock_comment.body = "test\n\n" @@ -141,6 +127,8 @@ async def test_comment_issue_reuse_same(app: App, mocker: MockerFixture): mock_list_comments_resp, ) - await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, mock_result) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await handler.comment_issue(render_comment, 1) - mock_render_comment.assert_called_once_with(mock_result, True) + # mock_render_comment.assert_called_once_with("test\n\n", True) diff --git a/tests/publish/utils/test_ensure_issue_content.py b/tests/publish/utils/test_ensure_issue_content.py index e5abb163..d3203c1d 100644 --- a/tests/publish/utils/test_ensure_issue_content.py +++ b/tests/publish/utils/test_ensure_issue_content.py @@ -6,10 +6,13 @@ from nonebug import App from pytest_mock import MockerFixture +from plugins.github.models import IssueHandler +from tests.publish.utils import MockIssue + async def test_ensure_issue_content(app: App, mocker: MockerFixture): """确保议题内容完整""" - from src.plugins.github.models import RepoInfo + from src.plugins.github.models import RepoInfo, GithubHandler from src.plugins.github.plugins.publish.utils import ensure_issue_content mock_comment = mocker.MagicMock() @@ -37,11 +40,15 @@ async def test_ensure_issue_content(app: App, mocker: MockerFixture): }, True, ) - - await ensure_issue_content( - bot, RepoInfo(owner="owner", repo="repo"), 1, "什么都没有" + handler = IssueHandler( + bot=bot, + repo_info=RepoInfo(owner="owner", repo="repo"), + issue=MockIssue(number=1).as_mock(mocker), + issue_number=1, ) + await ensure_issue_content(handler, "什么都没有") + async def test_ensure_issue_content_partial(app: App, mocker: MockerFixture): """确保议题内容被补全""" diff --git a/tests/publish/utils/test_resolve_conflict_pull_requests.py b/tests/publish/utils/test_resolve_conflict_pull_requests.py index 6352d6b5..8736ac19 100644 --- a/tests/publish/utils/test_resolve_conflict_pull_requests.py +++ b/tests/publish/utils/test_resolve_conflict_pull_requests.py @@ -21,6 +21,7 @@ async def test_resolve_conflict_pull_requests_adapter( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.plugins.github.models import RepoInfo, GithubHandler mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -61,7 +62,9 @@ async def test_resolve_conflict_pull_requests_adapter( ) bot = cast(GitHubBot, bot) - await resolve_conflict_pull_requests([mock_pull]) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await resolve_conflict_pull_requests(handler, [mock_pull]) # 测试 git 命令 mock_subprocess_run.assert_has_calls( @@ -147,6 +150,7 @@ async def test_resolve_conflict_pull_requests_bot( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.plugins.github.models import RepoInfo, GithubHandler mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -185,7 +189,9 @@ async def test_resolve_conflict_pull_requests_bot( ) bot = cast(GitHubBot, bot) - await resolve_conflict_pull_requests([mock_pull]) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await resolve_conflict_pull_requests(handler, [mock_pull]) # 测试 git 命令 mock_subprocess_run.assert_has_calls( @@ -267,6 +273,7 @@ async def test_resolve_conflict_pull_requests_plugin( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.plugins.github.models import RepoInfo, GithubHandler mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -305,7 +312,9 @@ async def test_resolve_conflict_pull_requests_plugin( ) bot = cast(GitHubBot, bot) - await resolve_conflict_pull_requests([mock_pull]) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await resolve_conflict_pull_requests(handler, [mock_pull]) # 测试 git 命令 mock_subprocess_run.assert_has_calls( @@ -386,6 +395,7 @@ async def test_resolve_conflict_pull_requests_draft( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.plugins.github.models import RepoInfo, GithubHandler mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -424,7 +434,9 @@ async def test_resolve_conflict_pull_requests_draft( ) bot = cast(GitHubBot, bot) - await resolve_conflict_pull_requests([mock_pull]) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await resolve_conflict_pull_requests(handler, [mock_pull]) # 测试 git 命令 mock_subprocess_run.assert_not_called() @@ -452,6 +464,7 @@ async def test_resolve_conflict_pull_requests_ref( ) -> None: from src.plugins.github import plugin_config from src.plugins.github.plugins.publish.utils import resolve_conflict_pull_requests + from src.plugins.github.models import RepoInfo, GithubHandler mock_subprocess_run = mocker.patch("subprocess.run") mock_result = mocker.MagicMock() @@ -490,7 +503,9 @@ async def test_resolve_conflict_pull_requests_ref( ) bot = cast(GitHubBot, bot) - await resolve_conflict_pull_requests([mock_pull]) + handler = GithubHandler(bot=bot, repo_info=RepoInfo(owner="owner", repo="repo")) + + await resolve_conflict_pull_requests(handler, [mock_pull]) # 测试 git 命令 mock_subprocess_run.assert_not_called() diff --git a/tests/publish/utils/test_trigger_registry_update.py b/tests/publish/utils/test_trigger_registry_update.py index 5ec7da52..9263fa03 100644 --- a/tests/publish/utils/test_trigger_registry_update.py +++ b/tests/publish/utils/test_trigger_registry_update.py @@ -1,5 +1,6 @@ from typing import cast +from inline_snapshot import snapshot from nonebot import get_adapter from nonebot.adapters.github import Adapter, GitHubBot from nonebot.adapters.github.config import GitHubApp @@ -8,6 +9,7 @@ from respx import MockRouter from tests.publish.utils import ( + MockIssue, generate_issue_body_bot, generate_issue_body_plugin_skip_test, ) @@ -21,10 +23,10 @@ async def test_trigger_registry_update(app: App, mocker: MockerFixture): mock_sleep = mocker.patch("asyncio.sleep") mock_sleep.return_value = None - mock_issue = mocker.MagicMock() - mock_issue.state = "open" - mock_issue.body = "### PyPI 项目名\n\nproject_link1\n\n### 插件 import 包名\n\nmodule_name1\n\n### 插件配置项\n\n```dotenv\nlog_level=DEBUG\n```" - mock_issue.number = 1 + mock_issue = MockIssue( + body="### PyPI 项目名\n\nproject_link1\n\n### 插件 import 包名\n\nmodule_name1\n\n### 插件配置项\n\n```dotenv\nlog_level=DEBUG\n```", + number=1, + ).as_mock(mocker) mock_comment = mocker.MagicMock() mock_comment.body = "Bot: test" @@ -52,11 +54,13 @@ async def test_trigger_registry_update(app: App, mocker: MockerFixture): "repo": "registry", "owner": "owner", "event_type": "registry_update", - "client_payload": { - "type": "Plugin", - "key": "project_link1:module_name1", - "config": "log_level=DEBUG\n", - }, + "client_payload": snapshot( + { + "type": "Plugin", + "key": "project_link1:module_name1", + "config": "log_level=DEBUG\n", + } + ), }, True, ) @@ -119,7 +123,9 @@ async def test_trigger_registry_update_skip_test( "type": "Plugin", "key": "project_link:module_name", "config": "log_level=DEBUG\n", - "data": '{"module_name": "module_name", "project_link": "project_link", "name": "name", "desc": "desc", "author": "user", "author_id": 1, "homepage": "https://nonebot.dev", "tags": [{"label": "test", "color": "#ffffff"}], "is_official": false, "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"], "load": false, "metadata": {"name": "name", "description": "desc", "homepage": "https://nonebot.dev", "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"]}}', + "data": snapshot( + '{"module_name": "module_name", "project_link": "project_link", "name": "name", "desc": "desc", "author": "user", "author_id": 1, "homepage": "https://nonebot.dev", "tags": [{"label": "test", "color": "#ffffff"}], "is_official": false, "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"], "load": false, "metadata": {"name": "name", "desc": "desc", "homepage": "https://nonebot.dev", "type": "application", "supported_adapters": ["nonebot.adapters.onebot.v11"]}}' + ), }, }, True,