Browse Source

better test for email

Guénaël Muller 6 years ago
parent
commit
81504d53ba
6 changed files with 242 additions and 8 deletions
  1. 6 0
      .travis.yml
  2. 1 0
      setup.py
  3. 31 0
      tests_configs.ini
  4. 11 0
      tracim/fixtures/content.py
  5. 23 8
      tracim/tests/__init__.py
  6. 170 0
      tracim/tests/functional/test_mail_notification.py

+ 6 - 0
.travis.yml View File

@@ -5,6 +5,12 @@ python:
5 5
   - "3.5"
6 6
   - "3.6"
7 7
 
8
+services:
9
+  - docker
10
+
11
+before_install:
12
+  - docker pull mailhog/mailhog
13
+  - docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog
8 14
 install:
9 15
   - pip install --upgrade pip setuptools
10 16
   - pip install -e ".[testing]"

+ 1 - 0
setup.py View File

@@ -47,6 +47,7 @@ tests_require = [
47 47
     'pytest-cov',
48 48
     'pep8',
49 49
     'mypy',
50
+    'requests'
50 51
 ]
51 52
 
52 53
 mysql_require = [

+ 31 - 0
tests_configs.ini View File

@@ -0,0 +1,31 @@
1
+[base_test]
2
+sqlalchemy.url = sqlite:///:memory:
3
+depot_storage_name = test
4
+depot_storage_dir = /tmp/test/depot
5
+user.auth_token.validity = 604800
6
+preview_cache_dir = /tmp/test/preview_cache
7
+
8
+[mail_test]
9
+sqlalchemy.url = sqlite:///:memory:
10
+depot_storage_name = test
11
+depot_storage_dir = /tmp/test/depot
12
+user.auth_token.validity = 604800
13
+preview_cache_dir = /tmp/test/preview_cache
14
+email.notification.activated = true
15
+email.notification.from.email = test_user_from+{user_id}@localhost
16
+email.notification.from.default_label = Tracim Notifications
17
+email.notification.reply_to.email = test_user_reply+{content_id}@localhost
18
+email.notification.references.email = test_user_refs+{content_id}@localhost
19
+email.notification.content_update.template.html = %(here)s/tracim/templates/mail/content_update_body_html.mak
20
+email.notification.content_update.template.text = %(here)s/tracim/templates/mail/content_update_body_text.mak
21
+email.notification.created_account.template.html = %(here)s/tracim/templates/mail/created_account_body_html.mak
22
+email.notification.created_account.template.text = %(here)s/tracim/templates/mail/created_account_body_text.mak
23
+# Note: items between { and } are variable names. Do not remove / rename them
24
+email.notification.content_update.subject = [{website_title}] [{workspace_label}] {content_label} ({content_status_label})
25
+email.notification.created_account.subject = [{website_title}] Created account
26
+# processing_mode may be sync or async
27
+email.notification.processing_mode = sync
28
+email.notification.smtp.server = 127.0.0.1
29
+email.notification.smtp.port = 1025
30
+email.notification.smtp.user = test_user
31
+email.notification.smtp.password = just_a_password

+ 11 - 0
tracim/fixtures/content.py View File

@@ -58,12 +58,14 @@ class Content(Fixture):
58 58
             workspace=w1,
59 59
             label='w1f1',
60 60
             do_save=True,
61
+            do_notify=False,
61 62
         )
62 63
         w1f2 = content_api.create(
63 64
             content_type=ContentType.Folder,
64 65
             workspace=w1,
65 66
             label='w1f2',
66 67
             do_save=True,
68
+            do_notify=False,
67 69
         )
68 70
 
69 71
         w2f1 = content_api.create(
@@ -71,12 +73,14 @@ class Content(Fixture):
71 73
             workspace=w2,
72 74
             label='w2f1',
73 75
             do_save=True,
76
+            do_notify=False,
74 77
         )
75 78
         w2f2 = content_api.create(
76 79
             content_type=ContentType.Folder,
77 80
             workspace=w2,
78 81
             label='w2f2',
79 82
             do_save=True,
83
+            do_notify=False,
80 84
         )
81 85
 
82 86
         w3f1 = content_api.create(
@@ -84,6 +88,7 @@ class Content(Fixture):
84 88
             workspace=w3,
85 89
             label='w3f3',
86 90
             do_save=True,
91
+            do_notify=False,
87 92
         )
88 93
 
89 94
         # Pages, threads, ..
@@ -93,6 +98,7 @@ class Content(Fixture):
93 98
             parent=w1f1,
94 99
             label='w1f1p1',
95 100
             do_save=True,
101
+            do_notify=False,
96 102
         )
97 103
         w1f1t1 = content_api.create(
98 104
             content_type=ContentType.Thread,
@@ -100,6 +106,7 @@ class Content(Fixture):
100 106
             parent=w1f1,
101 107
             label='w1f1t1',
102 108
             do_save=False,
109
+            do_notify=False,
103 110
         )
104 111
         w1f1t1.description = 'w1f1t1 description'
105 112
         self._session.add(w1f1t1)
