def test_inReplyTo(self): """Ensure that messages are in reply to the root""" bmp, subscriber = self.makeProposalWithSubscriber() bmp.root_message_id = '<root-message-id>' mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertEqual('<root-message-id>', ctrl.headers['In-Reply-To'])
def test_forCreation_without_commit_message(self): """If there is no commit message, email should say 'None Specified.'""" bmp, subscriber = self.makeProposalWithSubscriber() bmp.commit_message = None mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertNotIn('Commit message:', ctrl.body)
def test_forCreation_with_prerequisite_branch(self): """Correctly format list of reviewers.""" bmp, subscriber = self.makeProposalWithSubscriber(prerequisite=True) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) prereq = bmp.prerequisite_branch.bzr_identity self.assertIn(' with %s as a prerequisite.' % prereq, ctrl.body)
def test_forCreation_with_review_request_and_private_bug(self): """Correctly format list of reviewers and bug info. Private bugs should not be listed in the email unless authorised. """ reviewer = self.factory.makePerson(name='review-person') bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer) # Create and subscribe the owner of the private bug private_bug_owner = self.factory.makePerson(email="*****@*****.**") bmp.source_branch.subscribe(private_bug_owner, BranchSubscriptionNotificationLevel.NOEMAIL, None, CodeReviewNotificationLevel.FULL, private_bug_owner) # Create and link the bugs to the branch bug = self.factory.makeBug(title='I am a bug') bugtask = bug.default_bugtask bmp.source_branch.linkBug(bug, bmp.registrant) private_bug = self.factory.makeBug( title='I am a private bug', owner=private_bug_owner, information_type=InformationType.USERDATA) private_bugtask = private_bug.default_bugtask with person_logged_in(private_bug_owner): bmp.source_branch.linkBug(private_bug, bmp.registrant) # Set up the mailer bmp.nominateReviewer(reviewer, bmp.registrant, None) mailer = BMPMailer.forCreation(bmp, bmp.registrant) # A non authorised email recipient doesn't see the private bug. ctrl = mailer.generateEmail('*****@*****.**', subscriber) expected = ( '\nRequested reviews:' '\n Review-person (review-person)' '\nRelated bugs:' '\n %s' '\n %s\n' '\nFor more details, see:\n' '%s' '\n--' % (bugtask.title, canonical_url(bugtask), canonical_url(bmp))) self.assertIn(expected, ctrl.body) # An authorised email recipient does see the private bug. ctrl = mailer.generateEmail('*****@*****.**', private_bug_owner) expected = ( '\nRequested reviews:' '\n Review-person (review-person)' '\nRelated bugs:' '\n %s' '\n %s' '\n %s' '\n %s\n' '\nFor more details, see:\n' '%s' '\n--' % (bugtask.title, canonical_url(bugtask), private_bugtask.title, canonical_url(private_bugtask), canonical_url(bmp))) self.assertIn(expected, ctrl.body)
def test_to_addrs_excludes_people_with_hidden_addresses(self): """The to header excludes those with hidden addresses.""" request, requester = self.makeReviewRequest() request.recipient.hide_email_addresses = True bmp = request.merge_proposal mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail(request.recipient.preferredemail.email, request.recipient) self.assertEqual([bmp.address], ctrl.to_addrs)
def test_generateEmail_no_diff_for_status_only(self): """If the subscription is for status only, don't attach diffs.""" diff_text = ''.join(unified_diff('', 'Fake diff')) bmp, subscriber = self.makeProposalWithSubscriber( diff_text=diff_text) bmp.source_branch.subscribe(subscriber, BranchSubscriptionNotificationLevel.NOEMAIL, None, CodeReviewNotificationLevel.STATUS, subscriber) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertEqual(0, len(ctrl.attachments))
def test_to_addrs_excludes_team_reviewers(self): """Addresses for the to header exclude requested team reviewers.""" bmp, subscriber = self.makeProposalWithSubscriber() team = self.factory.makeTeam(email='*****@*****.**') CodeReviewVoteReference( branch_merge_proposal=bmp, reviewer=team, registrant=subscriber) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail(subscriber.preferredemail.email, subscriber) reviewer = bmp.target_branch.owner reviewer_id = mailer._format_user_address(reviewer) self.assertEqual(set([reviewer_id, bmp.address]), set(ctrl.to_addrs))
def test_forCreation_with_bugs(self): """If there are related bugs, include 'Related bugs'.""" bmp, subscriber = self.makeProposalWithSubscriber() bug = self.factory.makeBug(title='I am a bug') bugtask = bug.default_bugtask bmp.source_branch.linkBug(bug, bmp.registrant) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) expected = ( 'Related bugs:\n' ' %s\n' ' %s\n' % (bugtask.title, canonical_url(bugtask))) self.assertIn(expected, ctrl.body)
def test_to_addrs_includes_reviewers(self): """The addresses for the to header include requested reviewers""" request, requester = self.makeReviewRequest() bmp = request.merge_proposal bmp.source_branch.subscribe( bmp.registrant, BranchSubscriptionNotificationLevel.NOEMAIL, None, CodeReviewNotificationLevel.FULL, bmp.registrant) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail(bmp.registrant.preferredemail.email, bmp.registrant) reviewer = request.recipient reviewer_id = mailer._format_user_address(reviewer) self.assertEqual(set([reviewer_id, bmp.address]), set(ctrl.to_addrs))
def test_forCreation_with_review_request(self): """Correctly format list of reviewers.""" reviewer = self.factory.makePerson(name='review-person') bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer) bmp.nominateReviewer(reviewer, bmp.registrant, None) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertIn( '\nRequested reviews:' '\n Review-person (review-person)\n' '\n' 'For more details, see:\n' '%s\n-- \n' % canonical_url(bmp), ctrl.body)
def test_generateCreationEmail(self): """Ensure that the contents of the mail are as expected""" bmp, subscriber = self.makeProposalWithSubscriber() switch_dbuser(config.IBranchMergeProposalJobSource.dbuser) mailer = BMPMailer.forCreation(bmp, bmp.registrant) assert mailer.message_id is not None, 'Message-id should be set' mailer.message_id = '<foobar-example-com>' reason = mailer._recipients.getReason( subscriber.preferredemail.email)[0] bmp.root_message_id = None ctrl = mailer.generateEmail('*****@*****.**', subscriber) reviewer = bmp.target_branch.owner expected = dedent("""\ Baz Qux has proposed merging %(source)s into %(target)s. Commit message: %(commit_message)s Requested reviews: %(reviewer)s For more details, see: %(bmp)s --\x20 %(reason)s """) % { 'source': bmp.source_branch.bzr_identity, 'target': bmp.target_branch.bzr_identity, 'commit_message': bmp.commit_message, 'reviewer': reviewer.unique_displayname, 'bmp': canonical_url(bmp), 'reason': reason.getReason()} self.assertEqual(expected, ctrl.body) self.assertEqual('[Merge] ' 'lp://dev/~bob/super-product/fix-foo-for-bar into ' 'lp://dev/~mary/super-product/bar', ctrl.subject) self.assertEqual( {'X-Launchpad-Branch': bmp.source_branch.unique_name, 'X-Launchpad-Message-Rationale': 'Subscriber', 'X-Launchpad-Message-For': subscriber.name, 'X-Launchpad-Notification-Type': 'code-review', 'X-Launchpad-Project': bmp.source_branch.product.name, 'Reply-To': bmp.address, 'Message-Id': '<foobar-example-com>'}, ctrl.headers) self.assertEqual('Baz Qux <*****@*****.**>', ctrl.from_addr) reviewer_id = format_address_for_person(reviewer) self.assertEqual(set([reviewer_id, bmp.address]), set(ctrl.to_addrs)) mailer.sendAll()
def test_forCreation_with_review_request(self): """Correctly format list of reviewers.""" reviewer = self.factory.makePerson(name='review-person') bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer) bmp.nominateReviewer(reviewer, bmp.registrant, None) switch_dbuser(config.IBranchMergeProposalJobSource.dbuser) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertIn( '\nRequested reviews:' '\n Review-person (review-person)\n' '\n' 'For more details, see:\n' '%s\n-- \n' % canonical_url(bmp), ctrl.body)
def test_generateCreationEmail(self): """Ensure that the contents of the mail are as expected""" bmp, subscriber = self.makeProposalWithSubscriber() mailer = BMPMailer.forCreation(bmp, bmp.registrant) assert mailer.message_id is not None, 'Message-id should be set' mailer.message_id = '<foobar-example-com>' reason = mailer._recipients.getReason( subscriber.preferredemail.email)[0] bmp.root_message_id = None ctrl = mailer.generateEmail('*****@*****.**', subscriber) reviewer = bmp.target_branch.owner expected = dedent("""\ Baz Qux has proposed merging %(source)s into %(target)s. Commit message: %(commit_message)s Requested reviews: %(reviewer)s For more details, see: %(bmp)s --\x20 %(bmp)s %(reason)s """) % { 'source': bmp.source_branch.bzr_identity, 'target': bmp.target_branch.bzr_identity, 'commit_message': bmp.commit_message, 'reviewer': reviewer.unique_displayname, 'bmp': canonical_url(bmp), 'reason': reason.getReason()} self.assertEqual(expected, ctrl.body) self.assertEqual('[Merge] ' 'lp://dev/~bob/super-product/fix-foo-for-bar into ' 'lp://dev/~mary/super-product/bar', ctrl.subject) self.assertEqual( {'X-Launchpad-Branch': bmp.source_branch.unique_name, 'X-Launchpad-Message-Rationale': 'Subscriber', 'X-Launchpad-Notification-Type': 'code-review', 'X-Launchpad-Project': bmp.source_branch.product.name, 'Reply-To': bmp.address, 'Message-Id': '<foobar-example-com>'}, ctrl.headers) self.assertEqual('Baz Qux <*****@*****.**>', ctrl.from_addr) reviewer_id = mailer._format_user_address(reviewer) self.assertEqual(set([reviewer_id, bmp.address]), set(ctrl.to_addrs)) mailer.sendAll()
def test_generateEmail_attaches_diff_oversize_truncated(self): """An oversized diff will be truncated, and the receiver informed.""" self.pushConfig("diff", max_read_size=25) diff_text = ''.join(unified_diff('', "1234567890" * 10)) bmp, subscriber = self.makeProposalWithSubscriber( diff_text=diff_text) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) (attachment,) = ctrl.attachments self.assertEqual( 'text/x-diff; charset="utf-8"', attachment['Content-Type']) self.assertEqual('inline; filename="review-diff.txt"', attachment['Content-Disposition']) self.assertEqual(diff_text[:25], attachment.get_payload(decode=True)) warning_text = ( "The attached diff has been truncated due to its size.\n") self.assertTrue(warning_text in ctrl.body)
def test_RecordMessageId(self): """Ensure that the contents of the mail are as expected""" bmp, subscriber = self.makeProposalWithSubscriber() mailer = BMPMailer.forCreation(bmp, bmp.registrant) mailer.message_id = '<foobar-example-com>' ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertEqual('<foobar-example-com>', ctrl.headers['Message-Id']) self.assertEqual('Baz Qux <*****@*****.**>', ctrl.from_addr) bmp.root_message_id = None pop_notifications() mailer.sendAll() for notification in pop_notifications(): self.assertEqual('<foobar-example-com>', notification['Message-Id']) self.assertEqual('<foobar-example-com>', bmp.root_message_id) mailer.message_id = '<bazqux-example-com>' mailer.sendAll() self.assertEqual('<foobar-example-com>', bmp.root_message_id)
def test_generateEmail_attaches_diff(self): """A diff should be attached, with the correct metadata. The attached diff should be inline, should have a filename, and should be of type text/x-diff (or text/x-patch), with no declared encoding. (The only encoding in a diff is the encoding of the input files, which may be inconsistent.) """ diff_text = ''.join(unified_diff('', 'Fake diff')) bmp, subscriber = self.makeProposalWithSubscriber( diff_text=diff_text) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) (attachment,) = ctrl.attachments self.assertEqual( 'text/x-diff; charset="utf-8"', attachment['Content-Type']) self.assertEqual('inline; filename="review-diff.txt"', attachment['Content-Disposition']) self.assertEqual(diff_text, attachment.get_payload(decode=True))
def test_forCreation_with_review_request_and_bug(self): """Correctly format list of reviewers and bug info.""" reviewer = self.factory.makePerson(name='review-person') bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer) bug = self.factory.makeBug(title='I am a bug') bugtask = bug.default_bugtask bmp.source_branch.linkBug(bug, bmp.registrant) bmp.nominateReviewer(reviewer, bmp.registrant, None) mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) expected = ( '\nRequested reviews:' '\n Review-person (review-person)' '\nRelated bugs:' '\n %s' '\n %s\n' '\nFor more details, see:\n' '%s' '\n--' % (bugtask.title, canonical_url(bugtask), canonical_url(bmp))) self.assertIn(expected, ctrl.body)
def run(self): """See `IMergeProposalNeedsReviewEmailJob`.""" mailer = BMPMailer.forCreation(self.branch_merge_proposal, self.branch_merge_proposal.registrant) mailer.sendAll()
def test_forCreation_without_bugs(self): """If there are no related bugs, omit 'Related bugs'.""" bmp, subscriber = self.makeProposalWithSubscriber() mailer = BMPMailer.forCreation(bmp, bmp.registrant) ctrl = mailer.generateEmail('*****@*****.**', subscriber) self.assertNotIn('Related bugs:\n', ctrl.body)