Browse Source

better test for email

Guénaël Muller 6 years ago
parent
commit
81504d53ba

+ 6 - 0
.travis.yml View File

5
   - "3.5"
5
   - "3.5"
6
   - "3.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
 install:
14
 install:
9
   - pip install --upgrade pip setuptools
15
   - pip install --upgrade pip setuptools
10
   - pip install -e ".[testing]"
16
   - pip install -e ".[testing]"

+ 1 - 0
setup.py View File

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

+ 31 - 0
tests_configs.ini View File

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

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

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 import unittest
2
 import unittest
3
+
4
+import plaster
5
+import requests
3
 import transaction
6
 import transaction
4
 from depot.manager import DepotManager
7
 from depot.manager import DepotManager
5
 from pyramid import testing
8
 from pyramid import testing
92
     Pyramid default test.
95
     Pyramid default test.
93
     """
96
     """
94
 
97
 
98
+    config_uri = 'tests_configs.ini'
99
+    config_section = 'base_test'
100
+
95
     def setUp(self):
101
     def setUp(self):
96
         logger.debug(self, 'Setup Test...')
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
         self.config.include('tracim.models')
108
         self.config.include('tracim.models')
106
         DepotManager._clear()
109
         DepotManager._clear()
107
         DepotManager.configure(
110
         DepotManager.configure(
225
             owner=user
228
             owner=user
226
         )
229
         )
227
         return thread
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

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>'