# HG changeset patch # User Mads Kiilerich # Date 1467211927 -7200 # Node ID f656611798957cfd78c7576fa396befd26643195 # Parent 42d1e1ab41a8df6016615a78be0de2e5d0090467 tests: introduce tests and reference dump for notification mails The mails are dumped to a tracked html file: * changes shows up as diffs and are easy to spot and review * all mails can easily can be investigated in a browser and checked for content and consistency The tests are mocking canonical_url because it has deep dependencies to pylons.url which requires (thread local?) environment setup that the tests doesn't have. diff -r 42d1e1ab41a8 -r f65661179895 kallithea/model/db.py --- a/kallithea/model/db.py Wed Jun 29 16:52:07 2016 +0200 +++ b/kallithea/model/db.py Wed Jun 29 16:52:07 2016 +0200 @@ -2398,7 +2398,7 @@ TYPE_CHANGESET_COMMENT = u'cs_comment' TYPE_MESSAGE = u'message' - TYPE_MENTION = u'mention' + TYPE_MENTION = u'mention' # not used TYPE_REGISTRATION = u'registration' TYPE_PULL_REQUEST = u'pull_request' TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment' diff -r 42d1e1ab41a8 -r f65661179895 kallithea/tests/models/test_dump_html_mails.ref.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kallithea/tests/models/test_dump_html_mails.ref.html Wed Jun 29 16:52:07 2016 +0200 @@ -0,0 +1,629 @@ + + + +

cs_comment, is_mention=False, status_change=None

+
+
+From: u1
+To: u2@example.com
+Subject: [Comment] repo/name changeset cafe on brunch
+
+--------------------
+
+
+Comment from Commenter Name on repo_target changeset c0ffeecafe:
+This is the new comment.
+
+ - and here it ends indented.
+
+
+URL: http://comment.org
+
+Changeset: c0ffeecafe
+Description:
+This changeset did something clever which is hard to explain
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo_target changeset c0ffeecafe:

+

This is the new comment. + + - and here it ends indented.

+ + +

URL: http://comment.org

+ +

Changeset: c0ffeecafe

+

Description:
+This changeset did something clever which is hard to explain +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

cs_comment, is_mention=True, status_change=None

+
+
+From: u1
+To: u2@example.com
+Subject: [Comment] repo/name changeset cafe on brunch
+
+--------------------
+
+
+Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:
+This is the new comment.
+
+ - and here it ends indented.
+
+
+URL: http://comment.org
+
+Changeset: c0ffeecafe
+Description:
+This changeset did something clever which is hard to explain
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:

+

This is the new comment. + + - and here it ends indented.

+ + +

URL: http://comment.org

+ +

Changeset: c0ffeecafe

+

Description:
+This changeset did something clever which is hard to explain +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

cs_comment, is_mention=False, status_change='Approved'

+
+
+From: u1
+To: u2@example.com
+Subject: [Approved: Comment] repo/name changeset cafe on brunch
+
+--------------------
+
+
+Comment from Commenter Name on repo_target changeset c0ffeecafe:
+This is the new comment.
+
+ - and here it ends indented.
+
+The changeset status was changed to: Approved
+
+URL: http://comment.org
+
+Changeset: c0ffeecafe
+Description:
+This changeset did something clever which is hard to explain
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo_target changeset c0ffeecafe:

+

This is the new comment. + + - and here it ends indented.

+ +

The changeset status was changed to: Approved

+ +

URL: http://comment.org

+ +

Changeset: c0ffeecafe

+

Description:
+This changeset did something clever which is hard to explain +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

cs_comment, is_mention=True, status_change='Approved'

+
+
+From: u1
+To: u2@example.com
+Subject: [Approved: Comment] repo/name changeset cafe on brunch
+
+--------------------
+
+
+Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:
+This is the new comment.
+
+ - and here it ends indented.
+
+The changeset status was changed to: Approved
+
+URL: http://comment.org
+
+Changeset: c0ffeecafe
+Description:
+This changeset did something clever which is hard to explain
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:

+

This is the new comment. + + - and here it ends indented.