@@ -109,6 +116,7 @@ class Content(Fixture):
109 116
             parent=w1f1,
110 117
             label='w1f1d1',
111 118
             do_save=False,
119
+            do_notify=False,
112 120
         )
113 121
         w1f1d1_txt.file_extension = '.txt'
114 122
         w1f1d1_txt.depot_file = FileIntent(
@@ -123,6 +131,7 @@ class Content(Fixture):
123 131
             parent=w1f1,
124 132
             label='w1f1d2',
125 133
             do_save=False,
134
+            do_notify=False,
126 135
         )
127 136
         w1f1d2_html.file_extension = '.html'
128 137
         w1f1d2_html.depot_file = FileIntent(
@@ -137,6 +146,7 @@ class Content(Fixture):
137 146
             label='w1f1f1',
138 147
             parent=w1f1,
139 148
             do_save=True,
149
+            do_notify=False,
140 150
         )
141 151
 
142 152
         w2f1p1 = content_api.create(
@@ -145,5 +155,6 @@ class Content(Fixture):
145 155
             parent=w2f1,
146 156
             label='w2f1p1',
147 157
             do_save=True,
158
+            do_notify=False,
148 159
         )
149 160
         self._session.flush()

+ 23 - 8
tracim/tests/__init__.py View File

@@ -1,5 +1,8 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import unittest
3
+
4
+import plaster
5
+import requests
3 6
 import transaction
4 7
 from depot.manager import DepotManager
5 8
 from pyramid import testing
@@ -92,16 +95,16 @@ class BaseTest(unittest.TestCase):
92 95
     Pyramid default test.
