diff --git a/tests/conftest.py b/tests/conftest.py
index 08eaa370..66b0afd2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -4,6 +4,7 @@
import nonebot
import pytest
+from nonebot.adapters.github import Adapter
from nonebug import NONEBOT_INIT_KWARGS
from nonebug.app import App
from pytest_mock import MockerFixture
@@ -26,11 +27,13 @@ def pytest_configure(config: pytest.Config) -> None:
"github_event_path": "event_path",
"plugin_test_output": "test_output",
"plugin_test_result": False,
+ "github_apps": [],
}
@pytest.fixture(scope="session", autouse=True)
def load_plugin(nonebug_init: None) -> set["Plugin"]:
+ nonebot.get_driver().register_adapter(Adapter)
return nonebot.load_plugins(str(Path(__file__).parent.parent / "src" / "plugins"))
diff --git a/tests/process/test_publish_check.py b/tests/process/test_publish_check.py
index 85c491a2..9e8f9fcf 100644
--- a/tests/process/test_publish_check.py
+++ b/tests/process/test_publish_check.py
@@ -1,469 +1,671 @@
-# import json
-# from pathlib import Path
-# from typing import Any
-
-# from pytest_mock import MockerFixture
-
-
-# def mocked_httpx_get(url: str):
-# class MockResponse:
-# def __init__(self, status_code: int):
-# self.status_code = status_code
-
-# if url == "https://v2.nonebot.dev":
-# return MockResponse(200)
-
-# return MockResponse(404)
-
-
-# def check_json_data(file: Path, data: Any) -> None:
-# with open(file) as f:
-# assert json.load(f) == data
-
-
-# def test_process_publish_check(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试一个正常的发布流程"""
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
-# mock_issue.user.login = "test"
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# mock_issues_resp = mocker.MagicMock()
-# mock_issues_resp.parsed_data = mock_issue
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "Bot: test"
-# mock_list_comments_resp = mocker.MagicMock()
-# mock_list_comments_resp.parsed_data = [mock_comment]
-# bot.github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# mock_pull = mocker.MagicMock()
-# mock_pull.number = 2
-# mock_pulls_resp = mocker.MagicMock()
-# mock_pulls_resp.parsed_data = mock_pull
-# bot.github.rest.pulls.create.return_value = mock_pulls_resp
-
-# with open(tmp_path / "bots.json", "w") as f:
-# json.dump([], f)
-
-# check_json_data(g.settings.input_config.bot_path, [])
-
-# bot.process_publish_check(mock_event)
-
-# # 获取最新的议题信息
-# bot.github.rest.issues.get.assert_called_with("owner", "repo", 1)
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_has_calls(
-# [
-# mocker.call(
-# ["git", "switch", "-C", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "config", "--global", "user.name", "test"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# [
-# "git",
-# "config",
-# "--global",
-# "user.email",
-# "test@users.noreply.github.com",
-# ],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "add", "-A"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "commit", "-m", ":beers: publish bot test (#1)"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "diff", "origin/publish/issue1", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "push", "origin", "publish/issue1", "-f"],
-# check=True,
-# capture_output=True,
-# ),
-# ] # type: ignore
-# )
-
-# # 检查文件是否正确
-# check_json_data(
-# g.settings.input_config.bot_path,
-# [
-# {
-# "name": "test",
-# "desc": "desc",
-# "author": "test",
-# "homepage": "https://v2.nonebot.dev",
-# "tags": [{"label": "test", "color": "#ffffff"}],
-# "is_official": False,
-# }
-# ],
-# )
-
-# # 检查是否创建了拉取请求
-# bot.github.rest.pulls.create.assert_called_with(
-# "owner",
-# "repo",
-# title="Bot: test",
-# body="resolve #1",
-# base="master",
-# head="publish/issue1",
-# )
-
-# # 测试自动添加标签
-# bot.github.rest.issues.add_labels.assert_has_calls(
-# [
-# mocker.call("owner", "repo", 1, labels=["Bot"]), # 给议题添加标签
-# mocker.call("owner", "repo", 2, labels=["Bot"]), # 给拉取请求添加标签
-# ]
-# )
-
-# # 检查是否创建了评论
-# bot.github.rest.issues.create_comment.assert_called_with(
-# "owner",
-# "repo",
-# 1,
-# body="""# 📃 商店发布检查结果\n\n> Bot: test\n\n**✅ 所有测试通过,一切准备就绪!**\n\n详情
✅ 标签: test-#ffffff。✅ 项目 主页 返回状态码 200。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n""",
-# )
-
-
-# def test_edit_title(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试编辑标题
-
-# 插件名被修改后,标题也应该被修改
-# """
-# from githubkit.exception import RequestFailed
-
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# 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 = """**机器人名称:**\n\ntest1\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
-# mock_issue.user.login = "test"
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# mock_issues_resp = mocker.MagicMock()
-# mock_issues_resp.parsed_data = mock_issue
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "Bot: test"
-# mock_list_comments_resp = mocker.MagicMock()
-# mock_list_comments_resp.parsed_data = [mock_comment]
-# bot.github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# bot.github.rest.pulls.create.side_effect = RequestFailed(mocker.MagicMock())
-
-# mock_pull = mocker.MagicMock()
-# mock_pull.number = 2
-# mock_pull.title = "Bot: test"
-# mock_pulls_resp = mocker.MagicMock()
-# mock_pulls_resp.parsed_data = [mock_pull]
-# bot.github.rest.pulls.list.return_value = mock_pulls_resp
-
-# with open(tmp_path / "bots.json", "w") as f:
-# json.dump([], f)
-
-# check_json_data(g.settings.input_config.bot_path, [])
-
-# bot.process_publish_check(mock_event)
-
-# # 获取最新的议题信息
-# bot.github.rest.issues.get.assert_called_with("owner", "repo", 1)
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_has_calls(
-# [
-# mocker.call(
-# ["git", "switch", "-C", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "config", "--global", "user.name", "test"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# [
-# "git",
-# "config",
-# "--global",
-# "user.email",
-# "test@users.noreply.github.com",
-# ],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "add", "-A"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "commit", "-m", ":beers: publish bot test1 (#1)"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "diff", "origin/publish/issue1", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "push", "origin", "publish/issue1", "-f"],
-# check=True,
-# capture_output=True,
-# ),
-# ] # type: ignore
-# )
-
-# # 检查文件是否正确
-# check_json_data(
-# g.settings.input_config.bot_path,
-# [
-# {
-# "name": "test1",
-# "desc": "desc",
-# "author": "test",
-# "homepage": "https://v2.nonebot.dev",
-# "tags": [{"label": "test", "color": "#ffffff"}],
-# "is_official": False,
-# }
-# ],
-# )
-
-# # 检查是否创建了拉取请求
-# bot.github.rest.pulls.create.assert_called_with(
-# "owner",
-# "repo",
-# title="Bot: test1",
-# body="resolve #1",
-# base="master",
-# head="publish/issue1",
-# )
-
-# # 测试自动添加标签
-# bot.github.rest.issues.add_labels.assert_has_calls(
-# [
-# mocker.call("owner", "repo", 1, labels=["Bot"]), # 给议题添加标签
-# ]
-# )
-
-# # # 检查是否修改了标题
-# bot.github.rest.issues.update.assert_called_with(
-# "owner", "repo", 1, title="Bot: test1"
-# )
-# bot.github.rest.pulls.list.assert_called_with(
-# "owner", "repo", head="owner:publish/issue1"
-# )
-# bot.github.rest.pulls.update.assert_called_with(
-# "owner", "repo", 2, title="Bot: test1"
-# )
-
-# # 检查是否创建了评论
-# bot.github.rest.issues.create_comment.assert_called_with(
-# "owner",
-# "repo",
-# 1,
-# body="""# 📃 商店发布检查结果\n\n> Bot: test1\n\n**✅ 所有测试通过,一切准备就绪!**\n\n详情
✅ 标签: test-#ffffff。✅ 项目 主页 返回状态码 200。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n""",
-# )
-
-
-# def test_process_publish_check_not_pass(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试发布检查不通过"""
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://test\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
-# mock_issue.user.login = "test"
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# mock_issues_resp = mocker.MagicMock()
-# mock_issues_resp.parsed_data = mock_issue
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "Bot: test"
-# mock_list_comments_resp = mocker.MagicMock()
-# mock_list_comments_resp.parsed_data = [mock_comment]
-# bot.github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# with open(tmp_path / "bots.json", "w") as f:
-# json.dump([], f)
-
-# check_json_data(g.settings.input_config.bot_path, [])
-
-# bot.process_publish_check(mock_event)
-
-# # 获取最新的议题信息
-# bot.github.rest.issues.get.assert_called_with("owner", "repo", 1)
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_not_called()
-
-# # 检查文件是否正确
-# check_json_data(g.settings.input_config.bot_path, [])
-
-# # 检查是否创建了拉取请求
-# bot.github.rest.pulls.create.assert_not_called()
-
-# # 测试自动添加标签
-# bot.github.rest.issues.add_labels.assert_has_calls(
-# [
-# mocker.call("owner", "repo", 1, labels=["Bot"]), # 给议题添加标签
-# ]
-# )
-
-# # 检查是否创建了评论
-# bot.github.rest.issues.create_comment.assert_called_with(
-# "owner",
-# "repo",
-# 1,
-# body="""# 📃 商店发布检查结果\n\n> Bot: test\n\n**⚠️ 在发布检查过程中,我们发现以下问题:**\n
⚠️ 项目 主页 返回状态码 404。请确保您的项目主页可访问。
\n详情
✅ 标签: test-#ffffff。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n""",
-# )
-
-
-# def test_comment_at_pull_request(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试在拉取请求下评论
-
-# event.issue.pull_request 不为空
-# """
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# mock_issue = mocker.MagicMock()
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# bot.process_publish_check(mock_event)
-
-# mock_httpx.assert_not_called()
-# mock_subprocess_run.assert_not_called()
-# bot.github.rest.issues.add_labels.assert_not_called()
-
-
-# def test_issue_state_closed(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试议题已关闭
-
-# event.issue.state = "closed"
-# """
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# mock_issue = mocker.MagicMock()
-# mock_issue.pull_request = None
-# mock_issue.state = "closed"
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# bot.process_publish_check(mock_event)
-
-# mock_httpx.assert_not_called()
-# mock_subprocess_run.assert_not_called()
-# bot.github.rest.issues.add_labels.assert_not_called()
-
-
-# def test_not_publish_issue(mocker: MockerFixture, tmp_path: Path) -> None:
-# """测试议题与发布无关
-
-# 议题的标题不以 "Bot/Adapter/Plugin" 开头
-# """
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch(
-# "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
-# )
-
-# mock_issue = mocker.MagicMock()
-# mock_issue.pull_request = None
-# mock_issue.state = "open"
-# mock_issue.title = "test"
-
-# mock_event = mocker.MagicMock()
-# mock_event.issue = mock_issue
-
-# bot.process_publish_check(mock_event)
-
-# mock_httpx.assert_not_called()
-# mock_subprocess_run.assert_not_called()
-# bot.github.rest.issues.add_labels.assert_not_called()
+import json
+from pathlib import Path
+from typing import Any, cast
+
+from nonebot import get_adapter
+from nonebot.adapters.github import (
+ Adapter,
+ GitHubBot,
+ IssueCommentCreated,
+ IssuesOpened,
+)
+from nonebot.adapters.github.config import GitHubApp
+from nonebug import App
+from pytest_mock import MockerFixture
+
+
+def mocked_httpx_get(url: str):
+ class MockResponse:
+ def __init__(self, status_code: int):
+ self.status_code = status_code
+
+ if url == "https://v2.nonebot.dev":
+ return MockResponse(200)
+
+ return MockResponse(404)
+
+
+def check_json_data(file: Path, data: Any) -> None:
+ with open(file) as f:
+ assert json.load(f) == data
+
+
+async def test_process_publish_check(
+ app: App, mocker: MockerFixture, tmp_path: Path
+) -> None:
+ """测试一个正常的发布流程"""
+ from src.plugins.publish import check
+ from src.plugins.publish.config import plugin_config
+
+ mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+
+ 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
+ mock_issue.user.login = "test"
+
+ mock_event = mocker.MagicMock()
+ mock_event.issue = mock_issue
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "Bot: test"
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ mock_pull = mocker.MagicMock()
+ mock_pull.number = 2
+ mock_pulls_resp = mocker.MagicMock()
+ mock_pulls_resp.parsed_data = mock_pull
+
+ with open(tmp_path / "bots.json", "w") as f:
+ json.dump([], f)
+
+ check_json_data(plugin_config.input_config.bot_path, [])
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "issue-open.json"
+ event = Adapter.payload_to_event("1", "issues", event_path.read_bytes())
+ assert isinstance(event, IssuesOpened)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_issues_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_add_labels",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "labels": ["Bot"],
+ },
+ True,
+ )
+ 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",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "title": "Bot: test",
+ "body": "resolve #80",
+ "base": "master",
+ "head": "publish/issue80",
+ },
+ mock_pulls_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_add_labels",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 2,
+ "labels": ["Bot"],
+ },
+ True,
+ )
+ 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.issues.async_create_comment",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "body": """# 📃 商店发布检查结果\n\n> Bot: test\n\n**✅ 所有测试通过,一切准备就绪!**\n\n详情
✅ 标签: test-#ffffff。✅ 项目 主页 返回状态码 200。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n""",
+ },
+ True,
+ )
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_has_calls(
+ [
+ mocker.call(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "switch", "-C", "publish/issue80"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "config", "--global", "user.name", "test"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ [
+ "git",
+ "config",
+ "--global",
+ "user.email",
+ "test@users.noreply.github.com",
+ ],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "add", "-A"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "commit", "-m", ":beers: publish bot test (#80)"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "diff", "origin/publish/issue80", "publish/issue80"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "push", "origin", "publish/issue80", "-f"],
+ check=True,
+ capture_output=True,
+ ),
+ ] # type: ignore
+ )
+
+ # 检查文件是否正确
+ check_json_data(
+ plugin_config.input_config.bot_path,
+ [
+ {
+ "name": "test",
+ "desc": "desc",
+ "author": "test",
+ "homepage": "https://v2.nonebot.dev",
+ "tags": [{"label": "test", "color": "#ffffff"}],
+ "is_official": False,
+ }
+ ],
+ )
+
+
+async def test_edit_title(app: App, mocker: MockerFixture, tmp_path: Path) -> None:
+ """测试编辑标题
+
+ 插件名被修改后,标题也应该被修改
+ """
+ from src.plugins.publish import check
+ from src.plugins.publish.config import plugin_config
+
+ mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+ 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 = """**机器人名称:**\n\ntest1\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
+ mock_issue.user.login = "test"
+
+ mock_event = mocker.MagicMock()
+ mock_event.issue = mock_issue
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "Bot: test"
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ mock_pull = mocker.MagicMock()
+ mock_pull.number = 2
+ mock_pulls_resp = mocker.MagicMock()
+ mock_pulls_resp.parsed_data = mock_pull
+
+ with open(tmp_path / "bots.json", "w") as f:
+ json.dump([], f)
+
+ check_json_data(plugin_config.input_config.bot_path, [])
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "issue-open.json"
+ event = Adapter.payload_to_event("1", "issues", event_path.read_bytes())
+ assert isinstance(event, IssuesOpened)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_issues_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_add_labels",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "labels": ["Bot"],
+ },
+ True,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_list_comments",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_list_comments_resp,
+ )
+ # TODO: 抛出一个异常,然后执行修改拉取请求标题的逻辑
+ ctx.should_call_api(
+ "rest.pulls.async_create",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "title": "Bot: test1",
+ "body": "resolve #80",
+ "base": "master",
+ "head": "publish/issue80",
+ },
+ mock_pulls_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_add_labels",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 2,
+ "labels": ["Bot"],
+ },
+ True,
+ )
+ # 修改标题
+ ctx.should_call_api(
+ "rest.issues.async_update",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "title": "Bot: test1",
+ },
+ True,
+ )
+
+ 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.issues.async_create_comment",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "body": """# 📃 商店发布检查结果\n\n> Bot: test1\n\n**✅ 所有测试通过,一切准备就绪!**\n\n详情
✅ 标签: test-#ffffff。✅ 项目 主页 返回状态码 200。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n""",
+ },
+ True,
+ )
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_has_calls(
+ [
+ mocker.call(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "switch", "-C", "publish/issue80"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "config", "--global", "user.name", "test"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ [
+ "git",
+ "config",
+ "--global",
+ "user.email",
+ "test@users.noreply.github.com",
+ ],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "add", "-A"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "commit", "-m", ":beers: publish bot test1 (#80)"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "diff", "origin/publish/issue80", "publish/issue80"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "push", "origin", "publish/issue80", "-f"],
+ check=True,
+ capture_output=True,
+ ),
+ ] # type: ignore
+ )
+
+ # 检查文件是否正确
+ check_json_data(
+ plugin_config.input_config.bot_path,
+ [
+ {
+ "name": "test1",
+ "desc": "desc",
+ "author": "test",
+ "homepage": "https://v2.nonebot.dev",
+ "tags": [{"label": "test", "color": "#ffffff"}],
+ "is_official": False,
+ }
+ ],
+ )
+
+
+async def test_process_publish_check_not_pass(
+ app: App, mocker: MockerFixture, tmp_path: Path
+) -> None:
+ """测试发布检查不通过"""
+ from src.plugins.publish import check
+ from src.plugins.publish.config import plugin_config
+
+ mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+ 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://test\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
+ mock_issue.user.login = "test"
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "Bot: test"
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ with open(tmp_path / "bots.json", "w") as f:
+ json.dump([], f)
+
+ check_json_data(plugin_config.input_config.bot_path, [])
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "issue-open.json"
+ event = Adapter.payload_to_event("1", "issues", event_path.read_bytes())
+ assert isinstance(event, IssuesOpened)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_issues_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_add_labels",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "labels": ["Bot"],
+ },
+ True,
+ )
+ # 检查是否需要跳过插件测试
+ 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.issues.async_list_comments",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_list_comments_resp,
+ )
+
+ ctx.should_call_api(
+ "rest.issues.async_create_comment",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 80,
+ "body": """# 📃 商店发布检查结果\n\n> Bot: test\n\n**⚠️ 在发布检查过程中,我们发现以下问题:**\n⚠️ 项目 主页 返回状态码 404。请确保您的项目主页可访问。
\n详情
✅ 标签: test-#ffffff。
\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n""",
+ },
+ True,
+ )
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_called_once_with(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ )
+
+ # 检查文件是否正确
+ check_json_data(plugin_config.input_config.bot_path, [])
+
+
+async def test_comment_at_pull_request(app: App, mocker: MockerFixture) -> None:
+ """测试在拉取请求下评论
+
+ event.issue.pull_request 不为空
+ """
+ from src.plugins.publish import check
+
+ mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "pr-comment.json"
+ event = Adapter.payload_to_event("1", "issue_comment", event_path.read_bytes())
+ assert isinstance(event, IssueCommentCreated)
+
+ ctx.receive_event(bot, event)
+
+ mock_httpx.assert_not_called()
+ mock_subprocess_run.assert_not_called()
+
+
+async def test_issue_state_closed(app: App, mocker: MockerFixture) -> None:
+ """测试议题已关闭
+
+ event.issue.state = "closed"
+ """
+ from src.plugins.publish import check
+
+ mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+ 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_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "issue-open.json"
+ event = Adapter.payload_to_event("1", "issues", event_path.read_bytes())
+ assert isinstance(event, IssuesOpened)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_issues_resp,
+ )
+
+ ctx.receive_event(bot, event)
+
+ mock_httpx.assert_not_called()
+ mock_subprocess_run.assert_called_once_with(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ )
+
+
+async def test_not_publish_issue(app: App, mocker: MockerFixture) -> None:
+ """测试议题与发布无关
+
+ 议题的标题不以 "Bot/Adapter/Plugin" 开头
+ """
+ from src.plugins.publish import check
+
+ mock_httpx = mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch(
+ "subprocess.run", side_effect=lambda *args, **kwargs: mocker.MagicMock()
+ )
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+ mock_installation_resp = mocker.MagicMock()
+ mock_installation_resp.parsed_data = mock_installation
+
+ mock_issue = mocker.MagicMock()
+ mock_issue.pull_request = None
+ mock_issue.state = "open"
+ mock_issue.title = "test"
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ async with app.test_matcher(check) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event_path = Path(__file__).parent.parent / "plugin-test" / "issue-open.json"
+ event = Adapter.payload_to_event("1", "issues", event_path.read_bytes())
+ assert isinstance(event, IssuesOpened)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 80},
+ mock_issues_resp,
+ )
+
+ ctx.receive_event(bot, event)
+
+ mock_httpx.assert_not_called()
+ mock_subprocess_run.assert_called_once_with(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ )
diff --git a/tests/process/test_pull_request.py b/tests/process/test_pull_request.py
index e164bb72..f94c5fbc 100644
--- a/tests/process/test_pull_request.py
+++ b/tests/process/test_pull_request.py
@@ -1,171 +1,216 @@
-# from pytest_mock import MockerFixture
-
-
-# def test_process_pull_request(mocker: MockerFixture) -> None:
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_subprocess_run = mocker.patch("subprocess.run")
-# bot.get_pull_requests_by_label = mocker.MagicMock()
-# bot.get_pull_requests_by_label.return_value = []
-# bot.resolve_conflict_pull_requests = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Bot"
-
-# mock_event = mocker.MagicMock()
-# mock_event.pull_request.labels = [mock_label]
-# mock_event.pull_request.head.ref = "publish/issue1"
-# mock_event.pull_request.merged = True
-
-# mock_issues_resp = mocker.MagicMock()
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-# mock_issue = mocker.MagicMock()
-# mock_issue.state = "open"
-# mock_issues_resp.parsed_data = mock_issue
-
-# bot.process_pull_request_event(mock_event)
-
-# bot.github.rest.issues.get.assert_called_once_with("owner", "repo", 1)
-
-# bot.github.rest.issues.update.assert_called_once_with(
-# "owner", "repo", 1, state="closed", state_reason="completed"
-# )
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_called_once_with(
-# ["git", "push", "origin", "--delete", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# )
-
-# # 处理冲突的拉取请求
-# bot.get_pull_requests_by_label.assert_called_once_with("Bot")
-# bot.resolve_conflict_pull_requests.assert_called_once_with([])
-
-
-# def test_process_pull_request_not_merged(mocker: MockerFixture) -> None:
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_subprocess_run = mocker.patch("subprocess.run")
-# bot.get_pull_requests_by_label = mocker.MagicMock()
-# bot.get_pull_requests_by_label.return_value = []
-# bot.resolve_conflict_pull_requests = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Bot"
-
-# mock_event = mocker.MagicMock()
-# mock_event.pull_request.labels = [mock_label]
-# mock_event.pull_request.head.ref = "publish/issue1"
-# mock_event.pull_request.merged = False
-
-# mock_issues_resp = mocker.MagicMock()
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-# mock_issue = mocker.MagicMock()
-# mock_issue.state = "open"
-# mock_issues_resp.parsed_data = mock_issue
-
-# bot.process_pull_request_event(mock_event)
-
-# bot.github.rest.issues.get.assert_called_once_with("owner", "repo", 1)
-
-# bot.github.rest.issues.update.assert_called_once_with(
-# "owner", "repo", 1, state="closed", state_reason="not_planned"
-# )
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_called_once_with(
-# ["git", "push", "origin", "--delete", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# )
-
-# # 处理冲突的拉取请求
-# bot.get_pull_requests_by_label.assert_not_called()
-# bot.resolve_conflict_pull_requests.assert_not_called()
-
-
-# def test_not_publish(mocker: MockerFixture) -> None:
-# """测试与发布无关的拉取请求"""
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_subprocess_run = mocker.patch("subprocess.run")
-# bot.get_pull_requests_by_label = mocker.MagicMock()
-# bot.get_pull_requests_by_label.return_value = []
-# bot.resolve_conflict_pull_requests = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Something"
-
-# mock_event = mocker.MagicMock()
-# mock_event.pull_request.labels = [mock_label]
-# mock_event.pull_request.head.ref = "publish/issue1"
-# mock_event.pull_request.merged = True
-
-# mock_issues_resp = mocker.MagicMock()
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-# mock_issue = mocker.MagicMock()
-# mock_issue.state = "open"
-# mock_issues_resp.parsed_data = mock_issue
-
-# bot.process_pull_request_event(mock_event)
-
-# bot.github.rest.issues.get.assert_not_called()
-
-# bot.github.rest.issues.update.assert_not_called()
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_not_called()
-
-# # 处理冲突的拉取请求
-# bot.get_pull_requests_by_label.assert_not_called()
-# bot.resolve_conflict_pull_requests.assert_not_called()
-
-
-# def test_extract_issue_number_from_ref_failed(mocker: MockerFixture) -> None:
-# """测试从分支名中提取议题号失败"""
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_subprocess_run = mocker.patch("subprocess.run")
-# bot.get_pull_requests_by_label = mocker.MagicMock()
-# bot.get_pull_requests_by_label.return_value = []
-# bot.resolve_conflict_pull_requests = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Bot"
-
-# mock_event = mocker.MagicMock()
-# mock_event.pull_request.labels = [mock_label]
-# mock_event.pull_request.head.ref = "1"
-# mock_event.pull_request.merged = True
-
-# mock_issues_resp = mocker.MagicMock()
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-# mock_issue = mocker.MagicMock()
-# mock_issue.state = "open"
-# mock_issues_resp.parsed_data = mock_issue
-
-# bot.process_pull_request_event(mock_event)
-
-# bot.github.rest.issues.get.assert_not_called()
-
-# bot.github.rest.issues.update.assert_not_called()
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_not_called()
-
-# # 处理冲突的拉取请求
-# bot.get_pull_requests_by_label.assert_not_called()
-# bot.resolve_conflict_pull_requests.assert_not_called()
+from pathlib import Path
+from typing import cast
+
+from nonebot import get_adapter
+from nonebot.adapters.github import Adapter, GitHubBot, PullRequestClosed
+from nonebot.adapters.github.config import GitHubApp
+from nonebug import App
+from pytest_mock import MockerFixture
+
+
+async def test_process_pull_request(app: App, mocker: MockerFixture) -> None:
+ from src.plugins.publish import pr_close
+
+ event_path = Path(__file__).parent.parent / "plugin-test" / "pr-close.json"
+
+ mock_subprocess_run = mocker.patch("subprocess.run")
+
+ mock_issue = mocker.MagicMock()
+ mock_issue.state = "open"
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+
+ mock_installation_resp = mocker.MagicMock()
+ mock_installation_resp.parsed_data = mock_installation
+
+ mock_pulls_resp = mocker.MagicMock()
+ mock_pulls_resp.parsed_data = []
+
+ async with app.test_matcher(pr_close) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event = Adapter.payload_to_event("1", "pull_request", event_path.read_bytes())
+ assert isinstance(event, PullRequestClosed)
+ event.payload.pull_request.merged = True
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 76},
+ mock_issues_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_update",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 76,
+ "state": "closed",
+ "state_reason": "completed",
+ },
+ True,
+ )
+ ctx.should_call_api(
+ "rest.pulls.async_list",
+ {"owner": "he0119", "repo": "action-test", "state": "open"},
+ mock_pulls_resp,
+ )
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_has_calls(
+ [
+ mocker.call(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "push", "origin", "--delete", "publish/issue76"],
+ check=True,
+ capture_output=True,
+ ),
+ ], # type: ignore
+ any_order=True,
+ )
+
+
+async def test_process_pull_request_not_merged(app: App, mocker: MockerFixture) -> None:
+ from src.plugins.publish import pr_close
+
+ event_path = Path(__file__).parent.parent / "plugin-test" / "pr-close.json"
+
+ mock_subprocess_run = mocker.patch("subprocess.run")
+
+ mock_issue = mocker.MagicMock()
+ mock_issue.state = "open"
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_installation = mocker.MagicMock()
+ mock_installation.id = 123
+
+ mock_installation_resp = mocker.MagicMock()
+ mock_installation_resp.parsed_data = mock_installation
+
+ async with app.test_matcher(pr_close) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event = Adapter.payload_to_event("1", "pull_request", event_path.read_bytes())
+ assert isinstance(event, PullRequestClosed)
+
+ ctx.should_call_api(
+ "rest.apps.async_get_repo_installation",
+ {"owner": "he0119", "repo": "action-test"},
+ mock_installation_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "he0119", "repo": "action-test", "issue_number": 76},
+ mock_issues_resp,
+ )
+ ctx.should_call_api(
+ "rest.issues.async_update",
+ {
+ "owner": "he0119",
+ "repo": "action-test",
+ "issue_number": 76,
+ "state": "closed",
+ "state_reason": "not_planned",
+ },
+ True,
+ )
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_has_calls(
+ [
+ mocker.call(
+ ["git", "config", "--global", "safe.directory", "*"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "push", "origin", "--delete", "publish/issue76"],
+ check=True,
+ capture_output=True,
+ ),
+ ], # type: ignore
+ any_order=True,
+ )
+
+
+async def test_not_publish(app: App, mocker: MockerFixture) -> None:
+ """测试与发布无关的拉取请求"""
+ from src.plugins.publish import pr_close
+
+ event_path = Path(__file__).parent.parent / "plugin-test" / "pr-close.json"
+
+ mock_subprocess_run = mocker.patch("subprocess.run")
+
+ async with app.test_matcher(pr_close) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event = Adapter.payload_to_event("1", "pull_request", event_path.read_bytes())
+ assert isinstance(event, PullRequestClosed)
+ event.payload.pull_request.labels = []
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_not_called()
+
+
+async def test_extract_issue_number_from_ref_failed(
+ app: App, mocker: MockerFixture
+) -> None:
+ """测试从分支名中提取议题号失败"""
+ from src.plugins.publish import pr_close
+
+ event_path = Path(__file__).parent.parent / "plugin-test" / "pr-close.json"
+
+ mock_subprocess_run = mocker.patch("subprocess.run")
+
+ async with app.test_matcher(pr_close) as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+ event = Adapter.payload_to_event("1", "pull_request", event_path.read_bytes())
+ assert isinstance(event, PullRequestClosed)
+ event.payload.pull_request.head.ref = "1"
+
+ ctx.receive_event(bot, event)
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_not_called()
+ mock_subprocess_run.assert_not_called()
diff --git a/tests/utils/test_comment_issue.py b/tests/utils/test_comment_issue.py
index c05dcbdd..59973ec3 100644
--- a/tests/utils/test_comment_issue.py
+++ b/tests/utils/test_comment_issue.py
@@ -1,78 +1,116 @@
-# from nonebug import App
-# from pytest_mock import MockerFixture
-
-
-# async def test_comment_issue(app: App, mocker: MockerFixture):
-# from nonebot.adapters.github import GitHubBot
-# from nonebot.adapters.github.config import GitHubApp
-
-# from src.plugins.publish.models import RepoInfo
-# from src.plugins.publish.utils import comment_issue
-
-# repo_info = RepoInfo(owner="owner", repo="repo")
-# github = mocker.MagicMock()
-
-# async with app.test_api() as ctx:
-# bot = ctx.create_bot(base=GitHubBot, app=GitHubApp(app_id="1", private_key="1"))
-
-# mocker.patch.object(bot, "_github", github)
-
-# mock_list_comments_resp = mocker.MagicMock()
-# github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "Bot: test"
-# mock_list_comments_resp.parsed_data = [mock_comment]
-
-# await comment_issue(bot, repo_info, 1, "test")
-
-# github.rest.issues.update_comment.assert_not_called()
-# github.rest.issues.create_comment.assert_called_once_with(
-# "owner",
-# "repo",
-# 1,
-# body="# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n",
-# )
-
-
-# async def test_comment_issue_reuse(mocker: MockerFixture):
-# bot.github = mocker.MagicMock()
-
-# mock_list_comments_resp = mocker.MagicMock()
-# bot.github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "任意的东西\n\n"
-# mock_comment.id = 123
-# mock_list_comments_resp.parsed_data = [mock_comment]
-
-# bot.comment_issue(1, "test")
-
-# bot.github.rest.issues.create_comment.assert_not_called()
-# bot.github.rest.issues.update_comment.assert_called_once_with(
-# "owner",
-# "repo",
-# 123,
-# body="# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n♻️ 评论已更新至最新检查结果\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n",
-# )
-
-
-# async def test_comment_issue_reuse_same(mocker: MockerFixture):
-# """测试评论内容相同时不会更新评论"""
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_list_comments_resp = mocker.MagicMock()
-# bot.github.rest.issues.list_comments.return_value = mock_list_comments_resp
-
-# mock_comment = mocker.MagicMock()
-# mock_comment.body = "# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n♻️ 评论已更新至最新检查结果\n\n💪 Powered by [NoneBot2 Publish Bot](https://github.com/nonebot/noneflow)\n\n"
-# mock_comment.id = 123
-# mock_list_comments_resp.parsed_data = [mock_comment]
-
-# bot.comment_issue(1, "test")
-
-# bot.github.rest.issues.create_comment.assert_not_called()
-# bot.github.rest.issues.update_comment.assert_not_called()
+from typing import cast
+
+from nonebot import get_adapter
+from nonebot.adapters.github import Adapter, GitHubBot
+from nonebot.adapters.github.config import GitHubApp
+from nonebug import App
+from pytest_mock import MockerFixture
+
+
+async def test_comment_issue(app: App, mocker: MockerFixture):
+ from src.plugins.publish.models import RepoInfo
+ from src.plugins.publish.utils import comment_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "Bot: test"
+
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.issues.async_list_comments",
+ {"owner": "owner", "repo": "repo", "issue_number": 1},
+ mock_list_comments_resp,
+ )
+
+ ctx.should_call_api(
+ "rest.issues.async_create_comment",
+ {
+ "owner": "owner",
+ "repo": "repo",
+ "issue_number": 1,
+ "body": "# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n",
+ },
+ True,
+ )
+
+ await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, "test")
+
+
+async def test_comment_issue_reuse(app: App, mocker: MockerFixture):
+ from src.plugins.publish.models import RepoInfo
+ from src.plugins.publish.utils import comment_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "任意的东西\n\n"
+ mock_comment.id = 123
+
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.issues.async_list_comments",
+ {"owner": "owner", "repo": "repo", "issue_number": 1},
+ mock_list_comments_resp,
+ )
+
+ ctx.should_call_api(
+ "rest.issues.async_update_comment",
+ {
+ "owner": "owner",
+ "repo": "repo",
+ "comment_id": 123,
+ "body": "# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n♻️ 评论已更新至最新检查结果\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n",
+ },
+ True,
+ )
+
+ await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, "test")
+
+
+async def test_comment_issue_reuse_same(app: App, mocker: MockerFixture):
+ """测试评论内容相同时不会更新评论"""
+ from src.plugins.publish.models import RepoInfo
+ from src.plugins.publish.utils import comment_issue
+
+ mock_comment = mocker.MagicMock()
+ mock_comment.body = "# 📃 商店发布检查结果\n\ntest\n\n---\n\n💡 如需修改信息,请直接修改 issue,机器人会自动更新检查结果。\n💡 当插件加载测试失败时,请发布新版本后在当前页面下评论任意内容以触发测试。\n\n♻️ 评论已更新至最新检查结果\n\n💪 Powered by [NoneFlow](https://github.com/nonebot/noneflow)\n\n"
+ mock_comment.id = 123
+
+ mock_list_comments_resp = mocker.MagicMock()
+ mock_list_comments_resp.parsed_data = [mock_comment]
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.issues.async_list_comments",
+ {"owner": "owner", "repo": "repo", "issue_number": 1},
+ mock_list_comments_resp,
+ )
+
+ await comment_issue(bot, RepoInfo(owner="owner", repo="repo"), 1, "test")
diff --git a/tests/utils/test_get_pull_requests_by_label.py b/tests/utils/test_get_pull_requests_by_label.py
index 77d6edd4..628e433a 100644
--- a/tests/utils/test_get_pull_requests_by_label.py
+++ b/tests/utils/test_get_pull_requests_by_label.py
@@ -1,47 +1,79 @@
-# from pytest_mock import MockerFixture
-
-
-# def test_get_pull_requests_by_label(mocker: MockerFixture) -> None:
-# """测试获取指定标签的拉取请求"""
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Bot"
-
-# mock_pull = mocker.MagicMock()
-# mock_pull.labels = [mock_label]
-
-# mock_pulls_resp = mocker.MagicMock()
-# mock_pulls_resp.parsed_data = [mock_pull]
-# bot.github.rest.pulls.list.return_value = mock_pulls_resp
-
-# pulls = bot.get_pull_requests_by_label("Bot")
-
-# bot.github.rest.pulls.list.assert_called_with("owner", "repo", state="open")
-# assert pulls[0] == mock_pull
-
-
-# def test_get_pull_requests_by_label_not_match(mocker: MockerFixture) -> None:
-# """测试获取指定标签的拉取请求,但是没有匹配的"""
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Some"
-
-# mock_pull = mocker.MagicMock()
-# mock_pull.labels = [mock_label]
-
-# mock_pulls_resp = mocker.MagicMock()
-# mock_pulls_resp.parsed_data = [mock_pull]
-# bot.github.rest.pulls.list.return_value = mock_pulls_resp
-
-# pulls = bot.get_pull_requests_by_label("Bot")
-
-# bot.github.rest.pulls.list.assert_called_with("owner", "repo", state="open")
-# assert pulls == []
+from typing import cast
+
+from nonebot import get_adapter
+from nonebot.adapters.github import Adapter, GitHubBot
+from nonebot.adapters.github.config import GitHubApp
+from nonebug import App
+from pytest_mock import MockerFixture
+
+
+async def test_get_pull_requests_by_label(app: App, mocker: MockerFixture) -> None:
+ """测试获取指定标签的拉取请求"""
+ from src.plugins.publish.depends import get_pull_requests_by_label
+ from src.plugins.publish.models import PublishType, RepoInfo
+
+ mock_label = mocker.MagicMock()
+ mock_label.name = "Bot"
+
+ mock_pull = mocker.MagicMock()
+ mock_pull.labels = [mock_label]
+
+ mock_pulls_resp = mocker.MagicMock()
+ mock_pulls_resp.parsed_data = [mock_pull]
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.pulls.async_list",
+ {"owner": "owner", "repo": "repo", "state": "open"},
+ mock_pulls_resp,
+ )
+
+ pulls = await get_pull_requests_by_label(
+ bot, RepoInfo(owner="owner", repo="repo"), PublishType.BOT
+ )
+ assert pulls[0] == mock_pull
+
+
+async def test_get_pull_requests_by_label_not_match(
+ app: App, mocker: MockerFixture
+) -> None:
+ """测试获取指定标签的拉取请求,但是没有匹配的"""
+ from src.plugins.publish.depends import get_pull_requests_by_label
+ from src.plugins.publish.models import PublishType, RepoInfo
+
+ mock_label = mocker.MagicMock()
+ mock_label.name = "Some"
+
+ mock_pull = mocker.MagicMock()
+ mock_pull.labels = [mock_label]
+
+ mock_pulls_resp = mocker.MagicMock()
+ mock_pulls_resp.parsed_data = [mock_pull]
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.pulls.async_list",
+ {"owner": "owner", "repo": "repo", "state": "open"},
+ mock_pulls_resp,
+ )
+
+ pulls = await get_pull_requests_by_label(
+ bot, RepoInfo(owner="owner", repo="repo"), PublishType.BOT
+ )
+ assert pulls == []
diff --git a/tests/utils/test_resolve_conflict_pull_requests.py b/tests/utils/test_resolve_conflict_pull_requests.py
index 8e7d3dba..f6bd16ce 100644
--- a/tests/utils/test_resolve_conflict_pull_requests.py
+++ b/tests/utils/test_resolve_conflict_pull_requests.py
@@ -1,122 +1,140 @@
-# import json
-# from pathlib import Path
-# from typing import Any
-
-# from pytest_mock import MockerFixture
-
-
-# def mocked_httpx_get(url: str):
-# class MockResponse:
-# def __init__(self, status_code: int):
-# self.status_code = status_code
-
-# if url == "https://v2.nonebot.dev":
-# return MockResponse(200)
-
-# return MockResponse(404)
-
-
-# def check_json_data(file: Path, data: Any) -> None:
-# with open(file) as f:
-# assert json.load(f) == data
-
-
-# def test_resolve_conflict_pull_requests(mocker: MockerFixture, tmp_path: Path) -> None:
-# import src.globals as g
-# from src import Bot
-
-# bot = Bot()
-# bot.github = mocker.MagicMock()
-
-# mocker.patch("httpx.get", side_effect=mocked_httpx_get)
-# mock_subprocess_run = mocker.patch("subprocess.run")
-# mock_result = mocker.MagicMock()
-# mock_subprocess_run.side_effect = lambda *args, **kwargs: mock_result
-
-# mock_label = mocker.MagicMock()
-# mock_label.name = "Bot"
-
-# 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
-# mock_issue.user.login = "test"
-# mock_issue.labels = [mock_label]
-
-# mock_issues_resp = mocker.MagicMock()
-# bot.github.rest.issues.get.return_value = mock_issues_resp
-# mock_issues_resp.parsed_data = mock_issue
-
-# mock_pull = mocker.MagicMock()
-# mock_pull.head.ref = "publish/issue1"
-
-# with open(tmp_path / "bots.json", "w") as f:
-# json.dump([], f)
-
-# check_json_data(g.settings.input_config.bot_path, [])
-
-# bot.resolve_conflict_pull_requests([mock_pull])
-
-# bot.github.rest.issues.get.assert_called_with("owner", "repo", 1)
-
-# # 测试 git 命令
-# mock_subprocess_run.assert_has_calls(
-# [
-# mocker.call(["git", "checkout", "master"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "switch", "-C", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "config", "--global", "user.name", "test"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# [
-# "git",
-# "config",
-# "--global",
-# "user.email",
-# "test@users.noreply.github.com",
-# ],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "add", "-A"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "commit", "-m", ":beers: publish bot test (#1)"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
-# mocker.call(
-# ["git", "diff", "origin/publish/issue1", "publish/issue1"],
-# check=True,
-# capture_output=True,
-# ),
-# mocker.call(
-# ["git", "push", "origin", "publish/issue1", "-f"],
-# check=True,
-# capture_output=True,
-# ),
-# ] # type: ignore
-# )
-
-# # 检查文件是否正确
-# check_json_data(
-# g.settings.input_config.bot_path,
-# [
-# {
-# "name": "test",
-# "desc": "desc",
-# "author": "test",
-# "homepage": "https://v2.nonebot.dev",
-# "tags": [{"label": "test", "color": "#ffffff"}],
-# "is_official": False,
-# }
-# ],
-# )
+import json
+from pathlib import Path
+from typing import Any, cast
+
+from nonebot import get_adapter
+from nonebot.adapters.github import Adapter, GitHubBot
+from nonebot.adapters.github.config import GitHubApp
+from nonebug import App
+from pytest_mock import MockerFixture
+
+
+def mocked_httpx_get(url: str):
+ class MockResponse:
+ def __init__(self, status_code: int):
+ self.status_code = status_code
+
+ if url == "https://v2.nonebot.dev":
+ return MockResponse(200)
+
+ return MockResponse(404)
+
+
+def check_json_data(file: Path, data: Any) -> None:
+ with open(file) as f:
+ assert json.load(f) == data
+
+
+async def test_resolve_conflict_pull_requests(
+ app: App, mocker: MockerFixture, tmp_path: Path
+) -> None:
+ from src.plugins.publish.config import plugin_config
+ from src.plugins.publish.models import RepoInfo
+ from src.plugins.publish.utils import resolve_conflict_pull_requests
+
+ mocker.patch("httpx.get", side_effect=mocked_httpx_get)
+ mock_subprocess_run = mocker.patch("subprocess.run")
+ mock_result = mocker.MagicMock()
+ mock_subprocess_run.side_effect = lambda *args, **kwargs: mock_result
+
+ mock_label = mocker.MagicMock()
+ mock_label.name = "Bot"
+
+ 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 = """**机器人名称:**\n\ntest\n\n**机器人功能:**\n\ndesc\n\n**机器人项目仓库/主页链接:**\n\nhttps://v2.nonebot.dev\n\n**标签:**\n\n[{"label": "test", "color": "#ffffff"}]"""
+ mock_issue.user.login = "test"
+ mock_issue.labels = [mock_label]
+
+ mock_issues_resp = mocker.MagicMock()
+ mock_issues_resp.parsed_data = mock_issue
+
+ mock_pull = mocker.MagicMock()
+ mock_pull.head.ref = "publish/issue1"
+
+ with open(tmp_path / "bots.json", "w") as f:
+ json.dump([], f)
+
+ check_json_data(plugin_config.input_config.bot_path, [])
+
+ async with app.test_api() as ctx:
+ adapter = get_adapter(Adapter)
+ bot = ctx.create_bot(
+ base=GitHubBot,
+ adapter=adapter,
+ self_id=GitHubApp(app_id="1", private_key="1"), # type: ignore
+ )
+ bot = cast(GitHubBot, bot)
+
+ ctx.should_call_api(
+ "rest.issues.async_get",
+ {"owner": "owner", "repo": "repo", "issue_number": 1},
+ mock_issues_resp,
+ )
+
+ await resolve_conflict_pull_requests(
+ bot, RepoInfo(owner="owner", repo="repo"), [mock_pull]
+ )
+
+ # 测试 git 命令
+ mock_subprocess_run.assert_has_calls(
+ [
+ mocker.call(["git", "checkout", "master"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "switch", "-C", "publish/issue1"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "config", "--global", "user.name", "test"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ [
+ "git",
+ "config",
+ "--global",
+ "user.email",
+ "test@users.noreply.github.com",
+ ],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "add", "-A"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "commit", "-m", ":beers: publish bot test (#1)"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(["git", "fetch", "origin"], check=True, capture_output=True),
+ mocker.call(
+ ["git", "diff", "origin/publish/issue1", "publish/issue1"],
+ check=True,
+ capture_output=True,
+ ),
+ mocker.call(
+ ["git", "push", "origin", "publish/issue1", "-f"],
+ check=True,
+ capture_output=True,
+ ),
+ ] # type: ignore
+ )
+
+ # 检查文件是否正确
+ check_json_data(
+ plugin_config.input_config.bot_path,
+ [
+ {
+ "name": "test",
+ "desc": "desc",
+ "author": "test",
+ "homepage": "https://v2.nonebot.dev",
+ "tags": [{"label": "test", "color": "#ffffff"}],
+ "is_official": False,
+ }
+ ],
+ )