+ +

The changeset status was changed to: Approved

+ +

URL: http://comment.org

+ +

Changeset: c0ffeecafe

+

Description:
+This changeset did something clever which is hard to explain +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

message

+
+
+From: u1
+To: u2@example.com
+Subject: Test Message
+
+--------------------
+
+
+This is the body of the test message
+ - nothing interesting here except indentation.
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +
This is the body of the test message + - nothing interesting here except indentation.
+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

registration

+
+
+From: u1
+To: u2@example.com
+Subject: New user newbie registered
+
+--------------------
+
+
+Registration body
+
+View this user here: http://newbie.org
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +
Registration body
+ +View this user here: http://newbie.org + + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request, is_mention=False

+
+
+From: u1
+To: u2@example.com
+Subject: [Added] repo/name pull request 7 from ref
+
+--------------------
+
+
+Requester Name requested your review of repo/name pull request "The Title"
+
+URL: http://pr.org
+
+Description:
+This PR is awesome because it does stuff
+ - please approve indented!
+
+Changesets:
+123abc: http://changeset_home/?repo_name=repo_org&revision=123abc
+Introduce one and two
+
+567fed: http://changeset_home/?repo_name=repo_org&revision=567fed
+Make one plus two equal tree
+
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Requester Name requested your review of repo/name pull request "The Title"

+ +

URL: http://pr.org

+ +

Description:

+

This PR is awesome because it does stuff + - please approve indented!

+ +

Changesets:

+

+123abc: +Introduce one and two + +567fed: +Make one plus two equal tree + +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request, is_mention=True

+
+
+From: u1
+To: u2@example.com
+Subject: [Added] repo/name pull request 7 from ref
+
+--------------------
+
+
+Requester Name mentioned you on repo/name pull request "The Title"
+
+URL: http://pr.org
+
+Description:
+This PR is awesome because it does stuff
+ - please approve indented!
+
+Changesets:
+123abc: http://changeset_home/?repo_name=repo_org&revision=123abc
+Introduce one and two
+
+567fed: http://changeset_home/?repo_name=repo_org&revision=567fed
+Make one plus two equal tree
+
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Requester Name mentioned you on repo/name pull request "The Title"

+ +

URL: http://pr.org

+ +

Description:

+

This PR is awesome because it does stuff + - please approve indented!

+ +

Changesets:

+

+123abc: +Introduce one and two + +567fed: +Make one plus two equal tree + +

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request_comment, status_change=None, closing_pr=False

+
+
+From: u1
+To: u2@example.com
+Subject: [Comment] repo/name pull request 7 from ref
+
+--------------------
+
+
+Comment from Commenter Name on repo/name pull request "The Title":
+Me too!
+
+ - and indented on second line
+
+
+URL: http://pr.org/comment
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo/name pull request "The Title":

+

Me too! + + - and indented on second line

+ + +

URL: http://pr.org/comment

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request_comment, status_change='Under Review', closing_pr=False

+
+
+From: u1
+To: u2@example.com
+Subject: [Under Review: Comment] repo/name pull request 7 from ref
+
+--------------------
+
+
+Comment from Commenter Name on repo/name pull request "The Title":
+Me too!
+
+ - and indented on second line
+
+The comment was made with status: Under Review
+
+URL: http://pr.org/comment
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo/name pull request "The Title":

+

Me too! + + - and indented on second line

+ +

The comment was made with status: Under Review

+ +

URL: http://pr.org/comment

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request_comment, status_change=None, closing_pr=True

+
+
+From: u1
+To: u2@example.com
+Subject: [Closing: Comment] repo/name pull request 7 from ref
+
+--------------------
+
+
+Comment from Commenter Name on repo/name pull request "The Title":
+Me too!
+
+ - and indented on second line
+
+
+URL: http://pr.org/comment
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo/name pull request "The Title":

+

Me too! + + - and indented on second line

+ + +

URL: http://pr.org/comment

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

pull_request_comment, status_change='Under Review', closing_pr=True

