From f70c0a49c8c882cd036ab8523267a37b58ca46e8 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 1/11] Add support for pagure-messages This adds messages schemas to the notifications sent and ensures that this schema is applied and thus the data-structure used is the expected one. Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index 92eb0bd..47474ed 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -80,13 +80,27 @@ def fedora_messaging_publish(topic, message): # pragma: no cover try: import fedora_messaging.api import fedora_messaging.exceptions + import pagure_messages - msg = fedora_messaging.api.Message( - topic="pagure.{}".format(topic), body=message + msg_cls = pagure_messages.get_message_object_from_topic( + "pagure.{}".format(topic) ) + + if not hasattr(msg_cls, "app_name") is False: + _log.warning( + "pagure is about to send a message that has no schemas: %s", + topic, + ) + + msg = msg_cls(body=message) + if not msg.topic: + msg.topic = "pagure.{}".format(topic) fedora_messaging.api.publish(msg) except ImportError: - _log.warning("Fedora messaging does not appear to be available") + _log.warning( + "Fedora messaging or pagure-messages does not appear to be " + "available" + ) except fedora_messaging.exceptions.PublishReturned as e: _log.warning( "Fedora Messaging broker rejected message %s: %s", msg.id, e diff --git a/requirements-testing.txt b/requirements-testing.txt index a9563d9..00005ee 100644 --- a/requirements-testing.txt +++ b/requirements-testing.txt @@ -7,6 +7,7 @@ fedmsg flake8 flask-oidc mock +pagure-messages >= 0.0.1 pytest pytest-cov pytest-xdist From e4f4c75a33171ab8bb515cf1ace5303db36fad8e Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 2/11] Sort a number of lists returned in the API This way we are sure the data returned is consistently ordered and thus we can confidently test it in the test suite. Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/model.py b/pagure/lib/model.py index 0c935a6..57c0179 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -1505,7 +1505,7 @@ class Issue(BASE): @property def tags_text(self): """ Return the list of tags in a simple text form. """ - return [tag.tag for tag in self.tags] + return sorted([tag.tag for tag in self.tags]) @property def depending_text(self): @@ -2180,7 +2180,7 @@ class PullRequest(BASE): @property def tags_text(self): """ Return the list of tags in a simple text form. """ - return [tag.tag for tag in self.tags] + return sorted([tag.tag for tag in self.tags]) @property def discussion(self): diff --git a/pagure/lib/query.py b/pagure/lib/query.py index 513a4aa..3c9a3e0 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -511,7 +511,7 @@ def add_tag_obj(session, obj, tags, user): msg=dict( issue=obj.to_json(public=True), project=obj.project.to_json(public=True), - tags=added_tags, + tags=sorted(added_tags), agent=user_obj.username, ), ) @@ -537,7 +537,7 @@ def add_tag_obj(session, obj, tags, user): msg=dict( pull_request=obj.to_json(public=True), project=obj.project.to_json(public=True), - tags=added_tags, + tags=sorted(added_tags), agent=user_obj.username, ), ) @@ -851,7 +851,7 @@ def remove_tags(session, project, tags, user): topic="project.tag.removed", msg=dict( project=project.to_json(public=True), - tags=removed_tags, + tags=sorted(removed_tags), agent=user_obj.username, ), ) @@ -895,7 +895,7 @@ def remove_tags_obj(session, obj, tags, user): msg=dict( issue=obj.to_json(public=True), project=obj.project.to_json(public=True), - tags=removed_tags, + tags=sorted(removed_tags), agent=user_obj.username, ), ) @@ -915,7 +915,7 @@ def remove_tags_obj(session, obj, tags, user): msg=dict( pull_request=obj.to_json(public=True), project=obj.project.to_json(public=True), - tags=removed_tags, + tags=sorted(removed_tags), agent=user_obj.username, ), ) @@ -2169,7 +2169,7 @@ def edit_issue( msg=dict( issue=issue.to_json(public=True), project=issue.project.to_json(public=True), - fields=list(set(edit)), + fields=sorted(set(edit)), agent=user_obj.username, ), ) @@ -2260,7 +2260,7 @@ def update_project_settings(session, repo, settings, user, from_api=False): topic="project.edit", msg=dict( project=repo.to_json(public=True), - fields=update, + fields=sorted(update), agent=user_obj.username, ), ) From 57635ed839d14589fd9f216ef134e11ed17ad3f7 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 3/11] Commit to the database earlier in the process so the JSON sent is up to date Otherwise, the JSON representation of the object was not up to date which resulted in some odd notifications (ie: a new comment added while the comment did not show up in the JSON, or a new tag which does not show, and so on). Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/query.py b/pagure/lib/query.py index 3c9a3e0..d33f5e3 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -498,7 +498,8 @@ def add_tag_obj(session, obj, tags, user): session.add(dbobjtag) # Make sure we won't have SQLAlchemy error before we continue - session.flush() + # Commit so the tags show up in the notification sent + session.commit() added_tags.append(tagobj.tag) if isinstance(obj, model.Issue): @@ -710,7 +711,8 @@ def add_issue_dependency(session, issue, issue_blocked, user): ) session.add(i2i) # Make sure we won't have SQLAlchemy error before we continue - session.flush() + # and commit so the blocking issue appears in the JSON representation + session.commit() pagure.lib.git.update_git(issue, repo=issue.project) pagure.lib.git.update_git(issue_blocked, repo=issue_blocked.project) @@ -769,7 +771,8 @@ def remove_issue_dependency(session, issue, issue_blocked, user): issue.parents.remove(parent) # Make sure we won't have SQLAlchemy error before we continue - session.flush() + # and commit so the blocking issue appears in the JSON representation + session.commit() pagure.lib.git.update_git(issue, repo=issue.project) pagure.lib.git.update_git(issue_blocked, repo=issue_blocked.project) @@ -886,6 +889,9 @@ def remove_tags_obj(session, obj, tags, user): removed_tags.append(tag) session.delete(objtag) + # Commit so the tags are updated in the notification sent + session.commit() + if isinstance(obj, model.Issue): pagure.lib.git.update_git(obj, repo=obj.project) @@ -1151,7 +1157,7 @@ def add_user_to_project( update_read_only_mode(session, project, read_only=True) session.add(access_obj) session.add(project) - session.flush() + session.commit() pagure.lib.notify.log( project, @@ -1178,8 +1184,8 @@ def add_user_to_project( # Mark the project as read only, celery will then unmark it update_read_only_mode(session, project, read_only=True) session.add(project) - # Make sure we won't have SQLAlchemy error before we continue - session.flush() + # Commit so the JSON sent in the notification is up to date + session.commit() pagure.lib.notify.log( project, @@ -1263,7 +1269,8 @@ def add_group_to_project( project.date_modified = datetime.datetime.utcnow() update_read_only_mode(session, project, read_only=True) session.add(project) - session.flush() + # Commit so the JSON sent in the notification is up to date + session.commit() pagure.lib.notify.log( project, @@ -1291,7 +1298,8 @@ def add_group_to_project( # Mark the project read_only, celery will then unmark it update_read_only_mode(session, project, read_only=True) session.add(project) - session.flush() + # Commit so the JSON sent in the notification is up to date + session.commit() pagure.lib.notify.log( project, From e232a3eb34f34d7b84686942fe9be4855752472d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 4/11] Be consistent about the name of the pull-request object and topics Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/query.py b/pagure/lib/query.py index d33f5e3..132223d 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -537,6 +537,7 @@ def add_tag_obj(session, obj, tags, user): topic="pull-request.tag.added", msg=dict( pull_request=obj.to_json(public=True), + pullrequest=obj.to_json(public=True), project=obj.project.to_json(public=True), tags=sorted(added_tags), agent=user_obj.username, @@ -655,11 +656,23 @@ def add_pull_request_assignee(session, request, assignee, user): pagure.lib.notify.notify_assigned_request(request, None, user_obj) + # Deprecated -- this is not consistent in both the topic and the body: + # request vs pull-request (topic) and request vs pullrequest (body) pagure.lib.notify.log( request.project, topic="request.assigned.reset", msg=dict( request=request.to_json(public=True), + pullrequest=request.to_json(public=True), + project=request.project.to_json(public=True), + agent=user_obj.username, + ), + ) + pagure.lib.notify.log( + request.project, + topic="pull-request.assigned.reset", + msg=dict( + pullrequest=request.to_json(public=True), project=request.project.to_json(public=True), agent=user_obj.username, ), @@ -683,11 +696,23 @@ def add_pull_request_assignee(session, request, assignee, user): request, assignee_obj, user_obj ) + # Deprecated -- this is not consistent in both the topic and the body: + # request vs pull-request (topic) and request vs pullrequest (body) pagure.lib.notify.log( request.project, topic="request.assigned.added", msg=dict( request=request.to_json(public=True), + pullrequest=request.to_json(public=True), + project=request.project.to_json(public=True), + agent=user_obj.username, + ), + ) + pagure.lib.notify.log( + request.project, + topic="pull-request.assigned.added", + msg=dict( + pullrequest=request.to_json(public=True), project=request.project.to_json(public=True), agent=user_obj.username, ), @@ -920,6 +945,7 @@ def remove_tags_obj(session, obj, tags, user): topic="pull-request.tag.removed", msg=dict( pull_request=obj.to_json(public=True), + pullrequest=obj.to_json(public=True), project=obj.project.to_json(public=True), tags=sorted(removed_tags), agent=user_obj.username, From 40d3f0678b25fffe8e11f8701e0c2b7645bea3cc Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 5/11] Add a notification for when a group is removed from a project Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 4660a86..27c4f78 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -2163,11 +2163,24 @@ def remove_group_project(repo, groupid, username=None, namespace=None): + "#usersgroups-tab" ) + removed_groups = [] for grp in repo.groups: if grp.id == groupid: + removed_groups.append(grp.group_name) repo.groups.remove(grp) break try: + # Commit so the JSON sent on the notification is up to date + flask.g.session.commit() + pagure.lib.notify.log( + repo, + topic="project.group.removed", + msg=dict( + project=repo.to_json(public=True), + removed_groups=removed_groups, + agent=flask.g.fas_user.username, + ), + ) # Mark the project as read_only, celery will unmark it pagure.lib.query.update_read_only_mode( flask.g.session, repo, read_only=True From 91c0c7c45d135c3ea06fbc5f9d2fd7bbef33eea0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 6/11] Test the fedora-messaging notifications sent in the test suite Signed-off-by: Pierre-Yves Chibon --- diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py index cf24810..ce7727a 100644 --- a/tests/test_pagure_flask_api_issue.py +++ b/tests/test_pagure_flask_api_issue.py @@ -20,9 +20,12 @@ import time import os import flask +import pagure_messages import json import munch -from mock import patch, MagicMock + +from fedora_messaging import api, testing +from mock import ANY, patch, MagicMock from sqlalchemy.exc import SQLAlchemyError sys.path.insert( @@ -469,6 +472,9 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): }, ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_api_new_issue(self): """ Test the api_new_issue method of the flask api. """ tests.create_projects(self.session) @@ -486,9 +492,82 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): } # Valid request - output = self.app.post( - "/api/0/test/new_issue", data=data, headers=headers - ) + with testing.mock_sends( + pagure_messages.IssueNewV1( + topic="pagure.issue.new", + body={ + "issue": { + "id": 1, + "title": "test issue", + "content": "This issue needs attention", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/new_issue", data=data, headers=headers + ) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) data["issue"]["date_created"] = "1431414800" @@ -758,6 +837,58 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): self.assertDictEqual(data, {"issue": exp, "message": "Issue created"}) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) + def test_api_new_issue_private_no_fedora_messaging_notifs(self): + """ Test the api_new_issue method of the flask api. """ + tests.create_projects(self.session) + tests.create_projects_git( + os.path.join(self.path, "tickets"), bare=True + ) + tests.create_tokens(self.session) + tests.create_tokens_acl(self.session) + + headers = {"Authorization": "token aaabbbcccddd"} + + # Private issue: True + data = { + "title": "test issue", + "issue_content": "This issue needs attention", + "private": True, + } + output = self.app.post( + "/api/0/test/new_issue", data=data, headers=headers + ) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + data["issue"]["date_created"] = "1431414800" + data["issue"]["last_updated"] = "1431414800" + + issue = copy.deepcopy(FULL_ISSUE_LIST[2]) + issue["id"] = 1 + + self.assertDictEqual( + data, {"issue": issue, "message": "Issue created"} + ) + + # Private issue: 1 + data = { + "title": "test issue1", + "issue_content": "This issue needs attention", + "private": 1, + "assignee": "foo", + } + with self.assertRaises(AssertionError) as cm: + with testing.mock_sends(api.Message()): + output = self.app.post( + "/api/0/test/new_issue", data=data, headers=headers + ) + self.assertEqual( + cm.exception.args[0], + "Expected 1 messages to be sent, but 0 were sent", + ) + @patch("pagure.utils.check_api_acls", MagicMock(return_value=None)) def test_api_new_issue_raise_db_error(self): """ Test the api_new_issue method of the flask api. """ @@ -2982,6 +3113,9 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): }, ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_api_change_milestone_issue(self): """ Test the api_change_milestone_issue method of the flask api. """ tests.create_projects(self.session) @@ -3017,9 +3151,86 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): data = {"milestone": "v1.0"} # Valid requests - output = self.app.post( - "/api/0/test/issue/1/milestone", data=data, headers=headers - ) + with testing.mock_sends( + pagure_messages.IssueEditV1( + topic="pagure.issue.edit", + body={ + "issue": { + "id": 1, + "title": "Test issue #1", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": "v1.0", + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": { + "v1.0": {"date": None, "active": True}, + "v2.0": {"date": "Soon", "active": True}, + }, + }, + "fields": ["milestone"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/issue/1/milestone", data=data, headers=headers + ) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) self.assertDictEqual( @@ -3554,6 +3765,9 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): pagure.api.APIERROR.ETRACKERDISABLED.name, data["error_code"] ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_api_assign_issue(self, p_send_email, p_ugt): @@ -3620,17 +3834,184 @@ class PagureFlaskApiIssuetests(tests.SimplePagureTest): data = {"assignee": "pingou"} # Valid request - output = self.app.post( - "/api/0/test/issue/1/assign", data=data, headers=headers - ) + with testing.mock_sends( + pagure_messages.IssueAssignedAddedV1( + topic="pagure.issue.assigned.added", + body={ + "issue": { + "id": 1, + "title": "Test issue #1", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/issue/1/assign", data=data, headers=headers + ) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) self.assertDictEqual(data, {"message": "Issue assigned to pingou"}) # Un-assign - output = self.app.post( - "/api/0/test/issue/1/assign", data=data, headers=headers - ) + with testing.mock_sends( + pagure_messages.IssueAssignedResetV1( + topic="pagure.issue.assigned.reset", + body={ + "issue": { + "id": 1, + "title": "Test issue #1", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [ + { + "id": 1, + "comment": "**Metadata Update from @pingou**:" + "\n- Issue assigned to pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/issue/1/assign", data=data, headers=headers + ) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) self.assertDictEqual(data, {"message": "Assignee reset"}) diff --git a/tests/test_pagure_flask_api_pr_flag.py b/tests/test_pagure_flask_api_pr_flag.py index 8acb575..d162c3a 100644 --- a/tests/test_pagure_flask_api_pr_flag.py +++ b/tests/test_pagure_flask_api_pr_flag.py @@ -15,7 +15,9 @@ import sys import os import json -from mock import patch, MagicMock +import pagure_messages +from fedora_messaging import api, testing +from mock import ANY, patch, MagicMock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -219,6 +221,9 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): data = json.loads(output.get_data(as_text=True)) self.assertDictEqual(data, {"error": "error", "error_code": "ENOCODE"}) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_flagging_a_pul_request_with_notification(self, mock_email): """ Test the flagging a PR. """ @@ -240,10 +245,138 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): } # Valid request - output = self.app.post( - "/api/0/test/pull-request/1/flag", data=data, headers=headers - ) - self.assertEqual(output.status_code, 200) + with testing.mock_sends( + pagure_messages.PullRequestFlagAddedV1( + topic="pagure.pull-request.flag.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "test pull-request", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "master", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": None, + "commit_stop": None, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "flag": { + "pull_request_uid": ANY, + "username": "Jenkins", + "percent": None, + "comment": "Tests running", + "status": "pending", + "url": "http://jenkins.cloud.fedoraproject.org/", + "date_created": ANY, + "date_updated": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/pull-request/1/flag", data=data, headers=headers + ) + self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) data["flag"]["date_created"] = "1510742565" data["flag"]["date_updated"] = "1510742565" @@ -305,6 +438,9 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): user_from="Jenkins", ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_updating_flag(self): """ Test the updating the flag of a PR. """ headers = {"Authorization": "token aaabbbcccddd"} @@ -374,9 +510,137 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): "uid": "jenkins_build_pagure_100+seed", } - output = self.app.post( - "/api/0/test/pull-request/1/flag", data=data, headers=headers - ) + with testing.mock_sends( + pagure_messages.PullRequestFlagUpdatedV1( + topic="pagure.pull-request.flag.updated", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "test pull-request", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "master", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": None, + "commit_stop": None, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "flag": { + "pull_request_uid": ANY, + "username": "Jenkins", + "percent": "100", + "comment": "Tests passed", + "status": "success", + "url": "http://jenkins.cloud.fedoraproject.org/", + "date_created": ANY, + "date_updated": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/pull-request/1/flag", data=data, headers=headers + ) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) data["flag"]["date_created"] = "1510742565" diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 86a5469..de40d0f 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -14,6 +14,7 @@ from __future__ import unicode_literals, absolute_import import datetime import json import unittest +import pagure_messages import shutil import sys import tempfile @@ -21,7 +22,8 @@ import os import pygit2 from celery.result import EagerResult -from mock import patch, Mock +from fedora_messaging import api, testing +from mock import ANY, patch, Mock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -2927,6 +2929,221 @@ class PagureFlaskApiProjectFlagtests(tests.Modeltests): self.assertEqual(data, expected_output) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) + def test_update_flag_commit_with_uid(self): + """ Test flagging a commit with provided uid. """ + repo_obj = pygit2.Repository(self.git_path) + commit = repo_obj.revparse_single("HEAD") + + headers = {"Authorization": "token aaabbbcccddd"} + data = { + "username": "Jenkins", + "percent": 0, + "comment": "Tests running", + "url": "http://jenkins.cloud.fedoraproject.org/", + "uid": "jenkins_build_pagure_100+seed", + "status": "pending", + } + with testing.mock_sends( + pagure_messages.CommitFlagAddedV1( + topic="pagure.commit.flag.added", + body={ + "repo": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "flag": { + "commit_hash": commit.oid.hex, + "username": "Jenkins", + "percent": "0", + "comment": "Tests running", + "status": "pending", + "url": "http://jenkins.cloud.fedoraproject.org/", + "date_created": ANY, + "date_updated": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/c/%s/flag" % commit.oid.hex, + headers=headers, + data=data, + ) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + data["flag"]["date_created"] = "1510742565" + data["flag"]["date_updated"] = "1510742565" + expected_output = { + "flag": { + "comment": "Tests running", + "commit_hash": commit.oid.hex, + "date_created": "1510742565", + "date_updated": "1510742565", + "percent": 0, + "status": "pending", + "url": "http://jenkins.cloud.fedoraproject.org/", + "user": { + "default_email": "bar@pingou.com", + "emails": ["bar@pingou.com", "foo@pingou.com"], + "fullname": "PY C", + "name": "pingou", + "url_path": "user/pingou", + }, + "username": "Jenkins", + }, + "message": "Flag added", + "uid": "jenkins_build_pagure_100+seed", + } + + self.assertEqual(data, expected_output) + + data = { + "username": "Jenkins", + "percent": 100, + "comment": "Tests passed", + "url": "http://jenkins.cloud.fedoraproject.org/", + "uid": "jenkins_build_pagure_100+seed", + "status": "success", + } + with testing.mock_sends( + pagure_messages.CommitFlagUpdatedV1( + topic="pagure.commit.flag.updated", + body={ + "repo": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "flag": { + "commit_hash": commit.oid.hex, + "username": "Jenkins", + "percent": "100", + "comment": "Tests passed", + "status": "success", + "url": "http://jenkins.cloud.fedoraproject.org/", + "date_created": ANY, + "date_updated": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/api/0/test/c/%s/flag" % commit.oid.hex, + headers=headers, + data=data, + ) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + data["flag"]["date_created"] = "1510742565" + data["flag"]["date_updated"] = "1510742565" + expected_output = { + "flag": { + "comment": "Tests passed", + "commit_hash": commit.oid.hex, + "date_created": "1510742565", + "date_updated": "1510742565", + "percent": 100, + "status": "success", + "url": "http://jenkins.cloud.fedoraproject.org/", + "user": { + "default_email": "bar@pingou.com", + "emails": ["bar@pingou.com", "foo@pingou.com"], + "fullname": "PY C", + "name": "pingou", + "url_path": "user/pingou", + }, + "username": "Jenkins", + }, + "message": "Flag updated", + "uid": "jenkins_build_pagure_100+seed", + } + + self.assertEqual(data, expected_output) + @patch("pagure.lib.notify.send_email") def test_flag_commit_without_uid(self, mock_email): """ Test flagging a commit with missing info. @@ -3003,6 +3220,7 @@ class PagureFlaskApiProjectFlagtests(tests.Modeltests): "url": "http://jenkins.cloud.fedoraproject.org/", "status": "success", } + output = self.app.post( "/api/0/test/c/%s/flag" % commit.oid.hex, headers=headers, @@ -5081,6 +5299,9 @@ class PagureFlaskApiProjectCreateProjectTests(tests.Modeltests): data = json.loads(output.get_data(as_text=True)) self.assertDictEqual(data, {"message": 'Project "api1" created'}) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_api_new_project(self): headers = {"Authorization": "token aaabbbcccddd"} @@ -5090,7 +5311,49 @@ class PagureFlaskApiProjectCreateProjectTests(tests.Modeltests): } # Valid request - output = self.app.post("/api/0/new/", data=data, headers=headers) + with testing.mock_sends( + pagure_messages.ProjectNewV1( + topic="pagure.project.new", + body={ + "project": { + "id": 4, + "name": "test_42", + "fullname": "test_42", + "url_path": "test_42", + "description": "Just another small test project", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post("/api/0/new/", data=data, headers=headers) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) self.assertDictEqual(data, {"message": 'Project "test_42" created'}) diff --git a/tests/test_pagure_flask_dump_load_ticket.py b/tests/test_pagure_flask_dump_load_ticket.py index aefd8a8..33d46c6 100644 --- a/tests/test_pagure_flask_dump_load_ticket.py +++ b/tests/test_pagure_flask_dump_load_ticket.py @@ -142,7 +142,7 @@ class PagureFlaskDumpLoadTicketTests(tests.Modeltests): ) ] ) - self.assertIn(cnt, (9, 10)) + self.assertIn(cnt, (9, 10, 11)) last_commit = repo.revparse_single("HEAD") patch = pagure.lib.git.commit_to_patch(repo, last_commit) diff --git a/tests/test_pagure_flask_rebase.py b/tests/test_pagure_flask_rebase.py index c7cd980..5e645d0 100644 --- a/tests/test_pagure_flask_rebase.py +++ b/tests/test_pagure_flask_rebase.py @@ -17,7 +17,9 @@ import sys import os import json -from mock import patch, MagicMock +import pagure_messages +from fedora_messaging import api, testing +from mock import ANY, patch, MagicMock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -181,6 +183,9 @@ class PagureRebasetests(tests.Modeltests): }, ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_rebase_api_ui_logged_in(self): """ Test the rebase PR API endpoint when logged in from the UI and its outcome. """ @@ -203,10 +208,321 @@ class PagureRebasetests(tests.Modeltests): }, ) - output = self.app.post("/api/0/test/pull-request/1/rebase") - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual(data, {"message": "Pull-request rebased"}) + with testing.mock_sends( + pagure_messages.PullRequestRebasedV1( + topic="pagure.pull-request.rebased", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the test branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "test", + "repo_from": { + "id": 4, + "name": "test", + "fullname": "forks/foo/test", + "url_path": "fork/foo/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "access_users": { + "owner": ["foo"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "agent": "pagure", + }, + ), + pagure_messages.PullRequestCommentAddedV1( + topic="pagure.pull-request.comment.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the test branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "test", + "repo_from": { + "id": 4, + "name": "test", + "fullname": "forks/foo/test", + "url_path": "fork/foo/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "access_users": { + "owner": ["foo"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": ANY, + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "agent": "pingou", + }, + ), + ): + + output = self.app.post("/api/0/test/pull-request/1/rebase") + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual(data, {"message": "Pull-request rebased"}) data = {"requestid": self.request.uid, "csrf_token": csrf_token} output = self.app.post("/pv/pull-request/merge", data=data) diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py index 6cabfaa..50e2f61 100644 --- a/tests/test_pagure_flask_ui_fork.py +++ b/tests/test_pagure_flask_ui_fork.py @@ -19,11 +19,13 @@ import time import os import re +import pagure_messages import pygit2 import six -from mock import patch, MagicMock from bs4 import BeautifulSoup from datetime import datetime, timedelta +from fedora_messaging import api, testing +from mock import ANY, patch, MagicMock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -2335,6 +2337,9 @@ index 0000000..2a552bb ) self.assertIn("Pull request closed!", output_text) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_reopen_request_pull(self, send_email): """ Test the reopen_request_pull endpoint. """ @@ -2422,16 +2427,606 @@ index 0000000..2a552bb ) settings = repo.settings settings["pull_requests"] = True + settings["fedmsg_notifications"] = True repo.settings = settings self.session.add(repo) self.session.commit() - output = self.app.post( - "/test/pull-request/cancel/1", data=data, follow_redirects=True - ) - output = self.app.post( - "/test/pull-request/1/reopen", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.PullRequestCommentAddedV1( + topic="pagure.pull-request.comment.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Closed", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been closed by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "agent": "pingou", + }, + ), + pagure_messages.PullRequestClosedV1( + topic="pagure.pull-request.closed", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Closed", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been closed by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "merged": False, + "agent": "pingou", + }, + ), + ): + output = self.app.post( + "/test/pull-request/close/1", + data=data, + follow_redirects=True, + ) + self.assertEqual(output.status_code, 200) + + with testing.mock_sends( + pagure_messages.PullRequestCommentAddedV1( + topic="pagure.pull-request.comment.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been closed by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + }, + { + "id": 2, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been reopened by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + }, + ], + }, + "agent": "pingou", + }, + ), + pagure_messages.PullRequestReopenedV1( + topic="pagure.pull-request.reopened", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been closed by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + }, + { + "id": 2, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "Pull-Request has been reopened by pingou", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + }, + ], + }, + "agent": "pingou", + }, + ), + ): + output = self.app.post( + "/test/pull-request/1/reopen", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2444,6 +3039,9 @@ index 0000000..2a552bb output_text, ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) def test_update_pull_requests_assign(self): """ Test the update_pull_requests endpoint when assigning a PR. @@ -2554,9 +3152,430 @@ index 0000000..2a552bb user.username = "pingou" with tests.user_set(self.app.application, user): - output = self.app.post( - "/test/pull-request/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + api.Message( + topic="pagure.request.assigned.added", + body={ + "request": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ), + pagure_messages.PullRequestAssignedAddedV1( + topic="pagure.pull-request.assigned.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ), + ): + output = self.app.post( + "/test/pull-request/1/update", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2575,7 +3594,7 @@ index 0000000..2a552bb ) self.assertIn("Request assigned", output_text) - # Pull-Request closed + # Pull-Request closed - reset assignee repo = pagure.lib.query.get_authorized_project( self.session, "test" ) @@ -2585,9 +3604,480 @@ index 0000000..2a552bb self.session.add(req) self.session.commit() - output = self.app.post( - "/test/pull-request/1/update", data=data, follow_redirects=True - ) + data = {"csrf_token": csrf_token, "user": None} + + with testing.mock_sends( + api.Message( + topic="pagure.request.assigned.reset", + body={ + "request": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Closed", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**Metadata Update from @pingou**:\n- Request assigned", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Closed", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**Metadata Update from @pingou**:\n- Request assigned", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ), + pagure_messages.PullRequestAssignedResetV1( + topic="pagure.pull-request.assigned.reset", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Closed", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**Metadata Update from @pingou**:\n- Request assigned", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ), + ): + output = self.app.post( + "/test/pull-request/1/update", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) # Project w/o pull-request @@ -2605,6 +4095,9 @@ index 0000000..2a552bb ) self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) def test_update_pull_requests_tag(self): """ Test the update_pull_requests endpoint when tagging a PR. @@ -2653,10 +4146,168 @@ index 0000000..2a552bb # Tag the PR data = {"csrf_token": csrf_token, "tag": "black"} - output = self.app.post( - "/test/pull-request/1/update", data=data, follow_redirects=True - ) - self.assertEqual(output.status_code, 200) + with testing.mock_sends( + pagure_messages.PullRequestTagAddedV1( + topic="pagure.pull-request.tag.added", + body={ + # This is field is for backward compatibility but we + # don't want to check it + "pull_request": ANY, + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": ["black"], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["black"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/pull-request/1/update", + data=data, + follow_redirects=True, + ) + self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( "PR#1: PR from the feature branch - test\n - " @@ -2702,9 +4353,363 @@ index 0000000..2a552bb # Re-try to tag the PR data = {"csrf_token": csrf_token, "tag": "blue, yellow"} - output = self.app.post( - "/test/pull-request/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.PullRequestTagAddedV1( + topic="pagure.pull-request.tag.added", + body={ + "pull_request": ANY, + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": ["black", "blue", "yellow"], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**Metadata Update from " + "@pingou**:\n- Pull-request tagged " + "with: black", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["blue", "yellow"], + "agent": "foo", + }, + ), + pagure_messages.PullRequestTagRemovedV1( + topic="pagure.pull-request.tag.removed", + body={ + # This is field is for backward compatibility but we + # don't want to check it + "pull_request": ANY, + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": ["blue", "yellow"], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**Metadata Update from " + "@pingou**:\n- Pull-request tagged " + "with: black", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["black"], + "agent": "foo", + }, + ), + ): + output = self.app.post( + "/test/pull-request/1/update", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) soup = BeautifulSoup(output.get_data(as_text=True), "html.parser") self.assertEqual( @@ -2753,6 +4758,9 @@ index 0000000..2a552bb ) self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_fork_project(self, send_email): """ Test the fork_project endpoint. """ @@ -2793,10 +4801,90 @@ index 0000000..2a552bb data = {"csrf_token": csrf_token} - output = self.app.post( - "/do_fork/test", data=data, follow_redirects=True - ) - self.assertEqual(output.status_code, 200) + with testing.mock_sends( + pagure_messages.ProjectForkedV1( + topic="pagure.project.forked", + body={ + "project": { + "id": 4, + "name": "test", + "fullname": "forks/foo/test", + "url_path": "fork/foo/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "access_users": { + "owner": ["foo"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "agent": "foo", + }, + ) + ): + output = self.app.post( + "/do_fork/test", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) def test_fork_project_non_master_default(self): @@ -2881,6 +4969,9 @@ index 0000000..2a552bb output_text = output.get_data(as_text=True) self.assertIn("<p>Branch foo bar does not exist</p>", output_text) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_new_request_pull(self, send_email): """ Test the new_request_pull endpoint. """ @@ -2987,9 +5078,124 @@ More information</textarea> "initial_comment": "Test Initial Comment", } - output = self.app.post( - "/test/diff/master..feature", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.PullRequestNewV1( + topic="pagure.pull-request.new", + body={ + "pullrequest": { + "id": 2, + "uid": ANY, + "title": "foo bar PR", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": "Test Initial Comment", + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/diff/master..feature", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -4156,6 +6362,9 @@ More information</textarea> shutil.rmtree(newpath) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_pull_request_add_comment(self, send_email): """ Test the pull_request_add_comment endpoint. """ @@ -4186,11 +6395,144 @@ More information</textarea> "csrf_token": csrf_token, "comment": "This look alright but we can do better", } - output = self.app.post( - "/test/pull-request/1/comment", - data=data, - follow_redirects=True, - ) + with testing.mock_sends( + pagure_messages.PullRequestCommentAddedV1( + topic="pagure.pull-request.comment.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "This look alright but we can do better", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": False, + "reactions": {}, + } + ], + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/pull-request/1/comment", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -4317,6 +6659,9 @@ More information</textarea> ) self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.notify.send_email") def test_pull_request_edit_comment(self, send_email): """ Test the pull request edit comment endpoint """ @@ -4350,6 +6695,7 @@ More information</textarea> "csrf_token": csrf_token, "comment": "This look alright but we can do better", } + output = self.app.post( "/test/pull-request/1/comment", data=data, @@ -4389,11 +6735,186 @@ More information</textarea> "csrf_token": csrf_token, "update_comment": "This look alright but we can do better than this.", } - output = self.app.post( - "/test/pull-request/1/comment/1/edit", - data=data, - follow_redirects=True, - ) + with testing.mock_sends( + pagure_messages.PullRequestCommentEditedV1( + topic="pagure.pull-request.comment.edited", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "PR from the feature branch", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "comment": { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "This look alright but we can do better than this.", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": ANY, + "editor": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "notification": False, + "reactions": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/pull-request/1/comment/1/edit", + data=data, + follow_redirects=True, + ) output_text = output.get_data(as_text=True) # Checking if the comment is updated in the main page self.assertIn( diff --git a/tests/test_pagure_flask_ui_groups.py b/tests/test_pagure_flask_ui_groups.py index d1b18a1..b7b078a 100644 --- a/tests/test_pagure_flask_ui_groups.py +++ b/tests/test_pagure_flask_ui_groups.py @@ -16,7 +16,9 @@ import sys import os import json -from mock import patch +import pagure_messages +from fedora_messaging import api, testing +from mock import ANY, patch sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -161,6 +163,9 @@ class PagureFlaskGroupstests(tests.Modeltests): output.get_data(as_text=True), ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_edit_group(self): """ Test the edit_group endpoint. """ @@ -244,7 +249,7 @@ class PagureFlaskGroupstests(tests.Modeltests): output.get_data(as_text=True), ) self.assertIn( - "You are not " "allowed to edit this group", + "You are not allowed to edit this group", output.get_data(as_text=True), ) self.assertIn( @@ -263,10 +268,33 @@ class PagureFlaskGroupstests(tests.Modeltests): "<p>Group not found</p>", output.get_data(as_text=True) ) - output = self.app.post( - "/group/test_group/edit", data=data, follow_redirects=True - ) - self.assertEqual(output.status_code, 200) + # All good + with testing.mock_sends( + pagure_messages.GroupEditV1( + topic="pagure.group.edit", + body={ + "group": { + "name": "test_group", + "display_name": "Test Group edited", + "description": "This is a group for the tests edited", + "group_type": "user", + "creator": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "date_created": ANY, + "members": ["pingou"], + }, + "fields": ["display_name", "description"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/group/test_group/edit", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) self.assertIn( "<title>Group test_group - Pagure", output.get_data(as_text=True), diff --git a/tests/test_pagure_flask_ui_issues.py b/tests/test_pagure_flask_ui_issues.py index 6aba6c6..671d487 100644 --- a/tests/test_pagure_flask_ui_issues.py +++ b/tests/test_pagure_flask_ui_issues.py @@ -21,15 +21,17 @@ try: import pyclamd except ImportError: pyclamd = None +import pagure_messages import six import tempfile import re from datetime import datetime, timedelta +from fedora_messaging import testing from six.moves.urllib.parse import urlparse, parse_qs import pygit2 from bs4 import BeautifulSoup -from mock import patch, MagicMock +from mock import ANY, patch, MagicMock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -1934,6 +1936,9 @@ class PagureFlaskIssuestests(tests.Modeltests): "

