launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #10207
[Merge] lp:~stevenk/launchpad/bugnotification-testcases into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/bugnotification-testcases into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/bugnotification-testcases/+merge/116402
Clean up tests related to bug notification to prepare for the work that will force structural subscriptions to work with private bugs. I have removed xx-initial-bug-contacts.txt for being a doctest, due to that once the aforementioned structural subscription work lands, it will no longer match reality, and so I can claw back some LoC credit for this branch. I have removed three tests from test_bugnotifications which were frankly horrible, and also won't match reality after the aforementioned work lands.
--
https://code.launchpad.net/~stevenk/launchpad/bugnotification-testcases/+merge/116402
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/bugnotification-testcases into lp:launchpad.
=== removed file 'lib/lp/bugs/stories/initial-bug-contacts/xx-initial-bug-contacts.txt'
--- lib/lp/bugs/stories/initial-bug-contacts/xx-initial-bug-contacts.txt 2012-07-19 15:51:37 +0000
+++ lib/lp/bugs/stories/initial-bug-contacts/xx-initial-bug-contacts.txt 1970-01-01 00:00:00 +0000
@@ -1,237 +0,0 @@
-To set a bug supervisor for a distribution, we need to go to the Bug page
-of that distribution:
-
- >>> browser.open('http://launchpad.dev/ubuntu/+bugs')
-
-But the link is not available if you are not logged in with permission
-to change the bug supervisor.
-
- >>> browser.getLink("Change bug supervisor")
- Traceback (most recent call last):
- ...
- LinkNotFoundError
-
-Colin is an Ubuntu owner and can set the bug supervisor role.
-
- >>> colin_browser = setupBrowser(
- ... auth='Basic colin.watson@xxxxxxxxxxxxxxx:test')
- >>> colin_browser.open('http://bugs.launchpad.dev/ubuntu/+bugs')
-
-...and he can see that the link on Ubuntu's bugs page.
-
- >>> bug_supervisor_link = colin_browser.getLink("Change bug supervisor")
- >>> bug_supervisor_link.url
- 'http://bugs.launchpad.dev/ubuntu/+bugsupervisor'
-
-Anyone with launchpad.Edit permission can edit the distribution bug
-supervisor, but most users can select only themselves and the teams they
-administer. In this example, Colin will set himself as the distribution
-bug supervisor.
-
- >>> bug_supervisor_link.click()
- >>> colin_browser.url
- 'http://bugs.launchpad.dev/ubuntu/+bugsupervisor'
-
-The bug supervisor page takes just one simple value: the bug supervisor email
-or nickname. Let's set colin.watson@xxxxxxxxxxxxxxx as the bug supervisor for
-Ubuntu.
-
- >>> colin_browser.getControl("Bug Supervisor").value = (
- ... ' colin.watson@xxxxxxxxxxxxxxx ')
- >>> colin_browser.getControl("Change").click()
-
-And then Colin is redirected to the distribution bugs page.
-
- >>> print extract_text(find_tag_by_id(
- ... colin_browser.contents, 'bug-supervisor'))
- Bug supervisor: Colin Watson
-
-== Setting Upstream Bug Supervisor ==
-
-Setting the bug supervisor for an upstream requires launchpad.Edit
-permission on the product. But regular users can only appoint
-themselves as bug supervisors and teams they administer.
-
- >>> sample_browser = setupBrowser()
- >>> sample_browser.addHeader("Authorization",
- ... "Basic test@xxxxxxxxxxxxx:test")
-
- >>> sample_browser.open(
- ... "http://bugs.launchpad.dev/firefox/+bugsupervisor")
- >>> sample_browser.getControl(name="field.bug_supervisor").value = (
- ... "test@xxxxxxxxxxxxx")
- >>> sample_browser.getControl("Change").click()
-
-He is now redirected to the main product page, and he sees a confirmation
-message.
-
- >>> print extract_text(find_tag_by_id(
- ... sample_browser.contents, 'bug-supervisor'))
- Bug supervisor: Sample Person
-
-Another example, this time with a team that has no "preferred email" set.
-
- >>> sample_browser.open(
- ... "http://bugs.launchpad.dev/firefox/+bugsupervisor")
- >>> sample_browser.getControl(name="field.bug_supervisor").value = (
- ... "landscape-developers")
- >>> sample_browser.getControl("Change").click()
- >>> print extract_text(find_tag_by_id(
- ... sample_browser.contents, 'bug-supervisor'))
- Bug supervisor: Landscape Developers
-
-Launchpad administrators can appoint anybody.
-
- >>> admin_browser = setupBrowser()
- >>> admin_browser.addHeader("Authorization",
- ... "Basic foo.bar@xxxxxxxxxxxxx:test")
-
- >>> admin_browser.open("http://bugs.launchpad.dev/firefox/+bugsupervisor")
- >>> admin_browser.getControl(name="field.bug_supervisor").value = (
- ... "robertc@xxxxxxxxxxxxxxxxx")
- >>> admin_browser.getControl("Change").click()
- >>> print extract_text(find_tag_by_id(
- ... admin_browser.contents, 'bug-supervisor'))
- Bug supervisor: Robert Collins
-
-Filing a public bug on an upstream will subscribe the bug supervisor, as
-well.
-
- >>> browser.addHeader("Authorization", "Basic mark@xxxxxxxxxxx:test")
-
- >>> browser.open("http://launchpad.dev/firefox/+filebug")
-
- >>> browser.getControl(name="field.title", index=0).value = "bug supervisor test"
- >>> browser.getControl('Continue').click()
-
- >>> browser.getControl(name="field.comment").value = "a public bug"
- >>> browser.getControl("Submit Bug Report").click()
-
- >>> bug_id = browser.url.split("/")[-1]
- >>> print browser.url.replace(bug_id, "BUG-ID")
- http://bugs.launchpad.dev/firefox/+bug/BUG-ID
-
-Now mark (because he's the bug reporter), Sample Person (a former bug
-supervisor), Landscape Developers (another former bug supervisor) and
-Robert Collins (the current bug supervisor) are subscribed to this bug:
-
- >>> from itertools import chain
- >>> from zope.component import getUtility
- >>> from lp.bugs.interfaces.bug import IBugSet
- >>> from lp.testing import login, logout, ANONYMOUS
-
- >>> def subscriber_names(bug):
- ... subscribers = chain(
- ... bug.getDirectSubscribers(),
- ... bug.getIndirectSubscribers())
- ... return sorted(subscriber.displayname for subscriber in subscribers)
-
- >>> login(ANONYMOUS)
- >>> bugset = getUtility(IBugSet)
- >>> subscriber_names(bugset.get(bug_id))
- [u'Landscape Developers', u'Mark Shuttleworth', u'Robert Collins',
- u'Sample Person']
-
-For a security bug, only the reporter and the registrant gets
-subscribed, because Firefox does not have a security contact.
-
- >>> from lp.registry.interfaces.product import IProductSet
-
- >>> login(ANONYMOUS)
- >>> firefox = getUtility(IProductSet).getByName("firefox")
- >>> firefox.security_contact is None
- True
- >>> logout()
-
- >>> browser.open("http://launchpad.dev/firefox/+filebug")
-
- >>> browser.getControl(name="field.title", index=0).value = "bug supervisor test"
- >>> browser.getControl('Continue').click()
-
- >>> browser.getControl(name="field.comment").value = "a PRIVATE bug"
- >>> browser.getControl("Private Security").selected = True
- >>> browser.getControl("Submit Bug Report").click()
-
- >>> other_bug_id = browser.url.split("/")[-1]
- >>> print browser.url.replace(other_bug_id, "BUG-ID")
- http://bugs.launchpad.dev/firefox/+bug/BUG-ID
-
- >>> login("mark@xxxxxxxxxxx")
-
- >>> subscriber_names(bugset.get(other_bug_id))
- [u'Mark Shuttleworth', u'Sample Person']
-
- >>> logout()
-
-Filing a public bug on a distribution source package subscribes the bug
-reporter, the distribution bug supervisor, if there is one, and all the
-package subscribers, if there are any.
-
- >>> browser.addHeader("Authorization", "Basic mark@xxxxxxxxxxx:test")
-
- >>> browser.open(
- ... "http://localhost:9000/ubuntu/+source/mozilla-firefox/"
- ... "+filebug")
-
- >>> browser.getControl(name="field.title", index=0).value = "a public bug"
- >>> browser.getControl('Continue').click()
-
- >>> browser.getControl(name="field.comment").value = (
- ... "anyone can see this")
- >>> browser.getControl("Submit Bug Report").click()
-
- >>> bug_id = browser.url.split("/")[-1]
- >>> print browser.url.replace(bug_id, "BUG-ID")
- http://bugs.launchpad.dev/ubuntu/+source/mozilla-firefox/+bug/BUG-ID
-
-We should have three subscribers now. The bug reporter (also a package
-subscriber), mark, the distro bug supervisor kamion, and foobar, who is
-subscribed to the distribution.
-
- >>> from zope.component import getUtility
- >>> from lp.bugs.interfaces.bug import IBugSet
- >>> from lp.testing import login, logout, ANONYMOUS
-
- >>> def subscriber_names(bug):
- ... subscribers = chain(
- ... bug.getDirectSubscribers(),
- ... bug.getIndirectSubscribers())
- ... return sorted(subscriber.name for subscriber in subscribers)
-
- >>> login(ANONYMOUS)
-
- >>> bugset = getUtility(IBugSet)
- >>> subscriber_names(bugset.get(bug_id))
- [u'kamion', u'mark', u'name16']
-
-
-When filing a security bug, only the bug reporter and registrant are explicitly
-Cc'd, because the Ubuntu distribution does not have a security contact.
-
- >>> from lp.registry.interfaces.distribution import IDistributionSet
-
- >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu")
- >>> ubuntu.security_contact is None
- True
- >>> logout()
-
- >>> browser.open(
- ... "http://localhost:9000/ubuntu/+source/mozilla-firefox/"
- ... "+filebug")
- >>> browser.getControl(name="field.title", index=0).value = "a PRIVATE bug"
- >>> browser.getControl('Continue').click()
-
- >>> browser.getControl(name="field.comment").value = "top sekrit"
- >>> browser.getControl("Private Security").selected = True
- >>> browser.getControl("Submit Bug Report").click()
-
- >>> other_bug_id = browser.url.split("/")[-1]
- >>> print browser.url.replace(other_bug_id, "BUG-ID")
- http://bugs.launchpad.dev/ubuntu/+source/mozilla-firefox/+bug/BUG-ID
-
- >>> login("mark@xxxxxxxxxxx")
-
- >>> subscriber_names(bugset.get(other_bug_id))
- [u'mark', u'ubuntu-team']
-
- >>> logout()
=== added file 'lib/lp/bugs/tests/test_bug_notification_recipients.py'
--- lib/lp/bugs/tests/test_bug_notification_recipients.py 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/tests/test_bug_notification_recipients.py 2012-07-24 05:15:26 +0000
@@ -0,0 +1,156 @@
+# Copyright 2012 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests related to bug notification recipients."""
+
+__metaclass__ = type
+
+from lp.registry.enums import InformationType
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.layers import DatabaseFunctionalLayer
+
+
+class TestBugNotificationRecipients(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_public_bug(self):
+ bug = self.factory.makeBug()
+ self.assertContentEqual(
+ [bug.owner], bug.getBugNotificationRecipients())
+
+ def test_public_bug_with_subscriber(self):
+ bug = self.factory.makeBug()
+ subscriber = self.factory.makePerson()
+ with person_logged_in(bug.owner):
+ bug.subscribe(subscriber, bug.owner)
+ self.assertContentEqual(
+ [bug.owner, subscriber], bug.getBugNotificationRecipients())
+
+ def test_public_bug_with_structural_subscriber(self):
+ subscriber = self.factory.makePerson()
+ product = self.factory.makeProduct()
+ with person_logged_in(subscriber):
+ product.addBugSubscription(subscriber, subscriber)
+ bug = self.factory.makeBug(product=product)
+ self.assertContentEqual(
+ [bug.owner, subscriber], bug.getBugNotificationRecipients())
+
+ def test_public_bug_assignee(self):
+ assignee = self.factory.makePerson()
+ bug = self.factory.makeBug()
+ with person_logged_in(bug.owner):
+ bug.default_bugtask.transitionToAssignee(assignee)
+ self.assertContentEqual(
+ [bug.owner, assignee], bug.getBugNotificationRecipients())
+
+ def test_public_bug_with_duplicate_different_pillar_subscriber(self):
+ subscriber = self.factory.makePerson()
+ bug = self.factory.makeBug()
+ dupe = self.factory.makeBug()
+ with person_logged_in(dupe.owner):
+ dupe.subscribe(subscriber, dupe.owner)
+ dupe.markAsDuplicate(bug)
+ self.assertContentEqual(
+ [bug.owner, dupe.owner, subscriber],
+ bug.getBugNotificationRecipients())
+
+ def test_public_bug_with_duplicate_same_pillar_subscriber(self):
+ owner = self.factory.makePerson()
+ subscriber = self.factory.makePerson()
+ product = self.factory.makeProduct()
+ bug = self.factory.makeBug(product=product, owner=owner)
+ dupe = self.factory.makeBug(product=product, owner=owner)
+ with person_logged_in(owner):
+ dupe.subscribe(subscriber, owner)
+ dupe.markAsDuplicate(bug)
+ self.assertContentEqual(
+ [owner, subscriber], bug.getBugNotificationRecipients())
+
+ def test_public_bug_linked_to_question(self):
+ question = self.factory.makeQuestion()
+ bug = self.factory.makeBug()
+ with person_logged_in(question.owner):
+ question.linkBug(bug)
+ self.assertContentEqual(
+ [bug.owner, question.owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug(self):
+ owner = self.factory.makePerson()
+ bug = self.factory.makeBug(
+ owner=owner, information_type=InformationType.USERDATA)
+ with person_logged_in(owner):
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug_with_subscriber(self):
+ owner = self.factory.makePerson()
+ subscriber = self.factory.makePerson()
+ bug = self.factory.makeBug(
+ owner=owner, information_type=InformationType.USERDATA)
+ with person_logged_in(owner):
+ bug.subscribe(subscriber, owner)
+ self.assertContentEqual(
+ [owner, subscriber], bug.getBugNotificationRecipients())
+
+ def test_private_bug_with_structural_subscriber(self):
+ owner = self.factory.makePerson()
+ subscriber = self.factory.makePerson()
+ product = self.factory.makeProduct()
+ with person_logged_in(subscriber):
+ product.addBugSubscription(subscriber, subscriber)
+ bug = self.factory.makeBug(
+ product=product, owner=owner,
+ information_type=InformationType.USERDATA)
+ with person_logged_in(owner):
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug_assignee(self):
+ owner = self.factory.makePerson()
+ assignee = self.factory.makePerson()
+ bug = self.factory.makeBug(
+ owner=owner, information_type=InformationType.USERDATA)
+ with person_logged_in(owner):
+ bug.default_bugtask.transitionToAssignee(assignee)
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug_with_duplicate_different_pillar_subscriber(self):
+ owner = self.factory.makePerson()
+ subscriber = self.factory.makePerson()
+ bug = self.factory.makeBug(
+ owner=owner, information_type=InformationType.USERDATA)
+ dupe = self.factory.makeBug(owner=owner)
+ with person_logged_in(owner):
+ dupe.subscribe(subscriber, owner)
+ dupe.markAsDuplicate(bug)
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug_with_duplicate_same_pillar_subscriber(self):
+ owner = self.factory.makePerson()
+ subscriber = self.factory.makePerson()
+ product = self.factory.makeProduct()
+ bug = self.factory.makeBug(
+ product=product, owner=owner,
+ information_type=InformationType.USERDATA)
+ dupe = self.factory.makeBug(owner=owner, product=product)
+ with person_logged_in(owner):
+ dupe.subscribe(subscriber, owner)
+ dupe.markAsDuplicate(bug)
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
+
+ def test_private_bug_linked_to_question(self):
+ owner = self.factory.makePerson()
+ question = self.factory.makeQuestion(owner=owner)
+ bug = self.factory.makeBug(
+ owner=owner, information_type=InformationType.USERDATA)
+ with person_logged_in(owner):
+ question.linkBug(bug)
+ self.assertContentEqual(
+ [owner], bug.getBugNotificationRecipients())
=== modified file 'lib/lp/bugs/tests/test_bugnotification.py'
--- lib/lp/bugs/tests/test_bugnotification.py 2012-07-19 04:40:03 +0000
+++ lib/lp/bugs/tests/test_bugnotification.py 2012-07-24 05:15:26 +0000
@@ -7,7 +7,6 @@
from datetime import datetime
from itertools import chain
-import unittest
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.lifecycle.snapshot import Snapshot
@@ -32,90 +31,21 @@
BugNotificationSet,
)
from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilterMute
-from lp.registry.enums import InformationType
from lp.services.config import config
from lp.services.messages.interfaces.message import IMessageSet
from lp.services.messages.model.message import MessageSet
from lp.testing import (
- login,
person_logged_in,
TestCaseWithFactory,
)
from lp.testing.dbuser import switch_dbuser
-from lp.testing.factory import LaunchpadObjectFactory
from lp.testing.layers import (
DatabaseFunctionalLayer,
- LaunchpadFunctionalLayer,
LaunchpadZopelessLayer,
)
from lp.testing.matchers import Contains
-class TestNotificationRecipientsOfPrivateBugs(unittest.TestCase):
- """Test who get notified of changes to private bugs."""
-
- layer = LaunchpadFunctionalLayer
-
- def setUp(self):
- login('foo.bar@xxxxxxxxxxxxx')
- factory = LaunchpadObjectFactory()
- self.product_owner = factory.makePerson(name="product-owner")
- self.product = factory.makeProduct(owner=self.product_owner)
- self.product_subscriber = factory.makePerson(
- name="product-subscriber")
- self.product.addBugSubscription(
- self.product_subscriber, self.product_subscriber)
- self.bug_subscriber = factory.makePerson(name="bug-subscriber")
- self.bug_owner = factory.makePerson(name="bug-owner")
- self.private_bug = factory.makeBug(
- product=self.product, owner=self.bug_owner,
- information_type=InformationType.USERDATA)
- self.reporter = self.private_bug.owner
- self.private_bug.subscribe(self.bug_subscriber, self.reporter)
- [self.product_bugtask] = self.private_bug.bugtasks
- self.direct_subscribers = set(
- person.name for person in [self.bug_subscriber, self.reporter])
-
- def test_status_change(self):
- # Status changes are sent to the direct subscribers only.
- bugtask_before_modification = Snapshot(
- self.product_bugtask, providing=providedBy(self.product_bugtask))
- self.product_bugtask.transitionToStatus(
- BugTaskStatus.INVALID, self.private_bug.owner)
- notify(ObjectModifiedEvent(
- self.product_bugtask, bugtask_before_modification, ['status'],
- user=self.reporter))
- latest_notification = BugNotification.selectFirst(orderBy='-id')
- notified_people = set(
- recipient.person.name
- for recipient in latest_notification.recipients)
- self.assertEqual(self.direct_subscribers, notified_people)
-
- def test_add_comment(self):
- # Comment additions are sent to the direct subscribers only.
- self.private_bug.newMessage(
- self.reporter, subject='subject', content='content')
- latest_notification = BugNotification.selectFirst(orderBy='-id')
- notified_people = set(
- recipient.person.name
- for recipient in latest_notification.recipients)
- self.assertEqual(self.direct_subscribers, notified_people)
-
- def test_bug_edit(self):
- # Bug edits are sent to direct the subscribers only.
- bug_before_modification = Snapshot(
- self.private_bug, providing=providedBy(self.private_bug))
- self.private_bug.description = 'description'
- notify(ObjectModifiedEvent(
- self.private_bug, bug_before_modification, ['description'],
- user=self.reporter))
- latest_notification = BugNotification.selectFirst(orderBy='-id')
- notified_people = set(
- recipient.person.name
- for recipient in latest_notification.recipients)
- self.assertEqual(self.direct_subscribers, notified_people)
-
-
class TestNotificationsSentForBugExpiration(TestCaseWithFactory):
"""Ensure that question subscribers are notified about bug expiration."""
Follow ups