+
+
+From: u1
+To: u2@example.com
+Subject: [Under Review, Closing: Comment] repo/name pull request 7 from ref
+
+--------------------
+
+
+Comment from Commenter Name on repo/name pull request "The Title":
+Me too!
+
+ - and indented on second line
+
+The comment closed the pull request with status: Under Review
+
+URL: http://pr.org/comment
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Comment from Commenter Name on repo/name pull request "The Title":

+

Me too! + + - and indented on second line

+ +

The comment closed the pull request with status: Under Review

+ +

URL: http://pr.org/comment

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + +

TYPE_PASSWORD_RESET

+
+
+From: u1
+To: john@doe.com
+Subject: Password reset link
+
+--------------------
+
+
+Hello John Doe
+
+We have received a request to reset the password for your account.
+To set a new password, click the following link:
+
+http://reset.com/decbf64715098db5b0bd23eab44bd792670ab746
+
+Should you not be able to use the link above, please type the following code into the password reset form: decbf64715098db5b0bd23eab44bd792670ab746
+
+If it weren't you who requested the password reset, just disregard this message.
+
+
+-- 
+This is an automatic notification. Don't reply to this mail.
+
+--------------------
+ + + +

Hello John Doe

+ +

We have received a request to reset the password for your account.

+

To set a new password, click the following link:

+

http://reset.com/decbf64715098db5b0bd23eab44bd792670ab746

+ +

Should you not be able to use the link above, please type the following code into the password reset form: decbf64715098db5b0bd23eab44bd792670ab746

+ +

If it weren't you who requested the password reset, just disregard this message.

+ + +
+
+--
+This is an automatic notification. Don't reply to this mail. + +
--------------------
+ + diff -r 42d1e1ab41a8 -r f65661179895 kallithea/tests/models/test_notifications.py --- a/kallithea/tests/models/test_notifications.py Wed Jun 29 16:52:07 2016 +0200 +++ b/kallithea/tests/models/test_notifications.py Wed Jun 29 16:52:07 2016 +0200 @@ -1,10 +1,17 @@ +import os + +import mock +import routes.util + from kallithea.tests import * - +from kallithea.lib import helpers as h from kallithea.model.db import User, Notification, UserNotification from kallithea.model.user import UserModel +from kallithea.model.meta import Session +from kallithea.model.notification import NotificationModel, EmailNotificationModel -from kallithea.model.meta import Session -from kallithea.model.notification import NotificationModel +import kallithea.lib.celerylib +import kallithea.lib.celerylib.tasks class TestNotifications(TestController): @@ -38,9 +45,16 @@ def test_create_notification(self): usrs = [self.u1, self.u2] - notification = NotificationModel().create(created_by=self.u1, - subject=u'subj', body=u'hi there', - recipients=usrs) + def send_email(recipients, subject, body='', html_body='', headers=None, author=None): + assert recipients == ['u2@example.com'] + assert subject == 'Test Message' + assert body == "\n\nhi there\n\n\n-- \nThis is an automatic notification. Don't reply to this mail.\n" + assert '>hi there<' in html_body + assert author.username == 'u1' + with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', send_email): + notification = NotificationModel().create(created_by=self.u1, + subject=u'subj', body=u'hi there', + recipients=usrs) Session().commit() u1 = User.get(self.u1) u2 = User.get(self.u2) @@ -149,3 +163,71 @@ assert NotificationModel().get_unread_cnt_for_user(self.u1) == 0 assert NotificationModel().get_unread_cnt_for_user(self.u2) == 1 assert NotificationModel().get_unread_cnt_for_user(self.u3) == 2 + + @mock.patch.object(h, 'canonical_url', (lambda arg, **kwargs: 'http://%s/?%s' % (arg, '&'.join('%s=%s' % (k, v) for (k, v) in sorted(kwargs.items()))))) + def test_dump_html_mails(self): + # Exercise all notification types and dump them to one big html file + l = [] + + def send_email(recipients, subject, body='', html_body='', headers=None, author=None): + l.append('\n\n

%s

