Merge ~pappacena/launchpad:vcs-scenarios-for-bmp into launchpad:master
- Git
- lp:~pappacena/launchpad
- vcs-scenarios-for-bmp
- Merge into master
Proposed by
Thiago F. Pappacena
Status: | Superseded |
---|---|
Proposed branch: | ~pappacena/launchpad:vcs-scenarios-for-bmp |
Merge into: | launchpad:master |
Diff against target: |
671 lines (+164/-136) 3 files modified
lib/lp/code/model/branchmergeproposal.py (+5/-7) lib/lp/code/model/tests/test_branchmergeproposal.py (+146/-125) lib/lp/code/tests/helpers.py (+13/-4) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+387877@code.launchpad.net |
Commit message
Refactoring BMP test cases to extend scenarios on TestBranchMerge
Description of the change
To post a comment you must log in.
Unmerged commits
- 04850f4... by Thiago F. Pappacena
-
Refactoring BMP to extend scenarios to TestBranchMerge
ProposalNominat eReviewer - 7b57c36... by Thiago F. Pappacena
-
Refactoring test code nad removing unused attribute from GitRef
- 5577f7b... by Thiago F. Pappacena
-
LP: #1888396 Fixing webhook trigger for private git repositories
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/code/model/branchmergeproposal.py b/lib/lp/code/model/branchmergeproposal.py | |||
2 | index 5ebcf04..338cc29 100644 | |||
3 | --- a/lib/lp/code/model/branchmergeproposal.py | |||
4 | +++ b/lib/lp/code/model/branchmergeproposal.py | |||
5 | @@ -1,4 +1,4 @@ | |||
7 | 1 | # Copyright 2009-2018 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
8 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
9 | 3 | 3 | ||
10 | 4 | """Database class for branch merge proposals.""" | 4 | """Database class for branch merge proposals.""" |
11 | @@ -70,6 +70,7 @@ from lp.code.event.branchmergeproposal import ( | |||
12 | 70 | BranchMergeProposalNeedsReviewEvent, | 70 | BranchMergeProposalNeedsReviewEvent, |
13 | 71 | ReviewerNominatedEvent, | 71 | ReviewerNominatedEvent, |
14 | 72 | ) | 72 | ) |
15 | 73 | from lp.code.interfaces.branch import IBranch | ||
16 | 73 | from lp.code.interfaces.branchcollection import IAllBranches | 74 | from lp.code.interfaces.branchcollection import IAllBranches |
17 | 74 | from lp.code.interfaces.branchmergeproposal import ( | 75 | from lp.code.interfaces.branchmergeproposal import ( |
18 | 75 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, | 76 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
19 | @@ -881,7 +882,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin): | |||
20 | 881 | BranchSubscriptionDiffSize.NODIFF, | 882 | BranchSubscriptionDiffSize.NODIFF, |
21 | 882 | CodeReviewNotificationLevel.FULL, | 883 | CodeReviewNotificationLevel.FULL, |
22 | 883 | user) | 884 | user) |
24 | 884 | if branch.stacked_on is not None: | 885 | if IBranch.providedBy(branch) and branch.stacked_on is not None: |
25 | 885 | checked_branches.append(branch) | 886 | checked_branches.append(branch) |
26 | 886 | if branch.stacked_on not in checked_branches: | 887 | if branch.stacked_on not in checked_branches: |
27 | 887 | self._subscribeUserToStackedBranch( | 888 | self._subscribeUserToStackedBranch( |
28 | @@ -903,14 +904,11 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin): | |||
29 | 903 | the reviewer if the branch is private and the reviewer is an open | 904 | the reviewer if the branch is private and the reviewer is an open |
30 | 904 | team. | 905 | team. |
31 | 905 | """ | 906 | """ |
36 | 906 | if self.source_branch is None: | 907 | source = self.merge_source |
33 | 907 | # This only applies to Bazaar, which has stacked branches. | ||
34 | 908 | return | ||
35 | 909 | source = self.source_branch | ||
37 | 910 | if (not source.visibleByUser(reviewer) and | 908 | if (not source.visibleByUser(reviewer) and |
38 | 911 | self._acceptable_to_give_visibility(source, reviewer)): | 909 | self._acceptable_to_give_visibility(source, reviewer)): |
39 | 912 | self._subscribeUserToStackedBranch(source, reviewer) | 910 | self._subscribeUserToStackedBranch(source, reviewer) |
41 | 913 | target = self.target_branch | 911 | target = self.merge_target |
42 | 914 | if (not target.visibleByUser(reviewer) and | 912 | if (not target.visibleByUser(reviewer) and |
43 | 915 | self._acceptable_to_give_visibility(source, reviewer)): | 913 | self._acceptable_to_give_visibility(source, reviewer)): |
44 | 916 | self._subscribeUserToStackedBranch(target, reviewer) | 914 | self._subscribeUserToStackedBranch(target, reviewer) |
45 | diff --git a/lib/lp/code/model/tests/test_branchmergeproposal.py b/lib/lp/code/model/tests/test_branchmergeproposal.py | |||
46 | index 8936574..0d2457d 100644 | |||
47 | --- a/lib/lp/code/model/tests/test_branchmergeproposal.py | |||
48 | +++ b/lib/lp/code/model/tests/test_branchmergeproposal.py | |||
49 | @@ -1,4 +1,4 @@ | |||
51 | 1 | # Copyright 2009-2019 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
52 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
53 | 3 | 3 | ||
54 | 4 | """Tests for BranchMergeProposals.""" | 4 | """Tests for BranchMergeProposals.""" |
55 | @@ -57,6 +57,7 @@ from lp.code.event.branchmergeproposal import ( | |||
56 | 57 | BranchMergeProposalNeedsReviewEvent, | 57 | BranchMergeProposalNeedsReviewEvent, |
57 | 58 | ReviewerNominatedEvent, | 58 | ReviewerNominatedEvent, |
58 | 59 | ) | 59 | ) |
59 | 60 | from lp.code.interfaces.branch import IBranch | ||
60 | 60 | from lp.code.interfaces.branchmergeproposal import ( | 61 | from lp.code.interfaces.branchmergeproposal import ( |
61 | 61 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, | 62 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
62 | 62 | BRANCH_MERGE_PROPOSAL_OBSOLETE_STATES as OBSOLETE_STATES, | 63 | BRANCH_MERGE_PROPOSAL_OBSOLETE_STATES as OBSOLETE_STATES, |
63 | @@ -91,6 +92,7 @@ from lp.services.webapp import canonical_url | |||
64 | 91 | from lp.services.webhooks.testing import LogsScheduledWebhooks | 92 | from lp.services.webhooks.testing import LogsScheduledWebhooks |
65 | 92 | from lp.services.xref.interfaces import IXRefSet | 93 | from lp.services.xref.interfaces import IXRefSet |
66 | 93 | from lp.testing import ( | 94 | from lp.testing import ( |
67 | 95 | admin_logged_in, | ||
68 | 94 | ExpectedException, | 96 | ExpectedException, |
69 | 95 | launchpadlib_for, | 97 | launchpadlib_for, |
70 | 96 | login, | 98 | login, |
71 | @@ -109,6 +111,49 @@ from lp.testing.layers import ( | |||
72 | 109 | ) | 111 | ) |
73 | 110 | 112 | ||
74 | 111 | 113 | ||
75 | 114 | class WithVCSScenarios(WithScenarios): | ||
76 | 115 | |||
77 | 116 | scenarios = [ | ||
78 | 117 | ("bzr", {"git": False}), | ||
79 | 118 | ("git", {"git": True}), | ||
80 | 119 | ] | ||
81 | 120 | |||
82 | 121 | def makeBranch(self, same_target_as=None, product=None, stacked_on=None, | ||
83 | 122 | information_type=None, owner=None): | ||
84 | 123 | # Create the product pillar and its access policy if information | ||
85 | 124 | # type is "PROPRIETARY". | ||
86 | 125 | if product is None and same_target_as is None: | ||
87 | 126 | product = self.factory.makeProduct() | ||
88 | 127 | if information_type == InformationType.PROPRIETARY: | ||
89 | 128 | self.factory.makeAccessPolicy(product) | ||
90 | 129 | elif product is None: | ||
91 | 130 | same_target_as = removeSecurityProxy(same_target_as) | ||
92 | 131 | product = (same_target_as.target if self.git else | ||
93 | 132 | same_target_as.product) | ||
94 | 133 | |||
95 | 134 | kwargs = { | ||
96 | 135 | "information_type": information_type, | ||
97 | 136 | "owner": owner} | ||
98 | 137 | if self.git: | ||
99 | 138 | kwargs["target"] = product | ||
100 | 139 | return self.factory.makeGitRefs(**kwargs)[0] | ||
101 | 140 | else: | ||
102 | 141 | kwargs["product"] = product | ||
103 | 142 | kwargs["stacked_on"] = stacked_on | ||
104 | 143 | return self.factory.makeProductBranch(**kwargs) | ||
105 | 144 | |||
106 | 145 | def makeBranchMergeProposal(self, source=None, target=None, | ||
107 | 146 | prerequisite=None, **kwargs): | ||
108 | 147 | if self.git: | ||
109 | 148 | return self.factory.makeBranchMergeProposalForGit( | ||
110 | 149 | target_ref=target, source_ref=source, | ||
111 | 150 | prerequisite_ref=prerequisite, **kwargs) | ||
112 | 151 | else: | ||
113 | 152 | return self.factory.makeBranchMergeProposal( | ||
114 | 153 | source_branch=source, target_branch=target, | ||
115 | 154 | prerequisite_branch=prerequisite, **kwargs) | ||
116 | 155 | |||
117 | 156 | |||
118 | 112 | class TestBranchMergeProposalInterface(TestCaseWithFactory): | 157 | class TestBranchMergeProposalInterface(TestCaseWithFactory): |
119 | 113 | """Ensure that BranchMergeProposal implements its interface.""" | 158 | """Ensure that BranchMergeProposal implements its interface.""" |
120 | 114 | 159 | ||
121 | @@ -120,26 +165,16 @@ class TestBranchMergeProposalInterface(TestCaseWithFactory): | |||
122 | 120 | verifyObject(IBranchMergeProposal, bmp) | 165 | verifyObject(IBranchMergeProposal, bmp) |
123 | 121 | 166 | ||
124 | 122 | 167 | ||
126 | 123 | class TestBranchMergeProposalCanonicalUrl(WithScenarios, TestCaseWithFactory): | 168 | class TestBranchMergeProposalCanonicalUrl( |
127 | 169 | WithVCSScenarios, TestCaseWithFactory): | ||
128 | 124 | """Tests canonical_url for merge proposals.""" | 170 | """Tests canonical_url for merge proposals.""" |
129 | 125 | 171 | ||
130 | 126 | layer = DatabaseFunctionalLayer | 172 | layer = DatabaseFunctionalLayer |
131 | 127 | 173 | ||
132 | 128 | scenarios = [ | ||
133 | 129 | ("bzr", {"git": False}), | ||
134 | 130 | ("git", {"git": True}), | ||
135 | 131 | ] | ||
136 | 132 | |||
137 | 133 | def _makeBranchMergeProposal(self): | ||
138 | 134 | if self.git: | ||
139 | 135 | return self.factory.makeBranchMergeProposalForGit() | ||
140 | 136 | else: | ||
141 | 137 | return self.factory.makeBranchMergeProposal() | ||
142 | 138 | |||
143 | 139 | def test_BranchMergeProposal_canonical_url_base(self): | 174 | def test_BranchMergeProposal_canonical_url_base(self): |
144 | 140 | # The URL for a merge proposal starts with the parent (source branch | 175 | # The URL for a merge proposal starts with the parent (source branch |
145 | 141 | # or source Git repository). | 176 | # or source Git repository). |
147 | 142 | bmp = self._makeBranchMergeProposal() | 177 | bmp = self.makeBranchMergeProposal() |
148 | 143 | url = canonical_url(bmp) | 178 | url = canonical_url(bmp) |
149 | 144 | parent_url = canonical_url(bmp.parent) | 179 | parent_url = canonical_url(bmp.parent) |
150 | 145 | self.assertTrue(url.startswith(parent_url)) | 180 | self.assertTrue(url.startswith(parent_url)) |
151 | @@ -147,7 +182,7 @@ class TestBranchMergeProposalCanonicalUrl(WithScenarios, TestCaseWithFactory): | |||
152 | 147 | def test_BranchMergeProposal_canonical_url_rest(self): | 182 | def test_BranchMergeProposal_canonical_url_rest(self): |
153 | 148 | # The rest of the URL for a merge proposal is +merge followed by the | 183 | # The rest of the URL for a merge proposal is +merge followed by the |
154 | 149 | # db id. | 184 | # db id. |
156 | 150 | bmp = self._makeBranchMergeProposal() | 185 | bmp = self.makeBranchMergeProposal() |
157 | 151 | url = canonical_url(bmp) | 186 | url = canonical_url(bmp) |
158 | 152 | parent_url = canonical_url(bmp.parent) | 187 | parent_url = canonical_url(bmp.parent) |
159 | 153 | rest = url[len(parent_url):] | 188 | rest = url[len(parent_url):] |
160 | @@ -718,45 +753,14 @@ class TestMergeProposalGetPreviewDiff(TestCaseWithFactory): | |||
161 | 718 | self.mp_two.getPreviewDiff, self.preview_diff.id) | 753 | self.mp_two.getPreviewDiff, self.preview_diff.id) |
162 | 719 | 754 | ||
163 | 720 | 755 | ||
165 | 721 | class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): | 756 | class TestMergeProposalNotification(WithVCSScenarios, TestCaseWithFactory): |
166 | 722 | """Test that events are created when merge proposals are manipulated""" | 757 | """Test that events are created when merge proposals are manipulated""" |
167 | 723 | 758 | ||
168 | 724 | layer = DatabaseFunctionalLayer | 759 | layer = DatabaseFunctionalLayer |
169 | 725 | 760 | ||
170 | 726 | scenarios = [ | ||
171 | 727 | ("bzr", {"git": False}), | ||
172 | 728 | ("git", {"git": True}), | ||
173 | 729 | ] | ||
174 | 730 | |||
175 | 731 | def setUp(self): | 761 | def setUp(self): |
176 | 732 | TestCaseWithFactory.setUp(self, user='test@canonical.com') | 762 | TestCaseWithFactory.setUp(self, user='test@canonical.com') |
177 | 733 | 763 | ||
178 | 734 | def makeBranch(self, same_target_as=None, target=None, **kwargs): | ||
179 | 735 | kwargs = dict(kwargs) | ||
180 | 736 | if self.git: | ||
181 | 737 | if same_target_as is not None: | ||
182 | 738 | kwargs["target"] = same_target_as.target | ||
183 | 739 | elif target is not None: | ||
184 | 740 | kwargs["target"] = target | ||
185 | 741 | return self.factory.makeGitRefs(**kwargs)[0] | ||
186 | 742 | else: | ||
187 | 743 | if same_target_as is not None: | ||
188 | 744 | kwargs["product"] = same_target_as.product | ||
189 | 745 | elif target is not None: | ||
190 | 746 | kwargs["product"] = target | ||
191 | 747 | return self.factory.makeProductBranch(**kwargs) | ||
192 | 748 | |||
193 | 749 | def makeBranchMergeProposal(self, source=None, target=None, | ||
194 | 750 | prerequisite=None, **kwargs): | ||
195 | 751 | if self.git: | ||
196 | 752 | return self.factory.makeBranchMergeProposalForGit( | ||
197 | 753 | source_ref=source, target_ref=target, | ||
198 | 754 | prerequisite_ref=prerequisite, **kwargs) | ||
199 | 755 | else: | ||
200 | 756 | return self.factory.makeBranchMergeProposal( | ||
201 | 757 | source_branch=source, target_branch=target, | ||
202 | 758 | prerequisite_branch=prerequisite, **kwargs) | ||
203 | 759 | |||
204 | 760 | def test_notifyOnCreate_needs_review(self): | 764 | def test_notifyOnCreate_needs_review(self): |
205 | 761 | # When a merge proposal is created needing review, the | 765 | # When a merge proposal is created needing review, the |
206 | 762 | # BranchMergeProposalNeedsReviewEvent is raised as well as the usual | 766 | # BranchMergeProposalNeedsReviewEvent is raised as well as the usual |
207 | @@ -988,8 +992,8 @@ class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): | |||
208 | 988 | # they do not get email about the proposal. | 992 | # they do not get email about the proposal. |
209 | 989 | owner = self.factory.makePerson() | 993 | owner = self.factory.makePerson() |
210 | 990 | product = self.factory.makeProduct() | 994 | product = self.factory.makeProduct() |
213 | 991 | source = self.makeBranch(owner=owner, target=product) | 995 | source = self.makeBranch(owner=owner, product=product) |
214 | 992 | target = self.makeBranch(owner=owner, target=product) | 996 | target = self.makeBranch(owner=owner, product=product) |
215 | 993 | bmp = self.makeBranchMergeProposal(source=source, target=target) | 997 | bmp = self.makeBranchMergeProposal(source=source, target=target) |
216 | 994 | # Subscribe eric to the source branch only. | 998 | # Subscribe eric to the source branch only. |
217 | 995 | eric = self.factory.makePerson() | 999 | eric = self.factory.makePerson() |
218 | @@ -1021,31 +1025,15 @@ class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): | |||
219 | 1021 | self.assertIn(charlie, recipients) | 1025 | self.assertIn(charlie, recipients) |
220 | 1022 | 1026 | ||
221 | 1023 | 1027 | ||
223 | 1024 | class TestMergeProposalWebhooks(WithScenarios, TestCaseWithFactory): | 1028 | class TestMergeProposalWebhooks(WithVCSScenarios, TestCaseWithFactory): |
224 | 1025 | 1029 | ||
225 | 1026 | layer = DatabaseFunctionalLayer | 1030 | layer = DatabaseFunctionalLayer |
226 | 1027 | 1031 | ||
227 | 1028 | scenarios = [ | ||
228 | 1029 | ("bzr", {"git": False}), | ||
229 | 1030 | ("git", {"git": True}), | ||
230 | 1031 | ] | ||
231 | 1032 | |||
232 | 1033 | def setUp(self): | 1032 | def setUp(self): |
233 | 1034 | super(TestMergeProposalWebhooks, self).setUp() | 1033 | super(TestMergeProposalWebhooks, self).setUp() |
234 | 1035 | self.useFixture(FeatureFixture( | 1034 | self.useFixture(FeatureFixture( |
235 | 1036 | {BRANCH_MERGE_PROPOSAL_WEBHOOKS_FEATURE_FLAG: "on"})) | 1035 | {BRANCH_MERGE_PROPOSAL_WEBHOOKS_FEATURE_FLAG: "on"})) |
236 | 1037 | 1036 | ||
237 | 1038 | def makeBranch(self, same_target_as=None): | ||
238 | 1039 | kwargs = {} | ||
239 | 1040 | if self.git: | ||
240 | 1041 | if same_target_as is not None: | ||
241 | 1042 | kwargs["target"] = same_target_as.target | ||
242 | 1043 | return self.factory.makeGitRefs(**kwargs)[0] | ||
243 | 1044 | else: | ||
244 | 1045 | if same_target_as is not None: | ||
245 | 1046 | kwargs["product"] = same_target_as.product | ||
246 | 1047 | return self.factory.makeProductBranch(**kwargs) | ||
247 | 1048 | |||
248 | 1049 | def getWebhookTarget(self, branch): | 1037 | def getWebhookTarget(self, branch): |
249 | 1050 | if self.git: | 1038 | if self.git: |
250 | 1051 | return branch.repository | 1039 | return branch.repository |
251 | @@ -1102,6 +1090,39 @@ class TestMergeProposalWebhooks(WithScenarios, TestCaseWithFactory): | |||
252 | 1102 | (hook, "merge-proposal:0.1", | 1090 | (hook, "merge-proposal:0.1", |
253 | 1103 | MatchesDict(expected_redacted_payload))])) | 1091 | MatchesDict(expected_redacted_payload))])) |
254 | 1104 | 1092 | ||
255 | 1093 | def test_create_private_repo_triggers_webhooks(self): | ||
256 | 1094 | # When a merge proposal is created, any relevant webhooks are | ||
257 | 1095 | # triggered even if the repository is proprietary. | ||
258 | 1096 | logger = self.useFixture(FakeLogger()) | ||
259 | 1097 | source = self.makeBranch(information_type=InformationType.PROPRIETARY) | ||
260 | 1098 | target = self.makeBranch( | ||
261 | 1099 | same_target_as=source, | ||
262 | 1100 | information_type=InformationType.PROPRIETARY) | ||
263 | 1101 | |||
264 | 1102 | with admin_logged_in(): | ||
265 | 1103 | # Create the web hook and the proposal. | ||
266 | 1104 | registrant = self.factory.makePerson() | ||
267 | 1105 | hook = self.factory.makeWebhook( | ||
268 | 1106 | target=self.getWebhookTarget(target), | ||
269 | 1107 | event_types=["merge-proposal:0.1"]) | ||
270 | 1108 | proposal = source.addLandingTarget( | ||
271 | 1109 | registrant, target, needs_review=True) | ||
272 | 1110 | target_owner = target.owner | ||
273 | 1111 | |||
274 | 1112 | login_person(target_owner) | ||
275 | 1113 | delivery = hook.deliveries.one() | ||
276 | 1114 | expected_payload = { | ||
277 | 1115 | "merge_proposal": Equals(self.getURL(proposal)), | ||
278 | 1116 | "action": Equals("created"), | ||
279 | 1117 | "new": MatchesDict(self.getExpectedPayload(proposal)), | ||
280 | 1118 | } | ||
281 | 1119 | expected_redacted_payload = dict( | ||
282 | 1120 | expected_payload, | ||
283 | 1121 | new=MatchesDict( | ||
284 | 1122 | self.getExpectedPayload(proposal, redact=True))) | ||
285 | 1123 | self.assertCorrectDelivery(expected_payload, hook, delivery) | ||
286 | 1124 | self.assertCorrectLogging(expected_redacted_payload, hook, logger) | ||
287 | 1125 | |||
288 | 1105 | def test_create_triggers_webhooks(self): | 1126 | def test_create_triggers_webhooks(self): |
289 | 1106 | # When a merge proposal is created, any relevant webhooks are | 1127 | # When a merge proposal is created, any relevant webhooks are |
290 | 1107 | # triggered. | 1128 | # triggered. |
291 | @@ -1486,15 +1507,10 @@ class TestBranchMergeProposalDeletion(TestCaseWithFactory): | |||
292 | 1486 | SQLObjectNotFound, BranchMergeProposalJob.get, job_id) | 1507 | SQLObjectNotFound, BranchMergeProposalJob.get, job_id) |
293 | 1487 | 1508 | ||
294 | 1488 | 1509 | ||
296 | 1489 | class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | 1510 | class TestBranchMergeProposalBugs(WithVCSScenarios, TestCaseWithFactory): |
297 | 1490 | 1511 | ||
298 | 1491 | layer = DatabaseFunctionalLayer | 1512 | layer = DatabaseFunctionalLayer |
299 | 1492 | 1513 | ||
300 | 1493 | scenarios = [ | ||
301 | 1494 | ("bzr", {"git": False}), | ||
302 | 1495 | ("git", {"git": True}), | ||
303 | 1496 | ] | ||
304 | 1497 | |||
305 | 1498 | def setUp(self): | 1514 | def setUp(self): |
306 | 1499 | super(TestBranchMergeProposalBugs, self).setUp() | 1515 | super(TestBranchMergeProposalBugs, self).setUp() |
307 | 1500 | self.user = self.factory.makePerson() | 1516 | self.user = self.factory.makePerson() |
308 | @@ -1502,15 +1518,9 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
309 | 1502 | if self.git: | 1518 | if self.git: |
310 | 1503 | self.hosting_fixture = self.useFixture(GitHostingFixture()) | 1519 | self.hosting_fixture = self.useFixture(GitHostingFixture()) |
311 | 1504 | 1520 | ||
312 | 1505 | def _makeBranchMergeProposal(self): | ||
313 | 1506 | if self.git: | ||
314 | 1507 | return self.factory.makeBranchMergeProposalForGit() | ||
315 | 1508 | else: | ||
316 | 1509 | return self.factory.makeBranchMergeProposal() | ||
317 | 1510 | |||
318 | 1511 | def test_bugs(self): | 1521 | def test_bugs(self): |
319 | 1512 | # bugs includes all linked bugs. | 1522 | # bugs includes all linked bugs. |
321 | 1513 | bmp = self._makeBranchMergeProposal() | 1523 | bmp = self.makeBranchMergeProposal() |
322 | 1514 | self.assertEqual([], bmp.bugs) | 1524 | self.assertEqual([], bmp.bugs) |
323 | 1515 | bugs = [self.factory.makeBug() for _ in range(2)] | 1525 | bugs = [self.factory.makeBug() for _ in range(2)] |
324 | 1516 | bmp.linkBug(bugs[0], bmp.registrant) | 1526 | bmp.linkBug(bugs[0], bmp.registrant) |
325 | @@ -1525,7 +1535,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
326 | 1525 | def test_related_bugtasks_includes_source_bugtasks(self): | 1535 | def test_related_bugtasks_includes_source_bugtasks(self): |
327 | 1526 | # related_bugtasks includes bugtasks linked to the source branch in | 1536 | # related_bugtasks includes bugtasks linked to the source branch in |
328 | 1527 | # the Bazaar case, or directly to the MP in the Git case. | 1537 | # the Bazaar case, or directly to the MP in the Git case. |
330 | 1528 | bmp = self._makeBranchMergeProposal() | 1538 | bmp = self.makeBranchMergeProposal() |
331 | 1529 | bug = self.factory.makeBug() | 1539 | bug = self.factory.makeBug() |
332 | 1530 | bmp.linkBug(bug, bmp.registrant) | 1540 | bmp.linkBug(bug, bmp.registrant) |
333 | 1531 | self.assertEqual( | 1541 | self.assertEqual( |
334 | @@ -1533,7 +1543,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
335 | 1533 | 1543 | ||
336 | 1534 | def test_related_bugtasks_excludes_private_bugs(self): | 1544 | def test_related_bugtasks_excludes_private_bugs(self): |
337 | 1535 | # related_bugtasks ignores private bugs for non-authorised users. | 1545 | # related_bugtasks ignores private bugs for non-authorised users. |
339 | 1536 | bmp = self._makeBranchMergeProposal() | 1546 | bmp = self.makeBranchMergeProposal() |
340 | 1537 | bug = self.factory.makeBug() | 1547 | bug = self.factory.makeBug() |
341 | 1538 | bmp.linkBug(bug, bmp.registrant) | 1548 | bmp.linkBug(bug, bmp.registrant) |
342 | 1539 | person = self.factory.makePerson() | 1549 | person = self.factory.makePerson() |
343 | @@ -1553,7 +1563,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
344 | 1553 | # related_bugtasks ignores bugs linked to the target branch. | 1563 | # related_bugtasks ignores bugs linked to the target branch. |
345 | 1554 | if self.git: | 1564 | if self.git: |
346 | 1555 | self.skipTest("Only relevant for Bazaar.") | 1565 | self.skipTest("Only relevant for Bazaar.") |
348 | 1556 | bmp = self._makeBranchMergeProposal() | 1566 | bmp = self.makeBranchMergeProposal() |
349 | 1557 | bug = self.factory.makeBug() | 1567 | bug = self.factory.makeBug() |
350 | 1558 | bmp.target_branch.linkBug(bug, bmp.registrant) | 1568 | bmp.target_branch.linkBug(bug, bmp.registrant) |
351 | 1559 | self.assertEqual([], list(bmp.getRelatedBugTasks(self.user))) | 1569 | self.assertEqual([], list(bmp.getRelatedBugTasks(self.user))) |
352 | @@ -1562,7 +1572,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
353 | 1562 | # related_bugtasks ignores bugs linked to both branches. | 1572 | # related_bugtasks ignores bugs linked to both branches. |
354 | 1563 | if self.git: | 1573 | if self.git: |
355 | 1564 | self.skipTest("Only relevant for Bazaar.") | 1574 | self.skipTest("Only relevant for Bazaar.") |
357 | 1565 | bmp = self._makeBranchMergeProposal() | 1575 | bmp = self.makeBranchMergeProposal() |
358 | 1566 | bug = self.factory.makeBug() | 1576 | bug = self.factory.makeBug() |
359 | 1567 | bmp.source_branch.linkBug(bug, bmp.registrant) | 1577 | bmp.source_branch.linkBug(bug, bmp.registrant) |
360 | 1568 | bmp.target_branch.linkBug(bug, bmp.registrant) | 1578 | bmp.target_branch.linkBug(bug, bmp.registrant) |
361 | @@ -1574,7 +1584,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
362 | 1574 | if not self.git: | 1584 | if not self.git: |
363 | 1575 | self.skipTest("Only relevant for Git.") | 1585 | self.skipTest("Only relevant for Git.") |
364 | 1576 | bugs = [self.factory.makeBug() for _ in range(3)] | 1586 | bugs = [self.factory.makeBug() for _ in range(3)] |
366 | 1577 | bmp = self._makeBranchMergeProposal() | 1587 | bmp = self.makeBranchMergeProposal() |
367 | 1578 | self.hosting_fixture.getLog.result = [ | 1588 | self.hosting_fixture.getLog.result = [ |
368 | 1579 | { | 1589 | { |
369 | 1580 | "sha1": bmp.source_git_commit_sha1, | 1590 | "sha1": bmp.source_git_commit_sha1, |
370 | @@ -1621,7 +1631,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
371 | 1621 | # bugs in either the database or the source branch. | 1631 | # bugs in either the database or the source branch. |
372 | 1622 | if not self.git: | 1632 | if not self.git: |
373 | 1623 | self.skipTest("Only relevant for Git.") | 1633 | self.skipTest("Only relevant for Git.") |
375 | 1624 | bmp = self._makeBranchMergeProposal() | 1634 | bmp = self.makeBranchMergeProposal() |
376 | 1625 | self._setUpLog([]) | 1635 | self._setUpLog([]) |
377 | 1626 | bmp.updateRelatedBugsFromSource() | 1636 | bmp.updateRelatedBugsFromSource() |
378 | 1627 | self.assertEqual([], bmp.bugs) | 1637 | self.assertEqual([], bmp.bugs) |
379 | @@ -1632,7 +1642,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
380 | 1632 | if not self.git: | 1642 | if not self.git: |
381 | 1633 | self.skipTest("Only relevant for Git.") | 1643 | self.skipTest("Only relevant for Git.") |
382 | 1634 | bugs = [self.factory.makeBug() for _ in range(3)] | 1644 | bugs = [self.factory.makeBug() for _ in range(3)] |
384 | 1635 | bmp = self._makeBranchMergeProposal() | 1645 | bmp = self.makeBranchMergeProposal() |
385 | 1636 | self._setUpLog([bugs[0]]) | 1646 | self._setUpLog([bugs[0]]) |
386 | 1637 | bmp.updateRelatedBugsFromSource() | 1647 | bmp.updateRelatedBugsFromSource() |
387 | 1638 | self.assertEqual([bugs[0]], bmp.bugs) | 1648 | self.assertEqual([bugs[0]], bmp.bugs) |
388 | @@ -1646,7 +1656,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
389 | 1646 | if not self.git: | 1656 | if not self.git: |
390 | 1647 | self.skipTest("Only relevant for Git.") | 1657 | self.skipTest("Only relevant for Git.") |
391 | 1648 | bug = self.factory.makeBug() | 1658 | bug = self.factory.makeBug() |
393 | 1649 | bmp = self._makeBranchMergeProposal() | 1659 | bmp = self.makeBranchMergeProposal() |
394 | 1650 | self._setUpLog([bug]) | 1660 | self._setUpLog([bug]) |
395 | 1651 | bmp.updateRelatedBugsFromSource() | 1661 | bmp.updateRelatedBugsFromSource() |
396 | 1652 | self.assertEqual([bug], bmp.bugs) | 1662 | self.assertEqual([bug], bmp.bugs) |
397 | @@ -1661,7 +1671,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
398 | 1661 | if not self.git: | 1671 | if not self.git: |
399 | 1662 | self.skipTest("Only relevant for Git.") | 1672 | self.skipTest("Only relevant for Git.") |
400 | 1663 | bug = self.factory.makeBug() | 1673 | bug = self.factory.makeBug() |
402 | 1664 | bmp = self._makeBranchMergeProposal() | 1674 | bmp = self.makeBranchMergeProposal() |
403 | 1665 | self._setUpLog([bug]) | 1675 | self._setUpLog([bug]) |
404 | 1666 | bmp.updateRelatedBugsFromSource() | 1676 | bmp.updateRelatedBugsFromSource() |
405 | 1667 | self.assertEqual([bug], bmp.bugs) | 1677 | self.assertEqual([bug], bmp.bugs) |
406 | @@ -1676,7 +1686,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
407 | 1676 | if not self.git: | 1686 | if not self.git: |
408 | 1677 | self.skipTest("Only relevant for Git.") | 1687 | self.skipTest("Only relevant for Git.") |
409 | 1678 | bug = self.factory.makeBug() | 1688 | bug = self.factory.makeBug() |
411 | 1679 | bmp = self._makeBranchMergeProposal() | 1689 | bmp = self.makeBranchMergeProposal() |
412 | 1680 | bmp.linkBug(bug) | 1690 | bmp.linkBug(bug) |
413 | 1681 | self._setUpLog([]) | 1691 | self._setUpLog([]) |
414 | 1682 | bmp.updateRelatedBugsFromSource() | 1692 | bmp.updateRelatedBugsFromSource() |
415 | @@ -1701,7 +1711,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
416 | 1701 | self.skipTest("Only relevant for Git.") | 1711 | self.skipTest("Only relevant for Git.") |
417 | 1702 | self.pushConfig("codehosting", related_bugs_from_source_limit=3) | 1712 | self.pushConfig("codehosting", related_bugs_from_source_limit=3) |
418 | 1703 | bugs = [self.factory.makeBug() for _ in range(5)] | 1713 | bugs = [self.factory.makeBug() for _ in range(5)] |
420 | 1704 | bmp = self._makeBranchMergeProposal() | 1714 | bmp = self.makeBranchMergeProposal() |
421 | 1705 | self._setUpLog([bugs[0]]) | 1715 | self._setUpLog([bugs[0]]) |
422 | 1706 | bmp.updateRelatedBugsFromSource() | 1716 | bmp.updateRelatedBugsFromSource() |
423 | 1707 | self.assertEqual([bugs[0]], bmp.bugs) | 1717 | self.assertEqual([bugs[0]], bmp.bugs) |
424 | @@ -1713,45 +1723,48 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): | |||
425 | 1713 | self.assertEqual("TooManyRelatedBugs", self.oopses[0]["type"]) | 1723 | self.assertEqual("TooManyRelatedBugs", self.oopses[0]["type"]) |
426 | 1714 | 1724 | ||
427 | 1715 | 1725 | ||
429 | 1716 | class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | 1726 | class TestBranchMergeProposalNominateReviewer( |
430 | 1727 | WithVCSScenarios, TestCaseWithFactory): | ||
431 | 1717 | """Test that the appropriate vote references get created.""" | 1728 | """Test that the appropriate vote references get created.""" |
432 | 1718 | 1729 | ||
433 | 1719 | layer = DatabaseFunctionalLayer | 1730 | layer = DatabaseFunctionalLayer |
434 | 1720 | 1731 | ||
435 | 1721 | def setUp(self): | 1732 | def setUp(self): |
436 | 1722 | TestCaseWithFactory.setUp(self, user='test@canonical.com') | 1733 | TestCaseWithFactory.setUp(self, user='test@canonical.com') |
437 | 1734 | if self.git: | ||
438 | 1735 | self.hosting_fixture = self.useFixture(GitHostingFixture()) | ||
439 | 1723 | 1736 | ||
440 | 1724 | def test_notify_on_nominate(self): | 1737 | def test_notify_on_nominate(self): |
441 | 1725 | # Ensure that a notification is emitted on nomination. | 1738 | # Ensure that a notification is emitted on nomination. |
444 | 1726 | merge_proposal = self.factory.makeBranchMergeProposal() | 1739 | merge_proposal = self.makeBranchMergeProposal() |
445 | 1727 | login_person(merge_proposal.source_branch.owner) | 1740 | login_person(merge_proposal.merge_source.owner) |
446 | 1728 | reviewer = self.factory.makePerson() | 1741 | reviewer = self.factory.makePerson() |
447 | 1729 | result, events = self.assertNotifies( | 1742 | result, events = self.assertNotifies( |
448 | 1730 | ReviewerNominatedEvent, False, | 1743 | ReviewerNominatedEvent, False, |
449 | 1731 | merge_proposal.nominateReviewer, | 1744 | merge_proposal.nominateReviewer, |
450 | 1732 | reviewer=reviewer, | 1745 | reviewer=reviewer, |
452 | 1733 | registrant=merge_proposal.source_branch.owner) | 1746 | registrant=merge_proposal.merge_source.owner) |
453 | 1734 | self.assertEqual(result, events[0].object) | 1747 | self.assertEqual(result, events[0].object) |
454 | 1735 | 1748 | ||
455 | 1736 | def test_notify_on_nominate_suppressed_if_requested(self): | 1749 | def test_notify_on_nominate_suppressed_if_requested(self): |
456 | 1737 | # Ensure that a notification is suppressed if notify listeners is set | 1750 | # Ensure that a notification is suppressed if notify listeners is set |
457 | 1738 | # to False. | 1751 | # to False. |
460 | 1739 | merge_proposal = self.factory.makeBranchMergeProposal() | 1752 | merge_proposal = self.makeBranchMergeProposal() |
461 | 1740 | login_person(merge_proposal.source_branch.owner) | 1753 | login_person(merge_proposal.merge_source.owner) |
462 | 1741 | reviewer = self.factory.makePerson() | 1754 | reviewer = self.factory.makePerson() |
463 | 1742 | self.assertNoNotification( | 1755 | self.assertNoNotification( |
464 | 1743 | merge_proposal.nominateReviewer, | 1756 | merge_proposal.nominateReviewer, |
465 | 1744 | reviewer=reviewer, | 1757 | reviewer=reviewer, |
467 | 1745 | registrant=merge_proposal.source_branch.owner, | 1758 | registrant=merge_proposal.merge_source.owner, |
468 | 1746 | _notify_listeners=False) | 1759 | _notify_listeners=False) |
469 | 1747 | 1760 | ||
470 | 1748 | def test_one_initial_votes(self): | 1761 | def test_one_initial_votes(self): |
471 | 1749 | """A new merge proposal has one vote of the default reviewer.""" | 1762 | """A new merge proposal has one vote of the default reviewer.""" |
473 | 1750 | merge_proposal = self.factory.makeBranchMergeProposal() | 1763 | merge_proposal = self.makeBranchMergeProposal() |
474 | 1751 | self.assertEqual(1, len(list(merge_proposal.votes))) | 1764 | self.assertEqual(1, len(list(merge_proposal.votes))) |
475 | 1752 | [vote] = list(merge_proposal.votes) | 1765 | [vote] = list(merge_proposal.votes) |
476 | 1753 | self.assertEqual( | 1766 | self.assertEqual( |
478 | 1754 | merge_proposal.target_branch.owner, vote.reviewer) | 1767 | merge_proposal.merge_target.owner, vote.reviewer) |
479 | 1755 | 1768 | ||
480 | 1756 | def makeProposalWithReviewer(self, reviewer=None, review_type=None, | 1769 | def makeProposalWithReviewer(self, reviewer=None, review_type=None, |
481 | 1757 | registrant=None, **kwargs): | 1770 | registrant=None, **kwargs): |
482 | @@ -1764,8 +1777,9 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
483 | 1764 | if registrant is None: | 1777 | if registrant is None: |
484 | 1765 | registrant = self.factory.makePerson() | 1778 | registrant = self.factory.makePerson() |
485 | 1766 | merge_proposal = make_merge_proposal_without_reviewers( | 1779 | merge_proposal = make_merge_proposal_without_reviewers( |
488 | 1767 | factory=self.factory, registrant=registrant, **kwargs) | 1780 | factory=self.factory, for_git=self.git, registrant=registrant, |
489 | 1768 | login_person(merge_proposal.source_branch.owner) | 1781 | **kwargs) |
490 | 1782 | login_person(merge_proposal.merge_source.owner) | ||
491 | 1769 | merge_proposal.nominateReviewer( | 1783 | merge_proposal.nominateReviewer( |
492 | 1770 | reviewer=reviewer, registrant=registrant, review_type=review_type) | 1784 | reviewer=reviewer, registrant=registrant, review_type=review_type) |
493 | 1771 | return merge_proposal, reviewer | 1785 | return merge_proposal, reviewer |
494 | @@ -1871,15 +1885,15 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
495 | 1871 | 1885 | ||
496 | 1872 | def test_nominate_updates_reference(self): | 1886 | def test_nominate_updates_reference(self): |
497 | 1873 | """The existing reference is updated on re-nomination.""" | 1887 | """The existing reference is updated on re-nomination.""" |
500 | 1874 | merge_proposal = self.factory.makeBranchMergeProposal() | 1888 | merge_proposal = self.makeBranchMergeProposal() |
501 | 1875 | login_person(merge_proposal.source_branch.owner) | 1889 | login_person(merge_proposal.merge_source.owner) |
502 | 1876 | reviewer = self.factory.makePerson() | 1890 | reviewer = self.factory.makePerson() |
503 | 1877 | reference = merge_proposal.nominateReviewer( | 1891 | reference = merge_proposal.nominateReviewer( |
505 | 1878 | reviewer=reviewer, registrant=merge_proposal.source_branch.owner, | 1892 | reviewer=reviewer, registrant=merge_proposal.merge_source.owner, |
506 | 1879 | review_type='General') | 1893 | review_type='General') |
507 | 1880 | self.assertEqual('general', reference.review_type) | 1894 | self.assertEqual('general', reference.review_type) |
508 | 1881 | merge_proposal.nominateReviewer( | 1895 | merge_proposal.nominateReviewer( |
510 | 1882 | reviewer=reviewer, registrant=merge_proposal.source_branch.owner, | 1896 | reviewer=reviewer, registrant=merge_proposal.merge_source.owner, |
511 | 1883 | review_type='Specific') | 1897 | review_type='Specific') |
512 | 1884 | # Note we're using the reference from the first call | 1898 | # Note we're using the reference from the first call |
513 | 1885 | self.assertEqual('specific', reference.review_type) | 1899 | self.assertEqual('specific', reference.review_type) |
514 | @@ -1896,31 +1910,37 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
515 | 1896 | CodeReviewNotificationLevel.FULL, sub.review_level) | 1910 | CodeReviewNotificationLevel.FULL, sub.review_level) |
516 | 1897 | # The reviewer can see the branch. | 1911 | # The reviewer can see the branch. |
517 | 1898 | self.assertTrue(branch.visibleByUser(reviewer)) | 1912 | self.assertTrue(branch.visibleByUser(reviewer)) |
519 | 1899 | if branch.stacked_on is not None: | 1913 | if IBranch.providedBy(branch) and branch.stacked_on is not None: |
520 | 1900 | self._check_mp_branch_visibility(branch.stacked_on, reviewer) | 1914 | self._check_mp_branch_visibility(branch.stacked_on, reviewer) |
521 | 1901 | 1915 | ||
522 | 1902 | def _test_nominate_grants_visibility(self, reviewer): | 1916 | def _test_nominate_grants_visibility(self, reviewer): |
523 | 1903 | """Nominated reviewers can see the source and target branches.""" | 1917 | """Nominated reviewers can see the source and target branches.""" |
524 | 1904 | owner = self.factory.makePerson() | 1918 | owner = self.factory.makePerson() |
525 | 1905 | product = self.factory.makeProduct() | 1919 | product = self.factory.makeProduct() |
528 | 1906 | # We make a source branch stacked on a private one. | 1920 | # For bzr, we make a source branch stacked on a private one. |
529 | 1907 | base_branch = self.factory.makeBranch( | 1921 | # For git, we make the gitref itself private. |
530 | 1922 | if self.git: | ||
531 | 1923 | source_branch = self.makeBranch( | ||
532 | 1924 | product=product, owner=owner, | ||
533 | 1925 | information_type=InformationType.USERDATA) | ||
534 | 1926 | else: | ||
535 | 1927 | base_branch = self.makeBranch( | ||
536 | 1928 | owner=owner, product=product, | ||
537 | 1929 | information_type=InformationType.USERDATA) | ||
538 | 1930 | source_branch = self.makeBranch( | ||
539 | 1931 | stacked_on=base_branch, product=product, owner=owner) | ||
540 | 1932 | target_branch = self.makeBranch( | ||
541 | 1908 | owner=owner, product=product, | 1933 | owner=owner, product=product, |
542 | 1909 | information_type=InformationType.USERDATA) | 1934 | information_type=InformationType.USERDATA) |
543 | 1910 | source_branch = self.factory.makeBranch( | ||
544 | 1911 | stacked_on=base_branch, product=product, owner=owner) | ||
545 | 1912 | target_branch = self.factory.makeBranch(owner=owner, product=product) | ||
546 | 1913 | login_person(owner) | 1935 | login_person(owner) |
551 | 1914 | merge_proposal = self.factory.makeBranchMergeProposal( | 1936 | merge_proposal = self.makeBranchMergeProposal( |
552 | 1915 | source_branch=source_branch, | 1937 | source=source_branch, target=target_branch) |
549 | 1916 | target_branch=target_branch) | ||
550 | 1917 | target_branch.setPrivate(True, owner) | ||
553 | 1918 | # The reviewer can't see the source or target branches. | 1938 | # The reviewer can't see the source or target branches. |
554 | 1919 | self.assertFalse(source_branch.visibleByUser(reviewer)) | 1939 | self.assertFalse(source_branch.visibleByUser(reviewer)) |
555 | 1920 | self.assertFalse(target_branch.visibleByUser(reviewer)) | 1940 | self.assertFalse(target_branch.visibleByUser(reviewer)) |
556 | 1921 | merge_proposal.nominateReviewer( | 1941 | merge_proposal.nominateReviewer( |
557 | 1922 | reviewer=reviewer, | 1942 | reviewer=reviewer, |
559 | 1923 | registrant=merge_proposal.source_branch.owner) | 1943 | registrant=merge_proposal.merge_source.owner) |
560 | 1924 | for branch in [source_branch, target_branch]: | 1944 | for branch in [source_branch, target_branch]: |
561 | 1925 | self._check_mp_branch_visibility(branch, reviewer) | 1945 | self._check_mp_branch_visibility(branch, reviewer) |
562 | 1926 | 1946 | ||
563 | @@ -1944,7 +1964,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
564 | 1944 | def test_comment_with_vote_creates_reference(self): | 1964 | def test_comment_with_vote_creates_reference(self): |
565 | 1945 | """A comment with a vote creates a vote reference.""" | 1965 | """A comment with a vote creates a vote reference.""" |
566 | 1946 | reviewer = self.factory.makePerson() | 1966 | reviewer = self.factory.makePerson() |
568 | 1947 | merge_proposal = self.factory.makeBranchMergeProposal( | 1967 | merge_proposal = self.makeBranchMergeProposal( |
569 | 1948 | reviewer=reviewer, registrant=reviewer) | 1968 | reviewer=reviewer, registrant=reviewer) |
570 | 1949 | comment = merge_proposal.createComment( | 1969 | comment = merge_proposal.createComment( |
571 | 1950 | reviewer, 'Message subject', 'Message content', | 1970 | reviewer, 'Message subject', 'Message content', |
572 | @@ -1955,7 +1975,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
573 | 1955 | def test_comment_without_a_vote_does_not_create_reference(self): | 1975 | def test_comment_without_a_vote_does_not_create_reference(self): |
574 | 1956 | """A comment with a vote creates a vote reference.""" | 1976 | """A comment with a vote creates a vote reference.""" |
575 | 1957 | reviewer = self.factory.makePerson() | 1977 | reviewer = self.factory.makePerson() |
577 | 1958 | merge_proposal = make_merge_proposal_without_reviewers(self.factory) | 1978 | merge_proposal = make_merge_proposal_without_reviewers( |
578 | 1979 | self.factory, for_git=self.git) | ||
579 | 1959 | merge_proposal.createComment( | 1980 | merge_proposal.createComment( |
580 | 1960 | reviewer, 'Message subject', 'Message content') | 1981 | reviewer, 'Message subject', 'Message content') |
581 | 1961 | self.assertEqual([], list(merge_proposal.votes)) | 1982 | self.assertEqual([], list(merge_proposal.votes)) |
582 | @@ -1963,7 +1984,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
583 | 1963 | def test_second_vote_by_person_just_alters_reference(self): | 1984 | def test_second_vote_by_person_just_alters_reference(self): |
584 | 1964 | """A second vote changes the comment reference only.""" | 1985 | """A second vote changes the comment reference only.""" |
585 | 1965 | reviewer = self.factory.makePerson() | 1986 | reviewer = self.factory.makePerson() |
587 | 1966 | merge_proposal = self.factory.makeBranchMergeProposal( | 1987 | merge_proposal = self.makeBranchMergeProposal( |
588 | 1967 | reviewer=reviewer, registrant=reviewer) | 1988 | reviewer=reviewer, registrant=reviewer) |
589 | 1968 | merge_proposal.createComment( | 1989 | merge_proposal.createComment( |
590 | 1969 | reviewer, 'Message subject', 'Message content', | 1990 | reviewer, 'Message subject', 'Message content', |
591 | @@ -1979,7 +2000,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
592 | 1979 | reviewer = self.factory.makePerson() | 2000 | reviewer = self.factory.makePerson() |
593 | 1980 | merge_proposal, ignore = self.makeProposalWithReviewer( | 2001 | merge_proposal, ignore = self.makeProposalWithReviewer( |
594 | 1981 | reviewer=reviewer, review_type='general') | 2002 | reviewer=reviewer, review_type='general') |
596 | 1982 | login(merge_proposal.source_branch.owner.preferredemail.email) | 2003 | login(merge_proposal.merge_source.owner.preferredemail.email) |
597 | 1983 | comment = merge_proposal.createComment( | 2004 | comment = merge_proposal.createComment( |
598 | 1984 | reviewer, 'Message subject', 'Message content', | 2005 | reviewer, 'Message subject', 'Message content', |
599 | 1985 | vote=CodeReviewVote.APPROVE, review_type='general') | 2006 | vote=CodeReviewVote.APPROVE, review_type='general') |
600 | @@ -1999,7 +2020,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
601 | 1999 | team = self.factory.makeTeam(owner=reviewer) | 2020 | team = self.factory.makeTeam(owner=reviewer) |
602 | 2000 | merge_proposal, ignore = self.makeProposalWithReviewer( | 2021 | merge_proposal, ignore = self.makeProposalWithReviewer( |
603 | 2001 | reviewer=team, review_type='general') | 2022 | reviewer=team, review_type='general') |
605 | 2002 | login(merge_proposal.source_branch.owner.preferredemail.email) | 2023 | login(merge_proposal.merge_source.owner.preferredemail.email) |
606 | 2003 | [vote] = list(merge_proposal.votes) | 2024 | [vote] = list(merge_proposal.votes) |
607 | 2004 | self.assertEqual(team, vote.reviewer) | 2025 | self.assertEqual(team, vote.reviewer) |
608 | 2005 | comment = merge_proposal.createComment( | 2026 | comment = merge_proposal.createComment( |
609 | @@ -2016,8 +2037,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
610 | 2016 | # one. | 2037 | # one. |
611 | 2017 | reviewer = self.factory.makePerson() | 2038 | reviewer = self.factory.makePerson() |
612 | 2018 | team = self.factory.makeTeam(owner=reviewer) | 2039 | team = self.factory.makeTeam(owner=reviewer) |
615 | 2019 | merge_proposal = self.factory.makeBranchMergeProposal(reviewer=team) | 2040 | merge_proposal = self.makeBranchMergeProposal(reviewer=team) |
616 | 2020 | login(merge_proposal.source_branch.owner.preferredemail.email) | 2041 | login(merge_proposal.merge_source.owner.preferredemail.email) |
617 | 2021 | [vote] = list(merge_proposal.votes) | 2042 | [vote] = list(merge_proposal.votes) |
618 | 2022 | self.assertEqual(team, vote.reviewer) | 2043 | self.assertEqual(team, vote.reviewer) |
619 | 2023 | comment = merge_proposal.createComment( | 2044 | comment = merge_proposal.createComment( |
620 | @@ -2035,8 +2056,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): | |||
621 | 2035 | merge_proposal_1, reviewer_1 = self.makeProposalWithReviewer( | 2056 | merge_proposal_1, reviewer_1 = self.makeProposalWithReviewer( |
622 | 2036 | set_state=BranchMergeProposalStatus.MERGED) | 2057 | set_state=BranchMergeProposalStatus.MERGED) |
623 | 2037 | merge_proposal_2, _ = self.makeProposalWithReviewer( | 2058 | merge_proposal_2, _ = self.makeProposalWithReviewer( |
626 | 2038 | target_branch=merge_proposal_1.target_branch, | 2059 | target=merge_proposal_1.merge_target, |
627 | 2039 | source_branch=merge_proposal_1.source_branch) | 2060 | source=merge_proposal_1.merge_source) |
628 | 2040 | merge_proposal_2.nominateReviewer( | 2061 | merge_proposal_2.nominateReviewer( |
629 | 2041 | reviewer=reviewer_1, registrant=merge_proposal_2.registrant) | 2062 | reviewer=reviewer_1, registrant=merge_proposal_2.registrant) |
630 | 2042 | votes_1 = list(merge_proposal_1.votes) | 2063 | votes_1 = list(merge_proposal_1.votes) |
631 | diff --git a/lib/lp/code/tests/helpers.py b/lib/lp/code/tests/helpers.py | |||
632 | index 46f12ed..0e784f0 100644 | |||
633 | --- a/lib/lp/code/tests/helpers.py | |||
634 | +++ b/lib/lp/code/tests/helpers.py | |||
635 | @@ -1,4 +1,4 @@ | |||
637 | 1 | # Copyright 2009-2018 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
638 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
639 | 3 | 3 | ||
640 | 4 | """Helper functions for code testing live here.""" | 4 | """Helper functions for code testing live here.""" |
641 | @@ -49,8 +49,8 @@ from lp.code.model.seriessourcepackagebranch import ( | |||
642 | 49 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 49 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
643 | 50 | from lp.registry.interfaces.series import SeriesStatus | 50 | from lp.registry.interfaces.series import SeriesStatus |
644 | 51 | from lp.services.database.sqlbase import cursor | 51 | from lp.services.database.sqlbase import cursor |
645 | 52 | from lp.services.propertycache import get_property_cache | ||
646 | 53 | from lp.services.memcache.testing import MemcacheFixture | 52 | from lp.services.memcache.testing import MemcacheFixture |
647 | 53 | from lp.services.propertycache import get_property_cache | ||
648 | 54 | from lp.testing import ( | 54 | from lp.testing import ( |
649 | 55 | run_with_login, | 55 | run_with_login, |
650 | 56 | time_counter, | 56 | time_counter, |
651 | @@ -271,9 +271,18 @@ def recipe_parser_newest_version(version): | |||
652 | 271 | RecipeParser.NEWEST_VERSION = old_version | 271 | RecipeParser.NEWEST_VERSION = old_version |
653 | 272 | 272 | ||
654 | 273 | 273 | ||
656 | 274 | def make_merge_proposal_without_reviewers(factory, **kwargs): | 274 | def make_merge_proposal_without_reviewers( |
657 | 275 | factory, for_git=False, source=None, target=None, **kwargs): | ||
658 | 275 | """Make a merge proposal and strip of any review votes.""" | 276 | """Make a merge proposal and strip of any review votes.""" |
660 | 276 | proposal = factory.makeBranchMergeProposal(**kwargs) | 277 | kwargs = dict(kwargs) |
661 | 278 | if for_git: | ||
662 | 279 | kwargs["source_ref"] = source | ||
663 | 280 | kwargs["target_ref"] = target | ||
664 | 281 | proposal = factory.makeBranchMergeProposalForGit(**kwargs) | ||
665 | 282 | else: | ||
666 | 283 | kwargs["source_branch"] = source | ||
667 | 284 | kwargs["target_branch"] = target | ||
668 | 285 | proposal = factory.makeBranchMergeProposal(**kwargs) | ||
669 | 277 | for vote in proposal.votes: | 286 | for vote in proposal.votes: |
670 | 278 | removeSecurityProxy(vote).destroySelf() | 287 | removeSecurityProxy(vote).destroySelf() |
671 | 279 | del get_property_cache(proposal).votes | 288 | del get_property_cache(proposal).votes |