Prepare for 1.3.3 release.
[mailman-postorious.git] / src / postorius / tests / test_list_forms.py
blob940ac4d175807ff225341291395f3ae9b691674a
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2017-2019 by the Free Software Foundation, Inc.
4 # This file is part of Postorius.
6 # Postorius is free software: you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free
8 # Software Foundation, either version 3 of the License, or (at your option)
9 # any later version.
11 # Postorius is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 # more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Postorius. If not, see <http://www.gnu.org/licenses/>.
19 import unittest
21 from django.test import TestCase
23 from postorius.forms.list_forms import (
24 ArchiveSettingsForm, ChangeSubscriptionForm, DigestSettingsForm,
25 DMARCMitigationsForm, ListAnonymousSubscribe, ListAutomaticResponsesForm,
26 ListHeaderMatchForm, ListIdentityForm, ListMassRemoval,
27 ListMassSubscription, ListNew, ListSubscribe, MemberModeration,
28 MemberPolicyForm, MessageAcceptanceForm)
29 from postorius.forms.system import AddBanForm
30 from postorius.tests.utils import create_mock_list
33 class TestListSubscribe(TestCase):
35 def test_required_fields_only(self):
36 user_emails = ['bob@example.com', 'anne@example.com']
37 form = ListSubscribe(user_emails, dict(email='bob@example.com'))
38 self.assertTrue(form.is_valid())
40 def test_email_is_only_from_choices(self):
41 user_emails = ['bob@example.com', 'anne@example.com']
42 form = ListSubscribe(user_emails, dict(email='alice@example.com',
43 display_name='Alice'))
44 self.assertFalse(form.is_valid())
45 self.assertTrue('email' in form.errors)
46 self.assertTrue('Select a valid choice.' in form.errors['email'][0])
48 def test_subscribe_works(self):
49 user_emails = ['someone@example.com']
50 form = ListSubscribe(user_emails,
51 {'email': 'someone@example.com',
52 'display_name': 'Someone'})
53 self.assertTrue(form.is_valid())
55 def test_subscribe_fails(self):
56 user_emails = ['someone@example.com']
57 form = ListSubscribe(user_emails,
58 {'email': 'notaemail',
59 'display_name': 'Someone'})
60 self.assertFalse(form.is_valid())
61 self.assertTrue('email' in form.errors.keys())
62 self.assertEqual(form.errors['email'][0],
63 'Select a valid choice.'
64 ' notaemail is not one of the available choices.')
66 def test_subscribe_validates_email(self):
67 user_emails = ['something']
68 form = ListSubscribe(user_emails,
69 {'email': 'something',
70 'display_name': 'Someone'})
71 self.assertFalse(form.is_valid())
72 self.assertTrue('email' in form.errors.keys())
73 self.assertEqual(form.errors['email'][0],
74 'Please enter a valid email address.')
77 class TestChangeSubscription(TestCase):
79 def test_subscription_changes_only_to_user_addresses(self):
80 user_emails = ['one@example.com', 'two@example.com']
81 form = ChangeSubscriptionForm(user_emails, {'email': 'abcd@d.com'})
82 self.assertFalse(form.is_valid())
83 self.assertTrue('email' in form.errors.keys())
84 self.assertEqual(form.errors['email'][0],
85 'Select a valid choice. '
86 'abcd@d.com is not one of the available choices.')
88 def test_subscription_works(self):
89 user_emails = ['one@example.com', 'two@example.com']
90 form = ChangeSubscriptionForm(user_emails,
91 {'email': 'two@example.com'})
92 self.assertTrue(form.is_valid())
94 def test_subscription_form_labels(self):
95 user_emails = ['one@example.com', 'two@example.com']
96 form = ChangeSubscriptionForm(user_emails, {})
97 self.assertTrue(form.is_valid())
98 self.assertEqual(form.fields['email'].label, 'Select Email')
100 def test_form_validity(self):
101 form = ChangeSubscriptionForm(
102 ['email@example.com', 'john@example.com', 'doe@example.com'],
103 {'email': 'email@example.com'})
104 self.assertTrue(form.is_valid())
106 def test_required_fields(self):
107 # There is no required fields, so empty form should be valid.
108 form = ChangeSubscriptionForm(
109 ['email@example.com', 'john@example.com', 'doe@example.com'],
111 self.assertTrue(form.is_valid())
114 class TestListNew(TestCase):
116 def test_form_fields_list(self):
117 domain_choices = [
118 ("mailman.most-desirable.org", "mailman.most-desirable.org")]
119 style_choices = [
120 ("legacy-default", 'Ordinary discussion mailing list style.'),
121 ("legacy-announce", 'Announce only mailing list style.')]
122 form = ListNew(domain_choices, style_choices,
123 {'listname': 'xyz',
124 'mail_host': 'mailman.most-desirable.org',
125 'list_owner': 'contact@mailman.most-desirable.org',
126 'advertised': 'True',
127 'list_style': 'legacy-default',
128 'description': 'The Most Desirable organization'})
129 self.assertTrue(form.is_valid(), form.errors)
131 def test_form_fields_list_invalid(self):
132 domain_choices = [
133 ("mailman.most-desirable.org", "mailman.most-desirable.org")]
134 style_choices = [
135 ("legacy-default", 'Ordinary discussion mailing list style.'),
136 ("legacy-announce", 'Announce only mailing list style.')]
137 form = ListNew(domain_choices, style_choices,
138 {'listname': 'xy#z',
139 'mail_host': 'mailman.most-desirable.org',
140 'list_owner': 'mailman.most-desirable.org',
141 'advertised': 'abcd',
142 'list_style': 'defg',
143 'description': 'The Most Desirable organization'})
144 self.assertFalse(form.is_valid())
145 # Test that all invalid fields are actually checked.
146 for field in ('list_owner', 'advertised'):
147 self.assertTrue(field in form.errors)
148 self.assertTrue('Enter a valid email address.' in
149 form.errors['list_owner'])
150 self.assertTrue(
151 'Select a valid choice. abcd is not one of the available choices.'
152 in form.errors['advertised'])
154 def test_form_without_domain_choices(self):
155 form = ListNew([],
156 {'listname': 'xyz',
157 'mail_host': 'mailman.most-desirable.org',
158 'list_owner': 'contact@mailman.most-desirable.org',
159 'advertised': 'True',
160 'description': 'The Most Desirable organization', })
161 # Without domain choices, the form is not going to be valid.
162 self.assertFalse(form.is_valid())
163 self.assertTrue(form.fields['mail_host'].help_text == # noqa: W504
164 'Site admin has not created any domains')
166 def test_listname_validation(self):
167 domain_choices = [
168 ("mailman.most-desirable.org", "mailman.most-desirable.org")]
169 style_choices = [
170 ("legacy-default", 'Ordinary discussion mailing list style.'),
171 ("legacy-announce", 'Announce only mailing list style.')]
172 form = ListNew(domain_choices, style_choices,
173 {'listname': 'xy@z',
174 'mail_host': 'mailman.most-desirable.org',
175 'list_owner': 'mailman.most-desirable.org',
176 'advertised': 'abcd',
177 'description': 'The Most Desirable organization', })
178 self.assertFalse(form.is_valid())
179 self.assertTrue('listname' in form.errors)
180 self.assertTrue('Please enter a valid listname' in
181 form.errors['listname'])
183 @unittest.expectedFailure
184 def test_listname_validation_errors_sane(self):
185 # This test is going to fail right now, but needs to be fixed.
186 form = ListNew([
187 ("mailman.most-desirable.org", "mailman.most-desirable.org")],
188 {'listname': 'xy#z',
189 'mail_host': 'mailman.most-desirable.org',
190 'list_owner': 'mailman.most-desirable.org',
191 'advertised': 'abcd',
192 'description': 'The Most Desirable organization', })
193 self.assertFalse(form.is_valid())
194 self.assertTrue('listname' in form.errors)
195 self.assertEqual(
196 'Please enter a valid listname, "@" is not allowed in listname',
197 form.errors['listname'])
199 def test_form_fields_order(self):
200 domain_choices = [
201 ("mailman.most-desirable.org", "mailman.most-desirable.org")]
202 style_choices = [
203 ("legacy-default", 'Ordinary discussion mailing list style.'),
204 ("legacy-announce", 'Announce only mailing list style.')]
205 form = ListNew(domain_choices, style_choices,
206 {'listname': 'xyz',
207 'mail_host': 'mailman.most-desirable.org',
208 'list_owner': 'mailman@most-desirable.org',
209 'list_style': 'legacy-default',
210 'advertised': 'True',
211 'description': 'The Most Desirable organization', })
212 self.assertTrue(form.is_valid())
213 # The order of the fields should remain exactly like this.
214 self.assertEqual(list(form.fields),
215 ['listname',
216 'mail_host',
217 'list_owner',
218 'advertised',
219 'list_style',
220 'description'])
223 class TestListIdentityForm(TestCase):
225 def test_not_required_fields(self):
226 # Only advertised is the required form field.
227 form = ListIdentityForm({
228 'advertised': 'True',
229 }, mlist=None)
230 self.assertTrue(form.is_valid(), form.errors)
232 def test_field_validations(self):
233 form = ListIdentityForm({
234 'advertised': 'abcd',
235 'description': 'This is the most desirable organization',
236 'info': 'This is a larger description of this mailing list.',
237 'display_name': 'Most Desirable Mailing List',
238 'subject_prefix': ' [Most Desirable] ',
239 'preferred_language': 'en',
240 'member_roster_visibility': 'public',
241 }, mlist=None)
242 self.assertFalse(form.is_valid())
243 self.assertTrue('advertised' in form.errors)
244 self.assertEqual(['Select a valid choice. abcd is not one of the available choices.'], # noqa
245 form.errors['advertised'])
246 # We shouldn't be removing trailing whitespaces, but we
247 # should remove the leading ones.
248 self.assertEqual(form.cleaned_data['subject_prefix'],
249 '[Most Desirable] ')
252 class TestListMassSubscription(TestCase):
254 def test_all_valid_email_formats(self):
255 form = ListMassSubscription({
256 'emails': '''
257 jdoe@example.com
258 <jdoe@example.com>
259 John Doe <jdoe@example.com>
260 "John Doe" <jdoe@example.com>
261 jdoe@example.com (John Doe)'''})
262 self.assertTrue(form.is_valid())
264 def test_required_fields(self):
265 form = ListMassSubscription({'email': ' '})
266 self.assertFalse(form.is_valid())
267 self.assertEqual(['This field is required.'],
268 form.errors['emails'])
269 form = ListMassSubscription({'email': '----'})
270 self.assertFalse(form.is_valid())
271 self.assertEqual(['This field is required.'],
272 form.errors['emails'])
275 class TestListMassRemoval(TestCase):
277 def test_all_valid_formats(self):
278 form = ListMassRemoval({
279 'emails': '''
280 jdoe@example.com
281 <jdoe@example.com>
282 John Doe <jdoe@example.com>
283 "John Doe" <jdoe@example.com>
284 jdoe@example.com (John Doe)'''})
285 self.assertTrue(form.is_valid())
288 class TestAddBanForm(TestCase):
290 def test_form_validity(self):
291 form = AddBanForm({'email': 'jdoe@example.com'})
292 self.assertTrue(form.is_valid())
294 def test_missing_fields_errors(self):
295 form = AddBanForm({})
296 self.assertFalse(form.is_valid())
297 self.assertTrue('email' in form.errors)
298 self.assertEqual(form.errors['email'],
299 ['Please enter an email address.'])
301 @unittest.expectedFailure
302 def test_invalid_fields_type(self):
303 # Valid values for email is either a regexp or an email address.
304 # However, this is currently not validated by the form.
305 form = AddBanForm({'email': 'invalid@'})
306 self.assertFalse(form.is_valid())
307 self.assertTrue('email' in form.errors)
308 self.assertEqual(form.errors['email'],
309 ['Please enter a valid email address.'])
312 class TestListHeaderMatchForm(TestCase):
314 def test_form_validity(self):
315 # Test by putting only required fields.
316 form = ListHeaderMatchForm({
317 'header': 'To',
318 'pattern': 'value@example.com'})
319 self.assertTrue(form.is_valid())
320 # Test all fileds.
321 form = ListHeaderMatchForm({
322 'header': 'To',
323 'pattern': 'value@example.com',
324 'action': 'accept'})
325 self.assertTrue(form.is_valid())
326 # Defer is not a valid action, so validation should fail here.
327 form = ListHeaderMatchForm({
328 'header': 'To',
329 'pattern': 'value@example.com',
330 'action': 'defer'})
331 self.assertFalse(form.is_valid())
332 self.assertTrue('action' in form.errors)
335 class TestMemberModeration(TestCase):
337 def test_moderation_action_validity(self):
338 form = MemberModeration({'moderation_action': 'moderation'})
339 self.assertFalse(form.is_valid())
340 self.assertTrue('moderation_action' in form.errors)
341 self.assertEqual(form.errors['moderation_action'],
342 ['Select a valid choice. moderation is not one of the available choices.']) # noqa
344 def test_required_fields(self):
345 form = MemberModeration({})
346 self.assertTrue(form.is_valid())
349 class TestListAutomaticResponsesForm(TestCase):
351 fields = ('autorespond_owner', 'autoresponse_owner_text',
352 'autorespond_postings', 'autoresponse_postings_text',
353 'autorespond_requests', 'autoresponse_request_text',
354 'autoresponse_grace_period', 'send_welcome_message',
355 'welcome_message_uri', 'goodbye_message_uri',
356 'admin_immed_notify', 'admin_notify_mchanges')
358 def prepare_formdata(self, values):
359 return dict(((key, val) for key, val in zip(self.fields, values) if val is not None)) # noqa
361 def test_required_fields_only(self):
362 values = ('respond_and_continue', None,
363 'respond_and_continue', None,
364 'respond_and_continue', None,
365 '2', None,
366 None, None,
367 None, None)
368 formdata = self.prepare_formdata(values)
369 form = ListAutomaticResponsesForm(formdata, mlist=None)
370 self.assertTrue(form.is_valid())
372 def test_all_values(self):
373 values = ('respond_and_continue', 'Autorespond text',
374 'respond_and_continue', 'Autorespond text',
375 'respond_and_continue', 'Autorespond text',
376 '2', 'True',
377 'http://example.com/welcome_text',
378 'http://example.com/goodbye_message',
379 'True', 'False')
380 formdata = self.prepare_formdata(values)
381 form = ListAutomaticResponsesForm(formdata, mlist=None)
382 print(form.errors)
383 self.assertTrue(form.is_valid())
386 class TestAlterMessageForm(TestCase):
388 fields = ('filter_content', 'collapse_alternatives',
389 'convert_html_to_plaintext', 'anonymous_list',
390 'include_rfc2369_headers', 'allow_list_posts',
391 'reply_list_posts', 'reply_to_address',
392 'first_strip_reply_to', 'reply_goes_to_list',
393 'posting_pipeline')
395 def prepare_formdata(self, values):
396 return dict(((key, val) for key, val in zip(self.fields, values) if val is not None)) # noqa
399 class TestDMARCMitigationsForm(TestCase):
401 def test_required_fields(self):
402 # All fields in the form are optional, so an empty form should be
403 # valid.
404 form = DMARCMitigationsForm({}, mlist=None)
405 self.assertTrue(form.is_valid())
407 def test_all_fields(self):
408 formdata = dict(
409 dmarc_mitigate_action='munge_from',
410 dmarc_mitigate_unconditionally='True',
411 dmarc_moderation_notice='This is a moderation notice',
412 dmarc_wrapped_message_text='This is wrapped message text')
413 form = DMARCMitigationsForm(formdata, mlist=None)
414 self.assertTrue(form.is_valid())
417 class TestDigestSettingsForm(TestCase):
419 def test_required_fields(self):
420 form = DigestSettingsForm({}, mlist=None)
421 self.assertFalse(form.is_valid())
422 self.assertTrue('digest_size_threshold' in form.errors)
423 self.assertEqual(form.errors['digest_size_threshold'],
424 ['This field is required.'])
425 form = DigestSettingsForm({'digest_size_threshold': 40}, mlist=None)
426 self.assertTrue(form.is_valid())
428 def test_all_fields(self):
429 formdata = dict(
430 digests_enabled='True',
431 digests_send_periodic='True',
432 digests_volume_frequency='daily',
433 digest_size_threshold='10',
435 form = DigestSettingsForm(formdata, mlist=None)
436 self.assertTrue(form.is_valid())
439 class TestMessageAcceptanceForm(TestCase):
441 fields = ('acceptable_aliases', 'require_explicit_destination',
442 'administrivia', 'default_member_action',
443 'default_nonmember_action', 'max_message_size',
444 'max_num_recipients')
446 def prepare_formdata(self, values):
447 return dict(((key, val) for key, val in zip(self.fields, values) if val is not None)) # noqa
449 def test_required_fields(self):
450 # Without any fields, form should not be valid.
451 form = MessageAcceptanceForm({}, mlist=None)
452 self.assertFalse(form.is_valid())
453 # Now lets try with only required fields.
454 values = (None, None, None, 'hold', 'hold', 40, 100)
455 form = MessageAcceptanceForm(self.prepare_formdata(values), mlist=None)
456 print(form.errors)
457 self.assertTrue(form.is_valid())
459 def test_all_fields(self):
460 pass
463 class TestArchiveSettingsForm(TestCase):
465 def setUp(self):
466 self.mlist = create_mock_list()
467 archivers = {'pipermail': True, 'hyperkitty': True}
468 self.mlist.archivers.keys.side_effect = archivers.keys
469 self.mlist.archivers.__getitem__.side_effect = archivers.__getitem__
470 self.mlist.archivers.__iter__.side_effect = archivers.__iter__
471 self.mlist.archivers.__contains__.side_effect = archivers.__contains__
473 def test_required_fields(self):
474 # First try without any fields.
475 form = ArchiveSettingsForm({}, mlist=self.mlist)
476 self.assertFalse(form.is_valid())
477 self.assertTrue('archive_policy' in form.errors)
478 # Now, with only required fields, this should be a valid form.
479 form = ArchiveSettingsForm(dict(archive_policy='public'),
480 mlist=self.mlist)
481 self.assertTrue(form.is_valid())
483 def test_all_fields(self):
484 formdata = dict(archive_policy='public',
485 archivers=['pipermail', 'hyperkitty'])
486 form = ArchiveSettingsForm(formdata, mlist=self.mlist)
487 self.assertTrue(form.is_valid())
489 def test_setup_archivers_populated(self):
490 formdata = dict(archive_policy='public',
491 archivers=['pipermail', 'hyperkitty'])
492 form = ArchiveSettingsForm(formdata, mlist=self.mlist,
493 initial={'archivers': None})
494 self.assertTrue(form.is_valid())
495 self.assertEqual(form.initial['archivers'],
496 ['hyperkitty', 'pipermail'])
499 class TestMemberPolicyForm(TestCase):
501 def test_required_fields(self):
502 form = MemberPolicyForm({}, mlist=None)
503 self.assertFalse(form.is_valid())
504 self.assertTrue('subscription_policy' in form.errors)
505 self.assertTrue('unsubscription_policy' in form.errors)
506 form = MemberPolicyForm(
507 dict(subscription_policy='confirm',
508 unsubscription_policy='confirm'),
509 mlist=None)
510 self.assertTrue(form.is_valid())
513 class TestListAnonymousSubscribe(TestCase):
515 def test_required_fields_only(self):
516 form = ListAnonymousSubscribe(dict(email='bob@exmaple.com'))
517 self.assertTrue(form.is_valid())
519 def test_email_is_validated(self):
520 form = ListAnonymousSubscribe(dict(email='invalid'))
521 self.assertFalse(form.is_valid())
522 self.assertTrue('email' in form.errors)
523 self.assertEqual(form.errors['email'],
524 ['Please enter a valid email address.'])
526 def test_all_fields(self):
527 form = ListAnonymousSubscribe(dict(email='bob@example.com',
528 display_name='Bob'))
529 self.assertTrue(form.is_valid())