\n' % desc) # desc is from outer scope + l.append('
\n\n')
+            l.append('From: %s\n' % author.username)
+            l.append('To: %s\n' % ' '.join(recipients))
+            l.append('Subject: %s\n' % subject)
+            l.append('\n--------------------\n%s\n--------------------' % body)
+            l.append('
\n') + l.append('\n%s\n' % html_body) + l.append('
--------------------
\n') + + l.append('\n') + with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', send_email): + pr_kwargs = dict(pr_nice_id='7', ref='ref', org_repo_name='repo_org', pr_title='The Title', pr_url='http://pr.org') + + for type_, body, kwargs in [ + (Notification.TYPE_CHANGESET_COMMENT, 'This is the new comment.\n\n - and here it ends indented.', dict(short_id='cafe', raw_id='c0ffeecafe', branch='brunch', cs_comment_user='Commenter Name', cs_comment_url='http://comment.org', is_mention=[False, True], message='This changeset did something clever which is hard to explain', status_change=[None, 'Approved'], cs_target_repo='repo_target', cs_url='http://changeset.com')), + (Notification.TYPE_MESSAGE, 'This is the body of the test message\n - nothing interesting here except indentation.', dict()), + #(Notification.TYPE_MENTION, '$body', None), # not used + (Notification.TYPE_REGISTRATION, 'Registration body', dict(new_username='newbie', registered_user_url='http://newbie.org', new_email='new@email.com', new_full_name='New Full Name')), + (Notification.TYPE_PULL_REQUEST, 'This PR is awesome because it does stuff\n - please approve indented!', dict(pr_user_created='Requester Name', is_mention=[False, True], pr_revisions=[('123abc', 'Introduce one and two'), ('567fed', 'Make one plus two equal tree')], **pr_kwargs)), + (Notification.TYPE_PULL_REQUEST_COMMENT, 'Me too!\n\n - and indented on second line', dict(closing_pr=[False, True], pr_comment_user='Commenter Name', pr_comment_url='http://pr.org/comment', status_change=[None, 'Under Review'], pr_target_repo='http://target.com/repo', **pr_kwargs)), + ]: + kwargs['repo_name'] = 'repo/name' + params = [(type_, type_, body, kwargs)] + for param_name in ['is_mention', 'status_change', 'closing_pr']: # TODO: inline/general + if not isinstance(kwargs.get(param_name), list): + continue + new_params = [] + for v in kwargs[param_name]: + for desc, type_, body, kwargs in params: + kwargs = dict(kwargs) + kwargs[param_name] = v + new_params.append(('%s, %s=%r' % (desc, param_name, v), type_, body, kwargs)) + params = new_params + + for desc, type_, body, kwargs in params: + # desc is used as "global" variable + notification = NotificationModel().create(created_by=self.u1, + subject='unused', body=body, email_kwargs=kwargs, + recipients=[self.u2], type_=type_) + + # Email type TYPE_PASSWORD_RESET has no corresponding notification type - test it directly: + desc = 'TYPE_PASSWORD_RESET' + kwargs = dict(user='John Doe', reset_token='decbf64715098db5b0bd23eab44bd792670ab746', reset_url='http://reset.com/decbf64715098db5b0bd23eab44bd792670ab746') + kallithea.lib.celerylib.run_task(kallithea.lib.celerylib.tasks.send_email, ['john@doe.com'], + "Password reset link", + EmailNotificationModel().get_email_tmpl(EmailNotificationModel.TYPE_PASSWORD_RESET, 'txt', **kwargs), + EmailNotificationModel().get_email_tmpl(EmailNotificationModel.TYPE_PASSWORD_RESET, 'html', **kwargs), + author=User.get(self.u1)) + + l.append('\n\n') + out = ''.join(l) + + outfn = os.path.join(os.path.dirname(__file__), 'test_dump_html_mails.out.html') + reffn = os.path.join(os.path.dirname(__file__), 'test_dump_html_mails.ref.html') + with file(outfn, 'w') as f: + f.write(out) + with file(reffn) as f: + ref = f.read() + assert ref == out # copy test_dump_html_mails.out.html to test_dump_html_mails.ref.html to update expectations + os.unlink(outfn)