launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21178
[Merge] lp:~cjwatson/launchpad/git-subscription-tests into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/git-subscription-tests into lp:launchpad.
Commit message:
Add more tests for Git subscriptions.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/git-subscription-tests/+merge/310467
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/git-subscription-tests into lp:launchpad.
=== modified file 'lib/lp/code/browser/tests/test_branchsubscription.py'
--- lib/lp/code/browser/tests/test_branchsubscription.py 2014-11-28 22:07:05 +0000
+++ lib/lp/code/browser/tests/test_branchsubscription.py 2016-11-09 18:08:56 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Unit tests for BranchSubscriptions."""
@@ -31,7 +31,7 @@
'field.actions.subscribe_action': 'Subscribe'}
with person_logged_in(owner):
view = create_initialized_view(
- branch, '+addsubscriber', pricipal=owner, form=form)
+ branch, '+addsubscriber', principal=owner, form=form)
self.assertContentEqual(
['Open and delegated teams cannot be subscribed to private '
'branches.'], view.errors)
@@ -48,5 +48,5 @@
'field.actions.subscribe_action': 'Subscribe'}
with person_logged_in(owner):
view = create_initialized_view(
- branch, '+addsubscriber', pricipal=owner, form=form)
+ branch, '+addsubscriber', principal=owner, form=form)
self.assertContentEqual([], view.errors)
=== modified file 'lib/lp/code/browser/tests/test_gitrepository.py'
--- lib/lp/code/browser/tests/test_gitrepository.py 2016-10-05 10:07:08 +0000
+++ lib/lp/code/browser/tests/test_gitrepository.py 2016-11-09 18:08:56 +0000
@@ -190,7 +190,8 @@
repository = self.factory.makeGitRepository()
with person_logged_in(repository.owner):
self.factory.makeGitSubscription(
- repository, private_subscriber, repository.owner)
+ repository=repository, person=private_subscriber,
+ subscribed_by=repository.owner)
# Ensure the repository subscriber is rendered.
url = canonical_url(repository, rootsite='code')
user = self.factory.makePerson()
@@ -207,7 +208,8 @@
repository = self.factory.makeGitRepository()
with person_logged_in(private_subscriber):
self.factory.makeGitSubscription(
- repository, private_subscriber, repository.owner)
+ repository=repository, person=private_subscriber,
+ subscribed_by=repository.owner)
# Viewing the repository doesn't show the private subscriber.
url = canonical_url(repository, rootsite='code')
browser = self._getBrowser()
@@ -230,7 +232,8 @@
target=project, owner=owner, name=u"repo",
information_type=InformationType.USERDATA)
with person_logged_in(owner):
- self.factory.makeGitSubscription(repository, subscriber, owner)
+ self.factory.makeGitSubscription(
+ repository=repository, person=subscriber, subscribed_by=owner)
base_url = canonical_url(repository, rootsite='code')
expected_title = '%s : Git : Code : %s' % (
repository.identity, project.displayname)
@@ -251,7 +254,8 @@
target=project, owner=owner,
information_type=InformationType.USERDATA)
with person_logged_in(owner):
- self.factory.makeGitSubscription(repository, subscriber, owner)
+ self.factory.makeGitSubscription(
+ repository=repository, person=subscriber, subscribed_by=owner)
base_url = canonical_url(repository, rootsite='code')
project_url = canonical_url(project, rootsite='code')
url = '%s/+subscription/%s' % (base_url, subscriber.name)
=== modified file 'lib/lp/code/browser/tests/test_gitsubscription.py'
--- lib/lp/code/browser/tests/test_gitsubscription.py 2015-05-14 13:57:51 +0000
+++ lib/lp/code/browser/tests/test_gitsubscription.py 2016-11-09 18:08:56 +0000
@@ -1,16 +1,33 @@
-# Copyright 2015 Canonical Ltd. This software is licensed under the
+# Copyright 2015-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Unit tests for GitSubscriptions."""
__metaclass__ = type
+from urllib import urlencode
+
+from fixtures import FakeLogger
+from mechanize import LinkNotFoundError
+from testtools.matchers import MatchesStructure
+from zope.security.interfaces import Unauthorized
+
from lp.app.enums import InformationType
+from lp.code.enums import (
+ BranchSubscriptionDiffSize,
+ BranchSubscriptionNotificationLevel,
+ CodeReviewNotificationLevel,
+ )
from lp.testing import (
+ BrowserTestCase,
person_logged_in,
TestCaseWithFactory,
)
from lp.testing.layers import DatabaseFunctionalLayer
+from lp.testing.pages import (
+ extract_text,
+ find_tags_by_class,
+ )
from lp.testing.views import create_initialized_view
@@ -31,7 +48,7 @@
'field.actions.subscribe_action': 'Subscribe'}
with person_logged_in(owner):
view = create_initialized_view(
- repository, '+addsubscriber', pricipal=owner, form=form)
+ repository, '+addsubscriber', principal=owner, form=form)
self.assertContentEqual(
['Open and delegated teams cannot be subscribed to private '
'repositories.'], view.errors)
@@ -48,5 +65,128 @@
'field.actions.subscribe_action': 'Subscribe'}
with person_logged_in(owner):
view = create_initialized_view(
- repository, '+addsubscriber', pricipal=owner, form=form)
+ repository, '+addsubscriber', principal=owner, form=form)
self.assertContentEqual([], view.errors)
+
+
+class TestGitSubscriptionAddView(BrowserTestCase):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_requires_login(self):
+ self.useFixture(FakeLogger())
+ repository = self.factory.makeGitRepository()
+ browser = self.getViewBrowser(repository, no_login=True)
+ self.assertRaises(LinkNotFoundError, browser.getLink, 'Subscribe')
+ self.assertRaises(
+ Unauthorized, self.getViewBrowser,
+ repository, view_name='+subscribe', no_login=True)
+
+ def _getSubscribers(self, contents):
+ subscriptions = find_tags_by_class(
+ contents, 'repository-subscribers')[0]
+ for subscriber in subscriptions.findAll('div'):
+ yield extract_text(subscriber.renderContents())
+
+ def _getInformationalMessage(self, contents):
+ message = find_tags_by_class(contents, 'informational message')
+ return extract_text(message[0])
+
+ def test_subscribe(self):
+ subscriber = self.factory.makePerson()
+ repository = self.factory.makeGitRepository()
+ repository.unsubscribe(repository.owner, repository.owner)
+ browser = self.getViewBrowser(repository, user=subscriber)
+ self.assertEqual(
+ ['No subscribers.'], list(self._getSubscribers(browser.contents)))
+ browser.getLink('Subscribe').click()
+ browser.getControl('Notification Level').displayValue = [
+ 'Branch attribute notifications only']
+ browser.getControl('Generated Diff Size Limit').displayValue = [
+ '1000 lines']
+ browser.getControl('Subscribe').click()
+ self.assertTextMatchesExpressionIgnoreWhitespace(
+ 'You have subscribed to this repository with: '
+ 'Only send notifications for branch attribute changes such '
+ 'as name, description and whiteboard. '
+ 'Send email about any code review activity for this branch.',
+ self._getInformationalMessage(browser.contents))
+ with person_logged_in(subscriber):
+ subscription = repository.getSubscription(subscriber)
+ self.assertThat(subscription, MatchesStructure.byEquality(
+ person=subscriber, repository=repository,
+ notification_level=(
+ BranchSubscriptionNotificationLevel.ATTRIBUTEONLY),
+ max_diff_lines=None,
+ review_level=CodeReviewNotificationLevel.FULL))
+
+ def test_already_subscribed(self):
+ repository = self.factory.makeGitRepository()
+ form = {
+ 'field.notification_level': 'NOEMAIL',
+ 'field.max_diff_lines': 'NODIFF',
+ 'field.review_level': 'NOEMAIL',
+ 'field.actions.subscribe': 'Subscribe',
+ }
+ with person_logged_in(repository.owner):
+ view = create_initialized_view(
+ repository, '+subscribe', principal=repository.owner,
+ form=form)
+ self.assertEqual(
+ ['You are already subscribed to this repository.'],
+ [notification.message
+ for notification in view.request.response.notifications])
+
+ def test_edit_subscription(self):
+ subscriber = self.factory.makePerson()
+ repository = self.factory.makeGitRepository()
+ repository.subscribe(
+ subscriber, BranchSubscriptionNotificationLevel.ATTRIBUTEONLY,
+ None, CodeReviewNotificationLevel.FULL, subscriber)
+ browser = self.getViewBrowser(repository, user=subscriber)
+ browser.getLink('Edit your subscription').click()
+ browser.getControl('Notification Level').displayValue = [
+ 'Branch attribute and revision notifications']
+ browser.getControl('Generated Diff Size Limit').displayValue = [
+ '5000 lines']
+ browser.getControl('Change').click()
+ self.assertTextMatchesExpressionIgnoreWhitespace(
+ 'Subscription updated to: '
+ 'Send notifications for both branch attribute updates and new '
+ 'revisions added to the branch. '
+ 'Limit the generated diff to 5000 lines. '
+ 'Send email about any code review activity for this branch.',
+ self._getInformationalMessage(browser.contents))
+ with person_logged_in(subscriber):
+ subscription = repository.getSubscription(subscriber)
+ self.assertThat(subscription, MatchesStructure.byEquality(
+ person=subscriber, repository=repository,
+ notification_level=BranchSubscriptionNotificationLevel.FULL,
+ max_diff_lines=BranchSubscriptionDiffSize.FIVEKLINES,
+ review_level=CodeReviewNotificationLevel.FULL))
+
+ def test_unsubscribe(self):
+ repository = self.factory.makeGitRepository()
+ browser = self.getViewBrowser(repository, user=repository.owner)
+ browser.getLink('Edit your subscription').click()
+ form_url = browser.url
+ browser.getControl('Unsubscribe').click()
+ self.assertEqual(
+ 'You have unsubscribed from this repository.',
+ self._getInformationalMessage(browser.contents))
+ self.assertEqual(
+ ['No subscribers.'], list(self._getSubscribers(browser.contents)))
+ # Going back and then clicking on either Change or Unsubscribe gives
+ # a message that we are not subscribed.
+ browser.addHeader('Referer', 'https://launchpad.dev/')
+ browser.open(
+ form_url, data=urlencode({'field.actions.change': 'Change'}))
+ self.assertEqual(
+ 'You are not subscribed to this repository.',
+ self._getInformationalMessage(browser.contents))
+ browser.open(
+ form_url,
+ data=urlencode({'field.actions.unsubscribe': 'Unsubscribe'}))
+ self.assertEqual(
+ 'You are not subscribed to this repository.',
+ self._getInformationalMessage(browser.contents))
=== modified file 'lib/lp/code/interfaces/gitref.py'
--- lib/lp/code/interfaces/gitref.py 2016-05-28 00:21:40 +0000
+++ lib/lp/code/interfaces/gitref.py 2016-11-09 18:08:56 +0000
@@ -155,6 +155,16 @@
"""Can the specified user see the repository containing this
reference?"""
+ def transitionToInformationType(information_type, user,
+ verify_policy=True):
+ """Set the information type for this reference's repository.
+
+ :param information_type: The `InformationType` to transition to.
+ :param user: The `IPerson` who is making the change.
+ :param verify_policy: Check if the new information type complies
+ with the `IGitNamespacePolicy`.
+ """
+
reviewer = Attribute(
"The person or exclusive team that is responsible for reviewing "
"proposals and merging into this reference.")
@@ -197,6 +207,13 @@
def getSubscription(person):
"""Return the `GitSubscription` for this person."""
+ def unsubscribe(person, unsubscribed_by):
+ """Remove the person's subscription to this reference's repository.
+
+ :param person: The person or team to unsubscribe from the repository.
+ :param unsubscribed_by: The person doing the unsubscribing.
+ """
+
def getNotificationRecipients():
"""Return a complete INotificationRecipientSet instance.
=== modified file 'lib/lp/code/model/gitref.py'
--- lib/lp/code/model/gitref.py 2016-05-28 00:21:40 +0000
+++ lib/lp/code/model/gitref.py 2016-11-09 18:08:56 +0000
@@ -132,6 +132,11 @@
"""See `IGitRef`."""
return self.repository.visibleByUser(user)
+ def transitionToInformationType(self, information_type, user,
+ verify_policy=True):
+ return self.repository.transitionToInformationType(
+ information_type, user, verify_policy=verify_policy)
+
@property
def reviewer(self):
"""See `IGitRef`."""
@@ -173,6 +178,10 @@
"""See `IGitRef`."""
return self.repository.getSubscription(person)
+ def unsubscribe(self, person, unsubscribed_by):
+ """See `IGitRef`."""
+ return self.repository.unsubscribe(person, unsubscribed_by)
+
def getNotificationRecipients(self):
"""See `IGitRef`."""
return self.repository.getNotificationRecipients()
=== modified file 'lib/lp/code/model/tests/test_branchmergeproposal.py'
--- lib/lp/code/model/tests/test_branchmergeproposal.py 2016-09-07 11:12:58 +0000
+++ lib/lp/code/model/tests/test_branchmergeproposal.py 2016-11-09 18:08:56 +0000
@@ -660,7 +660,7 @@
self.mp_two.getPreviewDiff, self.preview_diff.id)
-class TestMergeProposalNotification(TestCaseWithFactory):
+class TestMergeProposalNotificationMixin:
"""Test that events are created when merge proposals are manipulated"""
layer = DatabaseFunctionalLayer
@@ -672,32 +672,29 @@
# When a merge proposal is created needing review, the
# BranchMergeProposalNeedsReviewEvent is raised as well as the usual
# ObjectCreatedEvent.
- source_branch = self.factory.makeProductBranch()
- target_branch = self.factory.makeProductBranch(
- product=source_branch.product)
+ source = self.makeBranch()
+ target = self.makeBranch(same_target_as=source)
registrant = self.factory.makePerson()
result, events = self.assertNotifies(
[ObjectCreatedEvent, BranchMergeProposalNeedsReviewEvent], False,
- source_branch.addLandingTarget, registrant, target_branch,
- needs_review=True)
+ source.addLandingTarget, registrant, target, needs_review=True)
self.assertEqual(result, events[0].object)
def test_notifyOnCreate_work_in_progress(self):
# When a merge proposal is created as work in progress, the
# BranchMergeProposalNeedsReviewEvent is not raised.
- source_branch = self.factory.makeProductBranch()
- target_branch = self.factory.makeProductBranch(
- product=source_branch.product)
+ source = self.makeBranch()
+ target = self.makeBranch(same_target_as=source)
registrant = self.factory.makePerson()
result, events = self.assertNotifies(
[ObjectCreatedEvent], False,
- source_branch.addLandingTarget, registrant, target_branch)
+ source.addLandingTarget, registrant, target)
self.assertEqual(result, events[0].object)
def test_needs_review_from_work_in_progress(self):
# Transitioning from work in progress to needs review raises the
# BranchMergeProposalNeedsReviewEvent event.
- bmp = self.factory.makeBranchMergeProposal(
+ bmp = self.makeBranchMergeProposal(
set_state=BranchMergeProposalStatus.WORK_IN_PROGRESS)
with person_logged_in(bmp.registrant):
self.assertNotifies(
@@ -706,7 +703,7 @@
def test_needs_review_no_op(self):
# Calling needs review when in needs review does not notify.
- bmp = self.factory.makeBranchMergeProposal(
+ bmp = self.makeBranchMergeProposal(
set_state=BranchMergeProposalStatus.NEEDS_REVIEW)
with person_logged_in(bmp.registrant):
self.assertNoNotification(
@@ -714,7 +711,7 @@
def test_needs_review_from_approved(self):
# Calling needs review when approved does not notify either.
- bmp = self.factory.makeBranchMergeProposal(
+ bmp = self.makeBranchMergeProposal(
set_state=BranchMergeProposalStatus.CODE_APPROVED)
with person_logged_in(bmp.registrant):
self.assertNoNotification(
@@ -722,17 +719,17 @@
def test_getNotificationRecipients(self):
"""Ensure that recipients can be added/removed with subscribe"""
- bmp = self.factory.makeBranchMergeProposal()
+ bmp = self.makeBranchMergeProposal()
# Both of the branch owners are now subscribed to their own
# branches with full code review notification level set.
- source_owner = bmp.source_branch.owner
- target_owner = bmp.target_branch.owner
+ source_owner = bmp.merge_source.owner
+ target_owner = bmp.merge_target.owner
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
subscriber_set = set([source_owner, target_owner])
self.assertEqual(subscriber_set, set(recipients.keys()))
source_subscriber = self.factory.makePerson()
- bmp.source_branch.subscribe(
+ bmp.merge_source.subscribe(
source_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL,
@@ -741,7 +738,7 @@
CodeReviewNotificationLevel.STATUS)
subscriber_set.add(source_subscriber)
self.assertEqual(subscriber_set, set(recipients.keys()))
- bmp.source_branch.subscribe(
+ bmp.merge_source.subscribe(
source_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.NOEMAIL,
@@ -754,21 +751,21 @@
def test_getNotificationRecipientLevels(self):
"""Ensure that only recipients with the right level are returned"""
- bmp = self.factory.makeBranchMergeProposal()
+ bmp = self.makeBranchMergeProposal()
full_subscriber = self.factory.makePerson()
- bmp.source_branch.subscribe(full_subscriber,
+ bmp.merge_source.subscribe(full_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL, full_subscriber)
status_subscriber = self.factory.makePerson()
- bmp.source_branch.subscribe(status_subscriber,
+ bmp.merge_source.subscribe(status_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.STATUS, status_subscriber)
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
# Both of the branch owners are now subscribed to their own
# branches with full code review notification level set.
- source_owner = bmp.source_branch.owner
- target_owner = bmp.target_branch.owner
+ source_owner = bmp.merge_source.owner
+ target_owner = bmp.merge_target.owner
self.assertEqual(set([full_subscriber, status_subscriber,
source_owner, target_owner]),
set(recipients.keys()))
@@ -778,27 +775,26 @@
set(recipients.keys()))
def test_getNotificationRecipientsAnyBranch(self):
- prerequisite_branch = self.factory.makeProductBranch()
- bmp = self.factory.makeBranchMergeProposal(
- prerequisite_branch=prerequisite_branch)
+ prerequisite = self.makeBranch()
+ bmp = self.makeBranchMergeProposal(prerequisite=prerequisite)
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.NOEMAIL)
- source_owner = bmp.source_branch.owner
- target_owner = bmp.target_branch.owner
- prerequisite_owner = bmp.prerequisite_branch.owner
+ source_owner = bmp.merge_source.owner
+ target_owner = bmp.merge_target.owner
+ prerequisite_owner = bmp.merge_prerequisite.owner
self.assertEqual(
set([source_owner, target_owner, prerequisite_owner]),
set(recipients.keys()))
source_subscriber = self.factory.makePerson()
- bmp.source_branch.subscribe(source_subscriber,
+ bmp.merge_source.subscribe(source_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL, source_subscriber)
target_subscriber = self.factory.makePerson()
- bmp.target_branch.subscribe(target_subscriber,
+ bmp.merge_target.subscribe(target_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL, target_subscriber)
prerequisite_subscriber = self.factory.makePerson()
- bmp.prerequisite_branch.subscribe(prerequisite_subscriber,
+ bmp.merge_prerequisite.subscribe(prerequisite_subscriber,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL, prerequisite_subscriber)
recipients = bmp.getNotificationRecipients(
@@ -810,11 +806,11 @@
set(recipients.keys()))
def test_getNotificationRecipientsIncludesReviewers(self):
- bmp = self.factory.makeBranchMergeProposal()
+ bmp = self.makeBranchMergeProposal()
# Both of the branch owners are now subscribed to their own
# branches with full code review notification level set.
- source_owner = bmp.source_branch.owner
- target_owner = bmp.target_branch.owner
+ source_owner = bmp.merge_source.owner
+ target_owner = bmp.merge_target.owner
login_person(source_owner)
reviewer = self.factory.makePerson()
bmp.nominateReviewer(reviewer, registrant=source_owner)
@@ -825,11 +821,11 @@
def test_getNotificationRecipientsIncludesTeamReviewers(self):
# If the reviewer is a team, the team gets the email.
- bmp = self.factory.makeBranchMergeProposal()
+ bmp = self.makeBranchMergeProposal()
# Both of the branch owners are now subscribed to their own
# branches with full code review notification level set.
- source_owner = bmp.source_branch.owner
- target_owner = bmp.target_branch.owner
+ source_owner = bmp.merge_source.owner
+ target_owner = bmp.merge_target.owner
login_person(source_owner)
reviewer = self.factory.makeTeam()
bmp.nominateReviewer(reviewer, registrant=source_owner)
@@ -842,9 +838,9 @@
# If the registrant of the proposal is being notified of the
# proposals, they get their rationale set to "Registrant".
registrant = self.factory.makePerson()
- bmp = self.factory.makeBranchMergeProposal(registrant=registrant)
+ bmp = self.makeBranchMergeProposal(registrant=registrant)
# Make sure that the registrant is subscribed.
- bmp.source_branch.subscribe(registrant,
+ bmp.merge_source.subscribe(registrant,
BranchSubscriptionNotificationLevel.NOEMAIL, None,
CodeReviewNotificationLevel.FULL, registrant)
recipients = bmp.getNotificationRecipients(
@@ -852,14 +848,14 @@
reason = recipients[registrant]
self.assertEqual("Registrant", reason.mail_header)
self.assertEqual(
- "You proposed %s for merging." % bmp.source_branch.bzr_identity,
+ "You proposed %s for merging." % bmp.merge_source.identity,
reason.getReason())
def test_getNotificationRecipients_Registrant_not_subscribed(self):
# If the registrant of the proposal is not subscribed, we don't send
# them any email.
registrant = self.factory.makePerson()
- bmp = self.factory.makeBranchMergeProposal(registrant=registrant)
+ bmp = self.makeBranchMergeProposal(registrant=registrant)
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
self.assertFalse(registrant in recipients)
@@ -867,13 +863,13 @@
def test_getNotificationRecipients_Owner(self):
# If the owner of the source branch is subscribed (which is the
# default), then they get a rationale telling them they are the Owner.
- bmp = self.factory.makeBranchMergeProposal()
+ bmp = self.makeBranchMergeProposal()
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
- reason = recipients[bmp.source_branch.owner]
+ reason = recipients[bmp.merge_source.owner]
self.assertEqual("Owner", reason.mail_header)
self.assertEqual(
- "You are the owner of %s." % bmp.source_branch.bzr_identity,
+ "You are the owner of %s." % bmp.merge_source.identity,
reason.getReason())
def test_getNotificationRecipients_team_owner(self):
@@ -881,8 +877,8 @@
# default), but the owner is a team, then none of the headers will say
# Owner.
team = self.factory.makeTeam()
- branch = self.factory.makeProductBranch(owner=team)
- bmp = self.factory.makeBranchMergeProposal(source_branch=branch)
+ branch = self.makeBranch(owner=team)
+ bmp = self.makeBranchMergeProposal(source=branch)
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
headers = set([reason.mail_header for reason in recipients.values()])
@@ -890,10 +886,10 @@
def test_getNotificationRecipients_Owner_not_subscribed(self):
# If the owner of the source branch has unsubscribed themselves, then
- # we don't send them eamil.
- bmp = self.factory.makeBranchMergeProposal()
- owner = bmp.source_branch.owner
- bmp.source_branch.unsubscribe(owner, owner)
+ # we don't send them email.
+ bmp = self.makeBranchMergeProposal()
+ owner = bmp.merge_source.owner
+ bmp.merge_source.unsubscribe(owner, owner)
recipients = bmp.getNotificationRecipients(
CodeReviewNotificationLevel.STATUS)
self.assertFalse(owner in recipients)
@@ -903,10 +899,9 @@
# they do not get email about the proposal.
owner = self.factory.makePerson()
product = self.factory.makeProduct()
- source = self.factory.makeBranch(owner=owner, product=product)
- target = self.factory.makeBranch(owner=owner, product=product)
- bmp = self.factory.makeBranchMergeProposal(
- source_branch=source, target_branch=target)
+ source = self.makeBranch(owner=owner, target=product)
+ target = self.makeBranch(owner=owner, target=product)
+ bmp = self.makeBranchMergeProposal(source=source, target=target)
# Subscribe eric to the source branch only.
eric = self.factory.makePerson()
source.subscribe(
@@ -937,6 +932,38 @@
self.assertIn(charlie, recipients)
+class TestMergeProposalNotificationBzr(
+ TestMergeProposalNotificationMixin, TestCaseWithFactory):
+
+ def makeBranch(self, same_target_as=None, target=None, **kwargs):
+ if same_target_as is not None:
+ kwargs["product"] = same_target_as.product
+ elif target is not None:
+ kwargs["product"] = target
+ return self.factory.makeProductBranch(**kwargs)
+
+ def makeBranchMergeProposal(self, source=None, target=None,
+ prerequisite=None, **kwargs):
+ return self.factory.makeBranchMergeProposal(
+ source_branch=source, target_branch=target,
+ prerequisite_branch=prerequisite, **kwargs)
+
+
+class TestMergeProposalNotificationGit(
+ TestMergeProposalNotificationMixin, TestCaseWithFactory):
+
+ def makeBranch(self, same_target_as=None, **kwargs):
+ if same_target_as is not None:
+ kwargs["target"] = same_target_as.target
+ return self.factory.makeGitRefs(**kwargs)[0]
+
+ def makeBranchMergeProposal(self, source=None, target=None,
+ prerequisite=None, **kwargs):
+ return self.factory.makeBranchMergeProposalForGit(
+ source_ref=source, target_ref=target,
+ prerequisite_ref=prerequisite, **kwargs)
+
+
class TestMergeProposalWebhooksMixin:
layer = DatabaseFunctionalLayer
Follow ups