Mercurial > kallithea
changeset 5991:f65661179895
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.
author | Mads Kiilerich <madski@unity3d.com> |
---|---|
date | Wed, 29 Jun 2016 16:52:07 +0200 |
parents | 42d1e1ab41a8 |
children | 07b022e6d988 |
files | kallithea/model/db.py kallithea/tests/models/test_dump_html_mails.ref.html kallithea/tests/models/test_notifications.py |
diffstat | 3 files changed, 718 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- 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'
--- /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 @@ +<html><body> + + +<h1>cs_comment, is_mention=False, status_change=None</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo_target changeset c0ffeecafe:</p> +<p><div class="formatted-fixed">This is the new comment. + + - and here it ends indented.</div></p> + + +<p>URL: <a href="http://comment.org">http://comment.org</a></p> + +<p>Changeset: c0ffeecafe</p> +<p>Description:<br/> +This changeset did something clever which is hard to explain +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>cs_comment, is_mention=True, status_change=None</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:</p> +<p><div class="formatted-fixed">This is the new comment. + + - and here it ends indented.</div></p> + + +<p>URL: <a href="http://comment.org">http://comment.org</a></p> + +<p>Changeset: c0ffeecafe</p> +<p>Description:<br/> +This changeset did something clever which is hard to explain +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>cs_comment, is_mention=False, status_change='Approved'</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo_target changeset c0ffeecafe:</p> +<p><div class="formatted-fixed">This is the new comment. + + - and here it ends indented.</div></p> + + <p>The changeset status was changed to: <b>Approved</b></p> + +<p>URL: <a href="http://comment.org">http://comment.org</a></p> + +<p>Changeset: c0ffeecafe</p> +<p>Description:<br/> +This changeset did something clever which is hard to explain +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>cs_comment, is_mention=True, status_change='Approved'</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo_target changeset c0ffeecafe mentioned you:</p> +<p><div class="formatted-fixed">This is the new comment. + + - and here it ends indented.</div></p> + + <p>The changeset status was changed to: <b>Approved</b></p> + +<p>URL: <a href="http://comment.org">http://comment.org</a></p> + +<p>Changeset: c0ffeecafe</p> +<p>Description:<br/> +This changeset did something clever which is hard to explain +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>message</h1> +<pre> + +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. + +--------------------</pre> + + + +<div class="formatted-fixed">This is the body of the test message + - nothing interesting here except indentation.</div> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>registration</h1> +<pre> + +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. + +--------------------</pre> + + + +<div class="formatted-fixed">Registration body</div> + +View this user here: <a href="http://newbie.org">http://newbie.org</a> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request, is_mention=False</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Requester Name requested your review of repo/name pull request "The Title"</p> + +<p>URL: <a href="http://pr.org">http://pr.org</a></p> + +<p>Description:</p> +<p style="white-space: pre-wrap; font-family: monospace"><div class="formatted-fixed">This PR is awesome because it does stuff + - please approve indented!</div></p> + +<p>Changesets:</p> +<p style="white-space: pre-wrap"> +<i><a href="http://changeset_home/?repo_name=repo_org&revision=123abc">123abc</a></i>: +Introduce one and two + +<i><a href="http://changeset_home/?repo_name=repo_org&revision=567fed">567fed</a></i>: +Make one plus two equal tree + +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request, is_mention=True</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Requester Name mentioned you on repo/name pull request "The Title"</p> + +<p>URL: <a href="http://pr.org">http://pr.org</a></p> + +<p>Description:</p> +<p style="white-space: pre-wrap; font-family: monospace"><div class="formatted-fixed">This PR is awesome because it does stuff + - please approve indented!</div></p> + +<p>Changesets:</p> +<p style="white-space: pre-wrap"> +<i><a href="http://changeset_home/?repo_name=repo_org&revision=123abc">123abc</a></i>: +Introduce one and two + +<i><a href="http://changeset_home/?repo_name=repo_org&revision=567fed">567fed</a></i>: +Make one plus two equal tree + +</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request_comment, status_change=None, closing_pr=False</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo/name pull request "The Title":</p> +<p><div class="formatted-fixed">Me too! + + - and indented on second line</div></p> + + +<p>URL: <a href="http://pr.org/comment">http://pr.org/comment</a></p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request_comment, status_change='Under Review', closing_pr=False</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo/name pull request "The Title":</p> +<p><div class="formatted-fixed">Me too! + + - and indented on second line</div></p> + + <p>The comment was made with status: <b>Under Review</b></p> + +<p>URL: <a href="http://pr.org/comment">http://pr.org/comment</a></p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request_comment, status_change=None, closing_pr=True</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo/name pull request "The Title":</p> +<p><div class="formatted-fixed">Me too! + + - and indented on second line</div></p> + + +<p>URL: <a href="http://pr.org/comment">http://pr.org/comment</a></p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>pull_request_comment, status_change='Under Review', closing_pr=True</h1> +<pre> + +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. + +--------------------</pre> + + + +<p>Comment from Commenter Name on repo/name pull request "The Title":</p> +<p><div class="formatted-fixed">Me too! + + - and indented on second line</div></p> + + <p>The comment closed the pull request with status: <b>Under Review</b></p> + +<p>URL: <a href="http://pr.org/comment">http://pr.org/comment</a></p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + + +<h1>TYPE_PASSWORD_RESET</h1> +<pre> + +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. + +--------------------</pre> + + + +<h4>Hello John Doe</h4> + +<p>We have received a request to reset the password for your account.</p> +<p>To set a new password, click the following link:</p> +<p><a href="http://reset.com/decbf64715098db5b0bd23eab44bd792670ab746">http://reset.com/decbf64715098db5b0bd23eab44bd792670ab746</a></p> + +<p>Should you not be able to use the link above, please type the following code into the password reset form: <code>decbf64715098db5b0bd23eab44bd792670ab746</code></p> + +<p>If it weren't you who requested the password reset, just disregard this message.</p> + + +<br/> +<br/> +-- <br/> +This is an automatic notification. Don't reply to this mail. + +<pre>--------------------</pre> + +</body></html>
--- 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<h1>%s</h1>\n' % desc) # desc is from outer scope + l.append('<pre>\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('</pre>\n') + l.append('\n%s\n' % html_body) + l.append('<pre>--------------------</pre>\n') + + l.append('<html><body>\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</body></html>\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)