93 96
     """
94 97
 
98
+    config_uri = 'tests_configs.ini'
99
+    config_section = 'base_test'
100
+
95 101
     def setUp(self):
96 102
         logger.debug(self, 'Setup Test...')
97
-        self.config = testing.setUp(settings={
98
-            'sqlalchemy.url': 'sqlite:///:memory:',
99
-            'user.auth_token.validity': '604800',
100
-            'depot_storage_dir': '/tmp/test/depot',
101
-            'depot_storage_name': 'test',
102
-            'preview_cache_dir': '/tmp/test/preview_cache',
103
-
104
-        })
103
+        self.settings = plaster.get_settings(
104
+            self.config_uri,
105
+            self.config_section
106
+        )
107
+        self.config = testing.setUp(settings = self.settings)
105 108
         self.config.include('tracim.models')
106 109
         DepotManager._clear()
107 110
         DepotManager.configure(
@@ -225,3 +228,15 @@ class DefaultTest(StandardTest):
225 228
             owner=user
226 229
         )
227 230
         return thread
231
+
232
+
233
+class MailHogTest(DefaultTest):
234
+    """
235
+    Theses test need a working mailhog
236
+    """
237
+
238
+    config_section = 'mail_test'
239
+
240
+    def tearDown(self):
241
+        logger.debug(self, 'Cleanup MailHog list...')
242
+        requests.delete('http://127.0.0.1:8025/api/v1/messages')

+ 170 - 0
tracim/tests/functional/test_mail_notification.py View File

@@ -0,0 +1,170 @@
1
+# coding=utf-8
2
+# INFO - G.M - 09-06-2018 - Those test need a working MailHog
3
+
4
+from email.mime.multipart import MIMEMultipart
5
+from email.mime.text import MIMEText
6
+
7
+import requests
8
+import transaction
9
+
10
+from tracim.fixtures.users_and_groups import Base as BaseFixture
11
+from tracim.fixtures.content import Content as ContentFixture
12
+from tracim.models.data import ContentType
13
+
14
+from tracim.lib.core.content import ContentApi
15
+from tracim.lib.core.group import GroupApi
16
+from tracim.lib.core.user import UserApi
17
+from tracim.lib.core.userworkspace import RoleApi
18
+from tracim.lib.core.workspace import WorkspaceApi
19
+from tracim.lib.mail_notifier.notifier import EmailManager
20
+from tracim.lib.mail_notifier.sender import EmailSender
21
+from tracim.lib.mail_notifier.utils import SmtpConfiguration
22
+from tracim.models import Group
23
+from tracim.tests import MailHogTest
24
+
25
+
26
+class TestEmailSender(MailHogTest):
27
+
28
+    def test__func__connect_disconnect__ok__nominal_case(self):
29
+        smtp_config = SmtpConfiguration(
30
+            self.app_config.EMAIL_NOTIFICATION_SMTP_SERVER,
31
+            self.app_config.EMAIL_NOTIFICATION_SMTP_PORT,
32
+            self.app_config.EMAIL_NOTIFICATION_SMTP_USER,
33
+            self.app_config.EMAIL_NOTIFICATION_SMTP_PASSWORD
34
+        )
35
+        sender = EmailSender(
36
+            self.app_config,
37
+            smtp_config,
38
+            True,
39
+        )
40
+        sender.connect()
41
+        sender.disconnect()
42
+
43
+    def test__func__send_email__ok__nominal_case(self):
44
+        smtp_config = SmtpConfiguration(
45
+            self.app_config.EMAIL_NOTIFICATION_SMTP_SERVER,
46
+            self.app_config.EMAIL_NOTIFICATION_SMTP_PORT,
47
+            self.app_config.EMAIL_NOTIFICATION_SMTP_USER,
48
+            self.app_config.EMAIL_NOTIFICATION_SMTP_PASSWORD
49
+        )
50
+        sender = EmailSender(
51
+            self.app_config,
52
+            smtp_config,
53
+            True,
54
+        )
55
+
56
+        # Create test_mail
57
+        msg = MIMEMultipart()
58
+        msg['Subject'] = 'test__func__send_email__ok__nominal_case'
59
+        msg['From'] = 'test_send_mail@localhost'
60
+        msg['To'] = 'receiver_test_send_mail@localhost'
61
+        text = "test__func__send_email__ok__nominal_case"
62
+        html = """\
63
+        <html>
64
+          <head></head>
65
+          <body>
66
+            <p>test__func__send_email__ok__nominal_case</p>
67
+          </body>
68
+        </html>
69
+        """.replace(' ', '').replace('\n', '')
70
+        part1 = MIMEText(text, 'plain')
71
+        part2 = MIMEText(html, 'html')
72
+        msg.attach(part1)
73
+        msg.attach(part2)
74
+
75
+        sender.send_mail(msg)
76
+        sender.disconnect()
77
+
78
+        # check mail received
79
+        response = requests.get('http://127.0.0.1:8025/api/v1/messages')
80
+        response = response.json()
81
+        headers = response[0]['Content']['Headers']
82
+        assert headers['From'][0] == 'test_send_mail@localhost'
83
+        assert headers['To'][0] == 'receiver_test_send_mail@localhost'
84
+        assert headers['Subject'][0] == 'test__func__send_email__ok__nominal_case'
85
+        assert response[0]['MIME']['Parts'][0]['Body'] == text
86
+        assert response[0]['MIME']['Parts'][1]['Body'] == html
87
+
88
+
89
+class testUserNotification(MailHogTest):
90
+
91
+    def test_func__create_user_with_mail_notification__ok__nominal_case(self):
92
+        api = UserApi(
93
+            current_user=None,
94
+            session=self.session,
95
+            config=self.app_config,
96
+        )
97
+        u = api.create_user(
98
+            email='bob@bob',
99
+            password='pass',
100
+            name='bob',
101
+            timezone='+2',
102
+            do_save=True,
103
+            do_notify=True,
104
+        )
105
+        assert u is not None
106
+        assert u.email == "bob@bob"
107
+        assert u.validate_password('pass')
108
+        assert u.display_name == 'bob'
109
+        assert u.timezone == '+2'
110
+
111
+        # check mail received
112
+        response = requests.get('http://127.0.0.1:8025/api/v1/messages')
113
+        response = response.json()
114
+        headers = response[0]['Content']['Headers']
115
+        assert headers['From'][0] == 'Tracim Notifications <test_user_from+0@localhost>'
116
+        assert headers['To'][0] == 'bob <bob@bob>'
117
+        assert headers['Subject'][0] == '[TRACIM] Created account'
118
+
119
+
120
+class testContentNotification(MailHogTest):
121
+
122
+    fixtures = [BaseFixture, ContentFixture]
123
+
124
+    def test_func__create_new_content_with_notification__ok__nominal_case(self):
125
+        uapi = UserApi(
126
+            current_user=None,
127
+            session=self.session,
128
+            config=self.app_config,
129
+        )
130
+        current_user = uapi.get_one_by_email('admin@admin.admin')
131
+        # Create new user with notification enabled on w1 workspace
132
+        wapi = WorkspaceApi(
133
+            current_user=current_user,
134
+            session=self.session,
135
+        )
136
+        workspace = wapi.get_one_by_label('w1')
137
+        user = uapi.get_one_by_email('bob@fsf.local')
138
+        wapi.enable_notifications(user, workspace)
139
+
140
+        api = ContentApi(
141
+            current_user=user,
142
+            session=self.session,
143
+            config=self.app_config,
144
+        )
145
+        item = api.create(
146
+            ContentType.Folder,
147
+            workspace,
148
+            None,
149
+            'parent',
150
+            do_save=True,
151
+            do_notify=False,
152
+        )
153
+        item2 = api.create(
154
+            ContentType.File,
155
+            workspace,
156
+            item,
157
+            'file1',
158
+            do_save=True,
159
+            do_notify=True,
160
+        )
161
+
162
+        # check mail received
163
+        response = requests.get('http://127.0.0.1:8025/api/v1/messages')
164
+        response = response.json()
165
+        headers = response[0]['Content']['Headers']
166
+        assert headers['From'][0] == '"Bob i. via Tracim" <test_user_from+3@localhost>'
167
+        assert headers['To'][0] == 'Global manager <admin@admin.admin>'
168
+        assert headers['Subject'][0] == '[TRACIM] [w1] file1 (open)'
169
+        assert headers['References'][0] == 'test_user_refs+13@localhost'
170
+        assert headers['Reply-to'][0] == '"Bob i. & all members of w1" <test_user_reply+13@localhost>'