No issue tracker found for this project

", output_text ) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_update_issue_add_tags(self, p_send_email, p_ugt): @@ -1991,9 +1996,83 @@ class PagureFlaskIssuestests(tests.Modeltests): # Add two tags to the issue data = {"csrf_token": csrf_token, "tag": "red,green"} - output = self.app.post( - "/test/issue/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueTagAddedV1( + topic="pagure.issue.tag.added", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": ["green", "red"], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["green", "red"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2014,6 +2093,132 @@ class PagureFlaskIssuestests(tests.Modeltests): self.assertEqual([tag.tag for tag in tags], ["green", "red"]) self.assertEqual(repo.issues[0].tags_text, []) + # Drop one of the two tags + user = tests.FakeUser() + user.username = "pingou" + with tests.user_set(self.app.application, user): + + # Add two tags to the issue + data = {"csrf_token": csrf_token, "tag": "green"} + with testing.mock_sends( + pagure_messages.IssueTagRemovedV1( + topic="pagure.issue.tag.removed", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": ["green"], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [ + { + "id": 1, + "comment": "**Metadata Update from " + "@pingou**:\n- Issue tagged with: green, " + "red", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["red"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + "Issue #1: Test issue - test - Pagure", + output_text, + ) + self.assertIn( + '', + output_text, + ) + self.assertIn( + "
\n- Issue tagged with: green, red

", output_text + ) + self.assertIn( + "
\n- Issue untagged with: red

", + output_text, + ) + + # After update, list tags + tags = pagure.lib.query.get_tags_of_project(self.session, repo) + self.assertEqual([tag.tag for tag in tags], ["green", "red"]) + self.assertEqual(repo.issues[0].tags_text, []) + @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_update_issue(self, p_send_email, p_ugt): @@ -2347,6 +2552,9 @@ class PagureFlaskIssuestests(tests.Modeltests): output = self.app.post("/test/issue/1/update", data=data) self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_update_issue_drop_comment(self, p_send_email, p_ugt): @@ -2392,9 +2600,98 @@ class PagureFlaskIssuestests(tests.Modeltests): "csrf_token": csrf_token, "comment": "Woohoo a second comment!", } - output = self.app.post( - "/test/issue/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueCommentAddedV1( + topic="pagure.issue.comment.added", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [ + { + "id": 1, + "comment": "Woohoo a second comment!", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": False, + "reactions": {}, + } + ], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2461,6 +2758,9 @@ class PagureFlaskIssuestests(tests.Modeltests): issue = pagure.lib.query.search_issues(self.session, repo, issueid=1) self.assertEqual(len(issue.comments), 0) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_update_issue_depend(self, p_send_email, p_ugt): @@ -2514,9 +2814,83 @@ class PagureFlaskIssuestests(tests.Modeltests): # Add a dependent ticket data = {"csrf_token": csrf_token, "depending": "2"} - output = self.app.post( - "/test/issue/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueDependencyAddedV1( + topic="pagure.issue.dependency.added", + body={ + "issue": { + "id": 2, + "title": "Test issue #2", + "content": "We should work on this again", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": ["1"], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "added_dependency": 1, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2670,6 +3044,9 @@ class PagureFlaskIssuestests(tests.Modeltests): self.assertEqual(issue.depending_text, []) self.assertEqual(issue.blocking_text, [2]) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_update_issue_block(self, p_send_email, p_ugt): @@ -2682,15 +3059,88 @@ class PagureFlaskIssuestests(tests.Modeltests): # Create issues to play with repo = pagure.lib.query.get_authorized_project(self.session, "test") - msg = pagure.lib.query.new_issue( - session=self.session, - repo=repo, - title="Test issue", - content="We should work on this", - user="pingou", - ) - self.session.commit() - self.assertEqual(msg.title, "Test issue") + with testing.mock_sends( + pagure_messages.IssueNewV1( + topic="pagure.issue.new", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + msg = pagure.lib.query.new_issue( + session=self.session, + repo=repo, + title="Test issue", + content="We should work on this", + user="pingou", + ) + self.session.commit() + self.assertEqual(msg.title, "Test issue") repo = pagure.lib.query.get_authorized_project(self.session, "test") msg = pagure.lib.query.new_issue( @@ -2755,9 +3205,83 @@ class PagureFlaskIssuestests(tests.Modeltests): # Add a dependent ticket data = {"csrf_token": csrf_token, "blocking": "2"} - output = self.app.post( - "/test/issue/1/update", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueDependencyAddedV1( + topic="pagure.issue.dependency.added", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": ["2"], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "added_dependency": 2, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -2794,6 +3318,123 @@ class PagureFlaskIssuestests(tests.Modeltests): self.assertEqual(issue.depending_text, []) self.assertEqual(issue.blocking_text, [2]) + # Now remove the dependency and check everything is recorded + + user = tests.FakeUser() + user.username = "pingou" + with tests.user_set(self.app.application, user): + output = self.app.get("/test/issue/1") + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + "Issue #1: Test issue - test - Pagure", + output_text, + ) + self.assertIn( + '
', + output_text, + ) + + csrf_token = self.get_csrf(output=output) + + # Add a dependent ticket + data = {"csrf_token": csrf_token} + with testing.mock_sends( + pagure_messages.IssueDependencyRemovedV1( + topic="pagure.issue.dependency.removed", + body={ + "issue": { + "id": 2, + "title": "Test issue #2", + "content": "We should work on this again", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "removed_dependency": [1], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/update", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + "Issue #1: Test issue - test - Pagure", + output_text, + ) + self.assertIn( + '', + output_text, + ) + + self.session.commit() + repo = pagure.lib.query.get_authorized_project(self.session, "test") + issue = pagure.lib.query.search_issues(self.session, repo, issueid=1) + self.assertEqual(issue.depending_text, []) + self.assertEqual(issue.blocking_text, []) + @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_upload_issue(self, p_send_email, p_ugt): @@ -3092,6 +3733,9 @@ class PagureFlaskIssuestests(tests.Modeltests): output = self.app.get("/test" + url) self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_edit_issue(self, p_send_email, p_ugt): @@ -3168,9 +3812,83 @@ class PagureFlaskIssuestests(tests.Modeltests): self.assertEqual(output_text.count("Not a valid choice"), 0) data["csrf_token"] = csrf_token - output = self.app.post( - "/test/issue/1/edit", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueEditV1( + topic="pagure.issue.edit", + body={ + "issue": { + "id": 1, + "title": "Test issue #1", + "content": "We should work on this!", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "fields": ["content", "title"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/edit", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -3266,7 +3984,7 @@ class PagureFlaskIssuestests(tests.Modeltests): # disable issue tracker repo = pagure.lib.query.get_authorized_project(self.session, "test") - repo.settings = {"issue_tracker": False} + repo.settings = {"issue_tracker": False, "fedmsg_notifications": True} self.session.add(repo) self.session.commit() @@ -3325,6 +4043,9 @@ class PagureFlaskIssuestests(tests.Modeltests): tags = pagure.lib.query.get_tags_of_project(self.session, repo) self.assertEqual([tag.tag for tag in tags], ["tag1"]) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_edit_tag(self, p_send_email, p_ugt): @@ -3405,17 +4126,70 @@ class PagureFlaskIssuestests(tests.Modeltests): ) data["csrf_token"] = csrf_token - output = self.app.post( - "/test/tag/tag1/edit", data=data, follow_redirects=True - ) - self.assertEqual(output.status_code, 200) - output_text = output.get_data(as_text=True) - self.assertIn("Settings - test - Pagure", output_text) - self.assertIn( - "" - "Edited tag: tag1()[DeepSkyBlue] to tag2(lorem ipsum)[DeepSkyBlue]", - output_text, - ) + with testing.mock_sends( + pagure_messages.ProjectTagEditedV1( + topic="pagure.project.tag.edited", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "old_tag": "tag2", + "old_tag_description": "", + "old_tag_color": "DeepSkyBlue", + "new_tag": "tag2", + "new_tag_description": "lorem ipsum", + "new_tag_color": "DeepSkyBlue", + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/tag/tag1/edit", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn("Settings - test - Pagure", output_text) + self.assertIn( + "" + "Edited tag: tag1()[DeepSkyBlue] to tag2(lorem ipsum)[DeepSkyBlue]", + output_text, + ) # update tag with empty description data["tag_description"] = "" @@ -3436,6 +4210,9 @@ class PagureFlaskIssuestests(tests.Modeltests): tags = pagure.lib.query.get_tags_of_project(self.session, repo) self.assertEqual([tag.tag for tag in tags], ["tag2"]) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git", MagicMock(return_value=True)) @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) def test_remove_tag_issue_disabled(self): @@ -3477,9 +4254,57 @@ class PagureFlaskIssuestests(tests.Modeltests): user = tests.FakeUser(username="pingou") with tests.user_set(self.app.application, user): data = {"tag": "tag1", "csrf_token": self.get_csrf()} - output = self.app.post( - "/test/droptag/", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.ProjectTagRemovedV1( + topic="pagure.project.tag.removed", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "tags": ["tag1"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/droptag/", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -3584,6 +4409,9 @@ class PagureFlaskIssuestests(tests.Modeltests): ) self.assertIn("" "Tag: tag1 has been deleted", output_text) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.lib.git.update_git") @patch("pagure.lib.notify.send_email") def test_delete_issue(self, p_send_email, p_ugt): @@ -3644,9 +4472,82 @@ class PagureFlaskIssuestests(tests.Modeltests): ) data["csrf_token"] = csrf_token - output = self.app.post( - "/test/issue/1/drop", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.IssueDropV1( + topic="pagure.issue.drop", + body={ + "issue": { + "id": 1, + "title": "Test issue", + "content": "We should work on this", + "status": "Open", + "close_status": None, + "date_created": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "private": False, + "tags": [], + "depends": [], + "blocks": [], + "assignee": None, + "priority": None, + "milestone": None, + "custom_fields": [], + "closed_by": None, + "related_prs": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/issue/1/drop", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn("Issues - test - Pagure", output_text) diff --git a/tests/test_pagure_flask_ui_pr_edit.py b/tests/test_pagure_flask_ui_pr_edit.py index af6630b..fd44659 100644 --- a/tests/test_pagure_flask_ui_pr_edit.py +++ b/tests/test_pagure_flask_ui_pr_edit.py @@ -10,6 +10,10 @@ from __future__ import unicode_literals, absolute_import import sys import os +import pagure_messages +from fedora_messaging import api, testing +from mock import ANY, patch + sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") ) @@ -209,6 +213,9 @@ class PagureFlaskPrEdittests(tests.Modeltests): self.assertEqual(None, request.initial_comment) self.assertEqual(True, request.allow_rebase) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_pr_edit_pull_request_post_author(self): user = tests.FakeUser(username="foo") with tests.user_set(self.app.application, user): @@ -218,9 +225,196 @@ class PagureFlaskPrEdittests(tests.Modeltests): "allow_rebase": False, "csrf_token": self.get_csrf(), } - output = self.app.post( - "/test/pull-request/1/edit", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.PullRequestInitialCommentEditedV1( + topic="pagure.pull-request.initial_comment.edited", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "New title", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature", + "repo_from": { + "id": 4, + "name": "test", + "fullname": "forks/foo/test", + "url_path": "fork/foo/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "access_users": { + "owner": ["foo"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "foo", + "fullname": "foo bar", + "url_path": "user/foo", + }, + "assignee": None, + "status": "Open", + "commit_start": None, + "commit_stop": None, + "closed_by": None, + "initial_comment": "New initial comment", + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "agent": "foo", + }, + ) + ): + output = self.app.post( + "/test/pull-request/1/edit", + data=data, + follow_redirects=True, + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) # After successful edit, we end on pull_request view with new data diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index 109c7cf..1c76e6b 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -26,8 +26,10 @@ try: except ImportError: pass +import pagure_messages import pygit2 import six +from fedora_messaging import testing from mock import ANY, patch, MagicMock sys.path.insert( @@ -246,9 +248,11 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post("/test/adddeploykey") self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.decorators.admin_session_timedout") - @patch("pagure.lib.notify.log") - def test_add_user(self, mock_log, ast): + def test_add_user(self, ast): """ Test the add_user endpoint. """ ast.return_value = False @@ -338,9 +342,59 @@ class PagureFlaskRepotests(tests.Modeltests): # All correct data["user"] = "foo" - output = self.app.post( - "/test/adduser", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.ProjectUserAddedV1( + topic="pagure.project.user.added", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": ["foo"], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "new_user": "foo", + "access": "commit", + "branches": None, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/adduser", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -349,7 +403,69 @@ class PagureFlaskRepotests(tests.Modeltests): ) self.assertIn("User added", output_text) - mock_log.assert_called_with(ANY, topic="project.user.added", msg=ANY) + # Update access + data["access"] = "ticket" + data["user"] = "foo" + with testing.mock_sends( + pagure_messages.ProjectUserAccessUpdatedV1( + topic="pagure.project.user.access.updated", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": ["foo"], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "new_user": "foo", + "new_access": "ticket", + "new_branches": None, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/adduser", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + '
Project Settings
', + output_text, + ) + self.assertIn("User access updated", output_text) @patch("pagure.decorators.admin_session_timedout") def test_add_group_project_when_user_mngt_off(self, ast): @@ -439,6 +555,9 @@ class PagureFlaskRepotests(tests.Modeltests): ) self.assertIn("No group ralph found.", output_text) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.decorators.admin_session_timedout") def test_add_group_project(self, ast): """ Test the add_group_project endpoint. """ @@ -524,9 +643,59 @@ class PagureFlaskRepotests(tests.Modeltests): # All good data["access"] = "ticket" - output = self.app.post( - "/test/addgroup", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.ProjectGroupAddedV1( + topic="pagure.project.group.added", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": ["ralph"], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "new_group": "ralph", + "access": "ticket", + "branches": None, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/addgroup", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -538,6 +707,72 @@ class PagureFlaskRepotests(tests.Modeltests): ) self.assertIn("Group added", output_text) + # All good -- Update existing group/access + data["access"] = "commit" + with testing.mock_sends( + pagure_messages.ProjectGroupAccessUpdatedV1( + topic="pagure.project.group.access.updated", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": ["ralph"], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "new_group": "ralph", + "new_access": "commit", + "new_branches": None, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/addgroup", data=data, follow_redirects=True + ) + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn( + "Settings - test - Pagure", output_text + ) + self.assertIn( + '
Project Settings
', + output_text, + ) + self.assertIn("Group access updated", output_text) + @patch("pagure.decorators.admin_session_timedout") def test_remove_user_when_user_mngt_off(self, ast): """ Test the remove_user endpoint when user management is turned @@ -585,6 +820,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertEqual(output.status_code, 404) data = {"csrf_token": csrf_token} + output = self.app.post( "/test/dropuser/2", data=data, follow_redirects=True ) @@ -704,9 +940,11 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post("/test/dropdeploykey/1") self.assertEqual(output.status_code, 404) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.decorators.admin_session_timedout") - @patch("pagure.lib.notify.log") - def test_remove_user(self, mock_log, ast): + def test_remove_user(self, ast): """ Test the remove_user endpoint. """ ast.return_value = False @@ -790,9 +1028,58 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertEqual(len(repo.users), 1) data = {"csrf_token": csrf_token} - output = self.app.post( - "/test/dropuser/2", data=data, follow_redirects=True - ) + + with testing.mock_sends( + pagure_messages.ProjectUserRemovedV1( + topic="pagure.project.user.removed", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "removed_user": "foo", + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/dropuser/2", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -811,8 +1098,6 @@ class PagureFlaskRepotests(tests.Modeltests): ) self.assertEqual(len(repo.users), 0) - mock_log.assert_called_with(ANY, topic="project.user.removed", msg=ANY) - @patch("pagure.decorators.admin_session_timedout") @patch("pagure.lib.notify.log") def test_remove_user_self(self, mock_log, ast): @@ -931,6 +1216,9 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config["ENABLE_USER_MNGT"] = True + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.decorators.admin_session_timedout") def test_remove_group_project(self, ast): """ Test the remove_group_project endpoint. """ @@ -1035,9 +1323,57 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertEqual(len(repo.groups), 1) data = {"csrf_token": csrf_token} - output = self.app.post( - "/test/dropgroup/1", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.ProjectGroupRemovedV1( + topic="pagure.project.group.removed", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "removed_groups": ["testgrp"], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/dropgroup/1", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( @@ -1270,6 +1606,9 @@ class PagureFlaskRepotests(tests.Modeltests): ) self.assertIn("Project updated", output_text) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch("pagure.decorators.admin_session_timedout") def test_view_settings(self, ast): """ Test the view_settings endpoint. """ @@ -1329,6 +1668,7 @@ class PagureFlaskRepotests(tests.Modeltests): )[1].split('">')[0] data = {} + output = self.app.post( "/test/settings", data=data, follow_redirects=True ) @@ -1365,6 +1705,7 @@ class PagureFlaskRepotests(tests.Modeltests): ) data = {"csrf_token": csrf_token} + output = self.app.post( "/test/settings", data=data, follow_redirects=True ) @@ -1403,10 +1744,63 @@ class PagureFlaskRepotests(tests.Modeltests): "csrf_token": csrf_token, "pull_requests": "y", "issue_tracker": "y", + "fedmsg_notifications": "y", } - output = self.app.post( - "/test/settings", data=data, follow_redirects=True - ) + with testing.mock_sends( + pagure_messages.ProjectEditV1( + topic="pagure.project.edit", + body={ + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "fields": [ + "fedmsg_notifications", + "issue_tracker", + "pull_requests", + ], + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/test/settings", data=data, follow_redirects=True + ) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( diff --git a/tests/test_pagure_flask_ui_repo_delete_project.py b/tests/test_pagure_flask_ui_repo_delete_project.py index 0258335..adf8dd0 100644 --- a/tests/test_pagure_flask_ui_repo_delete_project.py +++ b/tests/test_pagure_flask_ui_repo_delete_project.py @@ -13,7 +13,9 @@ from __future__ import unicode_literals, absolute_import import sys import os -from mock import patch, MagicMock +import pagure_messages +from mock import ANY, patch, MagicMock +from fedora_messaging import testing sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -169,6 +171,9 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): projects = pagure.lib.query.search_projects(self.session) self.assertEqual(len(projects), 4) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) @patch.dict("pagure.config.config", {"ENABLE_DEL_PROJECTS": False}) @patch.dict("pagure.config.config", {"ENABLE_DEL_FORKS": True}) @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) @@ -191,10 +196,90 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): user = tests.FakeUser(username="pingou") with tests.user_set(self.app.application, user): - output = self.app.post( - "/fork/pingou/test/delete", follow_redirects=True - ) - self.assertEqual(output.status_code, 200) + with testing.mock_sends( + pagure_messages.ProjectDeletedV1( + topic="pagure.project.deleted", + body={ + "project": { + "id": 4, + "name": "test", + "fullname": "forks/pingou/test", + "url_path": "fork/pingou/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [], + "milestones": {}, + }, + "agent": "pingou", + }, + ) + ): + output = self.app.post( + "/fork/pingou/test/delete", follow_redirects=True + ) + self.assertEqual(output.status_code, 200) projects = pagure.lib.query.search_projects(self.session) self.assertEqual(len(projects), 3) diff --git a/tests/test_pagure_lib_git_diff_pr.py b/tests/test_pagure_lib_git_diff_pr.py index 612ecdf..d155674 100644 --- a/tests/test_pagure_lib_git_diff_pr.py +++ b/tests/test_pagure_lib_git_diff_pr.py @@ -19,7 +19,9 @@ import time # noqa import os # noqa import pygit2 # noqa -from mock import patch, MagicMock # noqa +import pagure_messages +from fedora_messaging import api, testing +from mock import ANY, patch, MagicMock sys.path.insert( 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") @@ -320,6 +322,9 @@ class PagureFlaskForkPrtests(tests.Modeltests): commit = pr_ref.peel() self.assertEqual(commit.oid.hex, diff_commits[0].oid.hex) + @patch.dict( + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + ) def test_diff_pull_request_updated(self): """ Test that calling pagure.lib.git.diff_pull_request on an updated PR updates the PR reference @@ -391,14 +396,336 @@ class PagureFlaskForkPrtests(tests.Modeltests): # Get the new diff for that PR and check its new ref - diff_commits, diff = pagure.lib.git.diff_pull_request( - self.session, - request=request, - repo_obj=PagureRepo(gitrepo2), - orig_repo=PagureRepo(gitrepo), - with_diff=True, - ) - self.assertEqual(len(diff_commits), 3) + with testing.mock_sends( + pagure_messages.PullRequestUpdatedV1( + topic="pagure.pull-request.updated", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "test pull-request", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature_foo", + "repo_from": { + "id": 2, + "name": "test", + "fullname": "forks/pingou/test", + "url_path": "fork/pingou/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [], + }, + "agent": "pagure", + }, + ), + pagure_messages.PullRequestCommentAddedV1( + topic="pagure.pull-request.comment.added", + body={ + "pullrequest": { + "id": 1, + "uid": ANY, + "title": "test pull-request", + "branch": "master", + "project": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "branch_from": "feature_foo", + "repo_from": { + "id": 2, + "name": "test", + "fullname": "forks/pingou/test", + "url_path": "fork/pingou/test", + "description": "test project #1", + "namespace": None, + "parent": { + "id": 1, + "name": "test", + "fullname": "test", + "url_path": "test", + "description": "test project #1", + "namespace": None, + "parent": None, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "date_created": ANY, + "date_modified": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "access_users": { + "owner": ["pingou"], + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "access_groups": { + "admin": [], + "commit": [], + "collaborator": [], + "ticket": [], + }, + "tags": [], + "priorities": {}, + "custom_keys": [], + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate", + ], + "milestones": {}, + }, + "remote_git": None, + "date_created": ANY, + "updated_on": ANY, + "last_updated": ANY, + "closed_at": None, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "assignee": None, + "status": "Open", + "commit_start": ANY, + "commit_stop": ANY, + "closed_by": None, + "initial_comment": None, + "cached_merge_status": "unknown", + "threshold_reached": None, + "tags": [], + "comments": [ + { + "id": 1, + "commit": None, + "tree": None, + "filename": None, + "line": None, + "comment": "**1 new commit added**\n\n " + "* ``Third edit on side branch of the file " + "sources for testing``\n", + "parent": None, + "date_created": ANY, + "user": { + "name": "pingou", + "fullname": "PY C", + "url_path": "user/pingou", + }, + "edited_on": None, + "editor": None, + "notification": True, + "reactions": {}, + } + ], + }, + "agent": "pingou", + }, + ), + ): + diff_commits, diff = pagure.lib.git.diff_pull_request( + self.session, + request=request, + repo_obj=PagureRepo(gitrepo2), + orig_repo=PagureRepo(gitrepo), + with_diff=True, + ) + self.assertEqual(len(diff_commits), 3) # Check that the PR has its PR refs # we don't know the task id but we'll give it 30 sec to finish From d2dc8d09f577d4178fa536e210f2e566fb525aed Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 7/11] Install pagure-messages via pip for now but fedora-messaging as RPM Signed-off-by: Pierre-Yves Chibon --- diff --git a/dev/containers/centos7-rpms-py2 b/dev/containers/centos7-rpms-py2 index 1880954..a1e7858 100644 --- a/dev/containers/centos7-rpms-py2 +++ b/dev/containers/centos7-rpms-py2 @@ -23,6 +23,8 @@ RUN yum -y install \ python-flask \ python-flake8 \ python2-pytest-xdist \ + python2-fedora-messaging \ + python2-pip \ redis \ which \ git @@ -30,6 +32,10 @@ RUN yum -y install \ # repoSpanner \ # repoSpanner-bridge +RUN pip install pip --upgrade +RUN pip install setuptools --upgrade +RUN pip install pagure-messages + RUN cd / \ && GIT_TRACE=1 GIT_CURL_VERBOSE=1 git clone -b $BRANCH $REPO \ && chmod +x /pagure/dev/containers/runtests_py2.sh diff --git a/dev/containers/fedora-rpms-py3 b/dev/containers/fedora-rpms-py3 index 56f3634..78e3d52 100644 --- a/dev/containers/fedora-rpms-py3 +++ b/dev/containers/fedora-rpms-py3 @@ -15,10 +15,14 @@ RUN dnf -y --enablerepo=updates-testing install \ python3-flake8 \ python3-pytest-xdist \ python3-cchardet \ + python3-fedora-messaging \ + python3-pip \ redis \ which \ git +RUN pip install pagure-messages + RUN cd / \ && GIT_TRACE=1 GIT_CURL_VERBOSE=1 git clone -b $BRANCH $REPO \ && chmod +x /pagure/dev/containers/runtests_py3.sh From 5ea387471f97d7ccecd296fdf4838d84149df4d1 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 8/11] Add a NOGITHOOKS configuration key This configuration key allows to entirely skip the git hooks. This is useful for the test suite as it allows to block some action from happening upon git push, which is done in a separate process. The action can then be triggered in the main process where they can be checked and thus tested. Signed-off-by: Pierre-Yves Chibon --- diff --git a/doc/configuration.rst b/doc/configuration.rst index 133a8be..bc98ae6 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -2199,6 +2199,21 @@ Defaults to: ``False``. +NOGITHOOKS +~~~~~~~~~~ + +This configuration key should not be touched. It is used in the test suite as a +way to prevent all the git hooks from running (which includes checking if the +user is allowed to push). Using this mechanism we are able to check some +behavior in the test suite that in a deployed pagure instance are happening in +a different process. + +**Do not change this option in production** + +Defaults to: ``None``. + + + Deprecated configuration keys ----------------------------- diff --git a/pagure/hooks/__init__.py b/pagure/hooks/__init__.py index a848afa..6de55b9 100644 --- a/pagure/hooks/__init__.py +++ b/pagure/hooks/__init__.py @@ -497,6 +497,9 @@ def run_hook_file(hooktype): hooktype (string): The name of the hook to run: pre-receive, update or post-receive """ + if pagure_config.get("NOGITHOOKS") or False: + return + if hooktype not in ("pre-receive", "update", "post-receive"): raise ValueError("Hook type %s not valid" % hooktype) changes = extract_changes(from_stdin=hooktype != "update") diff --git a/tests/__init__.py b/tests/__init__.py index b6253a5..d55ec60 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -134,6 +134,8 @@ LOGGING = { # that applies to all log messages not handled by a different logger "root": {"level": "WARN", "handlers": ["console"]}, } + +NOGITHOOKS = %(nogithooks)s """ # The Celery docs warn against using task_always_eager: # http://docs.celeryproject.org/en/latest/userguide/testing.html @@ -396,6 +398,7 @@ class SimplePagureTest(unittest.TestCase): "repospanner_admin_override": "False", "repospanner_new_fork": "True", "repospanner_admin_migration": "False", + "nogithooks": False, } config_values.update(self.config_values) self.config_values = config_values From 86eedfd19927c075e27ecd054002062372df5612 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 9/11] When checking if messages were sent via a rebase, do not run the git hooks Otherwise, the PR is updated in a separate process that is inaccessible from pytest. That process is then the one sending the fedora-messaging notifications and suddenly when we check the UI, none of the expected notifications were sent. So instead, we entirely skip the git hooks. The PR gets updated when the rebase finishes, in the process run by pytest and we are able to check the notifications sent. Signed-off-by: Pierre-Yves Chibon --- diff --git a/tests/test_pagure_flask_rebase.py b/tests/test_pagure_flask_rebase.py index 5e645d0..d9cec2d 100644 --- a/tests/test_pagure_flask_rebase.py +++ b/tests/test_pagure_flask_rebase.py @@ -30,15 +30,16 @@ import pagure.lib.tasks import tests -class PagureRebasetests(tests.Modeltests): +class PagureRebaseBasetests(tests.Modeltests): """ Tests rebasing pull-request in pagure """ maxDiff = None + config_values = {"authbackend": "pagure"} @patch("pagure.lib.notify.send_email", MagicMock(return_value=True)) def setUp(self): """ Set up the environnment, ran before every tests. """ - super(PagureRebasetests, self).setUp() + super(PagureRebaseBasetests, self).setUp() pagure.config.config["REQUESTS_FOLDER"] = None tests.create_projects(self.session) @@ -101,6 +102,10 @@ class PagureRebasetests(tests.Modeltests): self.assertEqual(len(project.requests), 1) self.request = self.project.requests[0] + +class PagureRebasetests(PagureRebaseBasetests): + """ Tests rebasing pull-request in pagure """ + def test_merge_status_merge(self): """ Test that the PR can be merged with a merge commit. """ @@ -183,8 +188,260 @@ class PagureRebasetests(tests.Modeltests): }, ) + def test_rebase_api_ui_logged_in_different_user(self): + """ Test the rebase PR API endpoint when logged in from the UI and + its outcome. """ + # Add 'bar' to the project 'test' so 'bar' can rebase the PR + item = pagure.lib.model.User( + user="bar", + fullname="bar foo", + password=b"foo", + default_email="bar@foo.com", + ) + self.session.add(item) + item = pagure.lib.model.UserEmail(user_id=2, email="bar@foo.com") + self.session.add(item) + self.session.commit() + repo = pagure.lib.query._get_project(self.session, "test") + msg = pagure.lib.query.add_user_to_project( + session=self.session, project=repo, new_user="bar", user="pingou" + ) + self.session.commit() + self.assertEqual(msg, "User added") + + user = tests.FakeUser(username="bar") + with tests.user_set(self.app.application, user): + # Get the merge status first so it's cached and can be refreshed + csrf_token = self.get_csrf() + data = {"requestid": self.request.uid, "csrf_token": csrf_token} + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "MERGE", + "message": "The pull-request can be merged with " + "a merge commit", + "short_code": "With merge", + }, + ) + + output = self.app.post("/api/0/test/pull-request/1/rebase") + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual(data, {"message": "Pull-request rebased"}) + + data = {"requestid": self.request.uid, "csrf_token": csrf_token} + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "FFORWARD", + "message": "The pull-request can be merged and " + "fast-forwarded", + "short_code": "Ok", + }, + ) + + output = self.app.get("/test/pull-request/1") + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn("rebased onto", output_text) + repo = pagure.lib.query._get_project(self.session, "test") + self.assertEqual(repo.requests[0].comments[0].user.username, "bar") + + def test_rebase_api_ui_logged_in_pull_request_author(self): + """ Test the rebase PR API endpoint when logged in from the UI and + its outcome. """ + + user = tests.FakeUser(username="foo") + with tests.user_set(self.app.application, user): + # Get the merge status first so it's cached and can be refreshed + csrf_token = self.get_csrf() + data = {"requestid": self.request.uid, "csrf_token": csrf_token} + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "MERGE", + "message": "The pull-request can be merged with " + "a merge commit", + "short_code": "With merge", + }, + ) + + output = self.app.post("/api/0/test/pull-request/1/rebase") + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual(data, {"message": "Pull-request rebased"}) + + data = {"requestid": self.request.uid, "csrf_token": csrf_token} + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "FFORWARD", + "message": "The pull-request can be merged and " + "fast-forwarded", + "short_code": "Ok", + }, + ) + + output = self.app.get("/test/pull-request/1") + self.assertEqual(output.status_code, 200) + output_text = output.get_data(as_text=True) + self.assertIn("rebased onto", output_text) + repo = pagure.lib.query._get_project(self.session, "test") + self.assertEqual(repo.requests[0].comments[0].user.username, "foo") + + def test_rebase_api_api_logged_in(self): + """ Test the rebase PR API endpoint when using an API token and + its outcome. """ + + tests.create_tokens(self.session) + tests.create_tokens_acl(self.session) + + headers = {"Authorization": "token aaabbbcccddd"} + + output = self.app.post( + "/api/0/test/pull-request/1/rebase", headers=headers + ) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual(data, {"message": "Pull-request rebased"}) + + user = tests.FakeUser(username="pingou") + with tests.user_set(self.app.application, user): + + data = { + "requestid": self.request.uid, + "csrf_token": self.get_csrf(), + } + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "FFORWARD", + "message": "The pull-request can be merged and " + "fast-forwarded", + "short_code": "Ok", + }, + ) + + def test_rebase_api_conflicts(self): + """ Test the rebase PR API endpoint when logged in from the UI and + its outcome. """ + tests.add_content_to_git( + os.path.join(self.path, "repos", "test.git"), + branch="master", + content="foobar baz", + ) + + user = tests.FakeUser(username="pingou") + with tests.user_set(self.app.application, user): + output = self.app.post("/api/0/test/pull-request/1/rebase") + self.assertEqual(output.status_code, 400) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "error": "Did not manage to rebase this pull-request", + "error_code": "ENOCODE", + }, + ) + + data = { + "requestid": self.request.uid, + "csrf_token": self.get_csrf(), + } + output = self.app.post("/pv/pull-request/merge", data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "code": "CONFLICTS", + "message": "The pull-request cannot be merged due " + "to conflicts", + "short_code": "Conflicts", + }, + ) + + def test_rebase_api_api_logged_in_unknown_project(self): + """ Test the rebase PR API endpoint when the project doesn't exist """ + + tests.create_tokens(self.session) + tests.create_tokens_acl(self.session) + + headers = {"Authorization": "token aaabbbcccddd"} + + output = self.app.post( + "/api/0/unknown/pull-request/1/rebase", headers=headers + ) + self.assertEqual(output.status_code, 404) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, {"error": "Project not found", "error_code": "ENOPROJECT"} + ) + + def test_rebase_api_api_logged_in_unknown_pr(self): + """ Test the rebase PR API endpoint when the PR doesn't exist """ + + tests.create_tokens(self.session) + tests.create_tokens_acl(self.session) + + headers = {"Authorization": "token aaabbbcccddd"} + + output = self.app.post( + "/api/0/test/pull-request/404/rebase", headers=headers + ) + self.assertEqual(output.status_code, 404) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, {"error": "Pull-Request not found", "error_code": "ENOREQ"} + ) + + def test_rebase_api_api_logged_in_unknown_token(self): + """ Test the rebase PR API endpoint with an invalid API token """ + + tests.create_tokens(self.session) + tests.create_tokens_acl(self.session) + + headers = {"Authorization": "token unknown"} + + output = self.app.post( + "/api/0/test/pull-request/1/rebase", headers=headers + ) + self.assertEqual(output.status_code, 401) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual( + data, + { + "error": "Invalid or expired token. Please visit " + "http://localhost.localdomain/settings#nav-api-tab to get " + "or renew your API token.", + "error_code": "EINVALIDTOK", + "errors": "Invalid token", + }, + ) + + +class PagureRebaseNoHooktests(PagureRebaseBasetests): + """ Tests rebasing pull-request in pagure """ + + config_values = {"authbackend": "pagure", "nogithooks": True} + @patch.dict( - "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True} + "pagure.config.config", {"FEDORA_MESSAGING_NOTIFICATIONS": True,} ) def test_rebase_api_ui_logged_in(self): """ Test the rebase PR API endpoint when logged in from the UI and @@ -547,253 +804,6 @@ class PagureRebasetests(tests.Modeltests): repo.requests[0].comments[0].user.username, "pingou" ) - def test_rebase_api_ui_logged_in_different_user(self): - """ Test the rebase PR API endpoint when logged in from the UI and - its outcome. """ - # Add 'bar' to the project 'test' so 'bar' can rebase the PR - item = pagure.lib.model.User( - user="bar", - fullname="bar foo", - password=b"foo", - default_email="bar@foo.com", - ) - self.session.add(item) - item = pagure.lib.model.UserEmail(user_id=2, email="bar@foo.com") - self.session.add(item) - - self.session.commit() - repo = pagure.lib.query._get_project(self.session, "test") - msg = pagure.lib.query.add_user_to_project( - session=self.session, project=repo, new_user="bar", user="pingou" - ) - self.session.commit() - self.assertEqual(msg, "User added") - - user = tests.FakeUser(username="bar") - with tests.user_set(self.app.application, user): - # Get the merge status first so it's cached and can be refreshed - csrf_token = self.get_csrf() - data = {"requestid": self.request.uid, "csrf_token": csrf_token} - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "MERGE", - "message": "The pull-request can be merged with " - "a merge commit", - "short_code": "With merge", - }, - ) - - output = self.app.post("/api/0/test/pull-request/1/rebase") - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual(data, {"message": "Pull-request rebased"}) - - data = {"requestid": self.request.uid, "csrf_token": csrf_token} - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "FFORWARD", - "message": "The pull-request can be merged and " - "fast-forwarded", - "short_code": "Ok", - }, - ) - - output = self.app.get("/test/pull-request/1") - self.assertEqual(output.status_code, 200) - output_text = output.get_data(as_text=True) - self.assertIn("rebased onto", output_text) - repo = pagure.lib.query._get_project(self.session, "test") - self.assertEqual(repo.requests[0].comments[0].user.username, "bar") - - def test_rebase_api_ui_logged_in_pull_request_author(self): - """ Test the rebase PR API endpoint when logged in from the UI and - its outcome. """ - - user = tests.FakeUser(username="foo") - with tests.user_set(self.app.application, user): - # Get the merge status first so it's cached and can be refreshed - csrf_token = self.get_csrf() - data = {"requestid": self.request.uid, "csrf_token": csrf_token} - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "MERGE", - "message": "The pull-request can be merged with " - "a merge commit", - "short_code": "With merge", - }, - ) - - output = self.app.post("/api/0/test/pull-request/1/rebase") - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual(data, {"message": "Pull-request rebased"}) - - data = {"requestid": self.request.uid, "csrf_token": csrf_token} - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "FFORWARD", - "message": "The pull-request can be merged and " - "fast-forwarded", - "short_code": "Ok", - }, - ) - - output = self.app.get("/test/pull-request/1") - self.assertEqual(output.status_code, 200) - output_text = output.get_data(as_text=True) - self.assertIn("rebased onto", output_text) - repo = pagure.lib.query._get_project(self.session, "test") - self.assertEqual(repo.requests[0].comments[0].user.username, "foo") - - def test_rebase_api_api_logged_in(self): - """ Test the rebase PR API endpoint when using an API token and - its outcome. """ - - tests.create_tokens(self.session) - tests.create_tokens_acl(self.session) - - headers = {"Authorization": "token aaabbbcccddd"} - - output = self.app.post( - "/api/0/test/pull-request/1/rebase", headers=headers - ) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual(data, {"message": "Pull-request rebased"}) - - user = tests.FakeUser(username="pingou") - with tests.user_set(self.app.application, user): - - data = { - "requestid": self.request.uid, - "csrf_token": self.get_csrf(), - } - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "FFORWARD", - "message": "The pull-request can be merged and " - "fast-forwarded", - "short_code": "Ok", - }, - ) - - def test_rebase_api_conflicts(self): - """ Test the rebase PR API endpoint when logged in from the UI and - its outcome. """ - tests.add_content_to_git( - os.path.join(self.path, "repos", "test.git"), - branch="master", - content="foobar baz", - ) - - user = tests.FakeUser(username="pingou") - with tests.user_set(self.app.application, user): - output = self.app.post("/api/0/test/pull-request/1/rebase") - self.assertEqual(output.status_code, 400) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "error": "Did not manage to rebase this pull-request", - "error_code": "ENOCODE", - }, - ) - - data = { - "requestid": self.request.uid, - "csrf_token": self.get_csrf(), - } - output = self.app.post("/pv/pull-request/merge", data=data) - self.assertEqual(output.status_code, 200) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "code": "CONFLICTS", - "message": "The pull-request cannot be merged due " - "to conflicts", - "short_code": "Conflicts", - }, - ) - - def test_rebase_api_api_logged_in_unknown_project(self): - """ Test the rebase PR API endpoint when the project doesn't exist """ - - tests.create_tokens(self.session) - tests.create_tokens_acl(self.session) - - headers = {"Authorization": "token aaabbbcccddd"} - - output = self.app.post( - "/api/0/unknown/pull-request/1/rebase", headers=headers - ) - self.assertEqual(output.status_code, 404) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, {"error": "Project not found", "error_code": "ENOPROJECT"} - ) - - def test_rebase_api_api_logged_in_unknown_pr(self): - """ Test the rebase PR API endpoint when the PR doesn't exist """ - - tests.create_tokens(self.session) - tests.create_tokens_acl(self.session) - - headers = {"Authorization": "token aaabbbcccddd"} - - output = self.app.post( - "/api/0/test/pull-request/404/rebase", headers=headers - ) - self.assertEqual(output.status_code, 404) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, {"error": "Pull-Request not found", "error_code": "ENOREQ"} - ) - - def test_rebase_api_api_logged_in_unknown_token(self): - """ Test the rebase PR API endpoint with an invalid API token """ - - tests.create_tokens(self.session) - tests.create_tokens_acl(self.session) - - headers = {"Authorization": "token unknown"} - - output = self.app.post( - "/api/0/test/pull-request/1/rebase", headers=headers - ) - self.assertEqual(output.status_code, 401) - data = json.loads(output.get_data(as_text=True)) - self.assertEqual( - data, - { - "error": "Invalid or expired token. Please visit " - "http://localhost.localdomain/settings#nav-api-tab to get " - "or renew your API token.", - "error_code": "EINVALIDTOK", - "errors": "Invalid token", - }, - ) - class PagureRebaseNotAllowedtests(tests.Modeltests): """ Tests rebasing pull-request in pagure """ From 520a161ae2aa85b0662a3327bd46d3ddfe523ba5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 10/11] Fix the topic of the notification sent Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/query.py b/pagure/lib/query.py index 132223d..7b01aab 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -1550,6 +1550,8 @@ def add_pull_request_flag( token=token, ) + action = action.replace("Flag ", "") + pr_flag = pagure.lib.query.get_commit_flag_by_uid( session, request.commit_stop, flag_uid ) @@ -1569,8 +1571,6 @@ def add_pull_request_flag( ), ) - action = action.replace("Flag ", "") - return ("Flag %s" % action, pr_flag.uid) From f0f56d214a9ede0b7be5e8cebbc349df571f0abb Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Dec 04 2020 11:07:22 +0000 Subject: [PATCH 11/11] Fix the test now that when we flag PR we're actually doing commit and PR flags Signed-off-by: Pierre-Yves Chibon --- diff --git a/tests/test_pagure_flask_api_pr_flag.py b/tests/test_pagure_flask_api_pr_flag.py index d162c3a..ae722dd 100644 --- a/tests/test_pagure_flask_api_pr_flag.py +++ b/tests/test_pagure_flask_api_pr_flag.py @@ -246,6 +246,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): # Valid request with testing.mock_sends( + pagure_messages.CommitFlagAddedV1, pagure_messages.PullRequestFlagAddedV1( topic="pagure.pull-request.flag.added", body={ @@ -346,7 +347,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): "assignee": None, "status": "Open", "commit_start": None, - "commit_stop": None, + "commit_stop": "hash_commit_stop", "closed_by": None, "initial_comment": None, "cached_merge_status": "unknown", @@ -355,7 +356,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): "comments": [], }, "flag": { - "pull_request_uid": ANY, + "commit_hash": "hash_commit_stop", "username": "Jenkins", "percent": None, "comment": "Tests running", @@ -371,7 +372,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): }, "agent": "pingou", }, - ) + ), ): output = self.app.post( "/api/0/test/pull-request/1/flag", data=data, headers=headers @@ -511,6 +512,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): } with testing.mock_sends( + pagure_messages.CommitFlagUpdatedV1, pagure_messages.PullRequestFlagUpdatedV1( topic="pagure.pull-request.flag.updated", body={ @@ -611,7 +613,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): "assignee": None, "status": "Open", "commit_start": None, - "commit_stop": None, + "commit_stop": "hash_commit_stop", "closed_by": None, "initial_comment": None, "cached_merge_status": "unknown", @@ -620,9 +622,9 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): "comments": [], }, "flag": { - "pull_request_uid": ANY, + "commit_hash": "hash_commit_stop", "username": "Jenkins", - "percent": "100", + "percent": 100, "comment": "Tests passed", "status": "success", "url": "http://jenkins.cloud.fedoraproject.org/", @@ -636,7 +638,7 @@ class PagureFlaskApiPRFlagtests(tests.Modeltests): }, "agent": "pingou", }, - ) + ), ): output = self.app.post( "/api/0/test/pull-request/1/flag", data=data, headers=headers