File: //lib/python3/dist-packages/postorius/tests/test_list_forms.py
# -*- coding: utf-8 -*-
# Copyright (C) 2017-2023 by the Free Software Foundation, Inc.
#
# This file is part of Postorius.
#
# Postorius is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Postorius is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# Postorius. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from django.test import TestCase
from postorius.forms.list_forms import (
ArchiveSettingsForm,
ChangeSubscriptionForm,
DigestSettingsForm,
DMARCMitigationsForm,
ListAnonymousSubscribe,
ListAutomaticResponsesForm,
ListHeaderMatchForm,
ListIdentityForm,
ListMassRemoval,
ListMassSubscription,
ListNew,
ListSubscribe,
MemberModeration,
MemberPolicyForm,
MessageAcceptanceForm,
)
from postorius.forms.system import AddBanForm
from postorius.tests.utils import create_mock_list
class TestListSubscribe(TestCase):
def test_required_fields_only(self):
user_emails = ['bob@example.com', 'anne@example.com']
form = ListSubscribe(
user_emails, None, None, dict(subscriber='bob@example.com')
)
self.assertTrue(form.is_valid())
def test_email_is_only_from_choices(self):
user_emails = ['bob@example.com', 'anne@example.com']
form = ListSubscribe(
user_emails,
None,
None,
dict(subscriber='alice@example.com', display_name='Alice'),
)
self.assertFalse(form.is_valid())
self.assertTrue('subscriber' in form.errors)
self.assertTrue(
'Select a valid choice.' in form.errors['subscriber'][0]
)
def test_subscribe_works(self):
user_emails = ['someone@example.com']
form = ListSubscribe(
user_emails,
None,
None,
{'subscriber': 'someone@example.com', 'display_name': 'Someone'},
)
self.assertTrue(form.is_valid())
def test_subscribe_fails(self):
user_emails = ['someone@example.com']
form = ListSubscribe(
user_emails,
None,
None,
{'subscriber': 'notaemail', 'display_name': 'Someone'},
)
self.assertFalse(form.is_valid())
self.assertTrue('subscriber' in form.errors.keys())
self.assertEqual(
form.errors['subscriber'][0],
'Select a valid choice.'
' notaemail is not one of the available choices.',
)
def test_subscribe_validates_email(self):
user_emails = ['something']
form = ListSubscribe(
user_emails,
None,
None,
{'subscriber': 'something', 'display_name': 'Someone'},
)
self.assertFalse(form.is_valid())
self.assertTrue('subscriber' in form.errors.keys())
self.assertEqual(
form.errors['subscriber'][0], 'Please enter a valid email address.'
)
def test_subscribe_with_user_uuid(self):
user_emails = ['aperson@example.com']
form = ListSubscribe(
user_emails,
'00000000000000000000000000000004',
'aperson@example.com',
{'subscriber': '00000000000000000000000000000004'},
)
self.assertEqual(form.is_valid(), True)
def test_subscribe_with_invalid_uuid(self):
# Test that invalid UUID returns errors.
user_emails = ['aperson@example.com']
form = ListSubscribe(
user_emails, '4', 'aperson@example.com', {'subscriber': '4'}
)
self.assertEqual(form.is_valid(), False)
self.assertEqual(
form.errors['subscriber'][0], 'Please enter a valid email address.'
)
def test_list_subscribe_with_delivery_mode(self):
user_emails = ['aperson@example.com']
form = ListSubscribe(
user_emails,
'00000000000000000000000000000004',
'aperson@example.com',
{
'subscriber': '00000000000000000000000000000004',
'delivery_mode': 'plaintext_digests',
'delivery_status': 'by_user',
},
)
self.assertTrue(form.is_valid())
def test_list_subscribe_with_invalid_delivery_status(self):
user_emails = ['aperson@example.com']
form = ListSubscribe(
user_emails,
'00000000000000000000000000000004',
'aperson@example.com',
{
'subscriber': '00000000000000000000000000000004',
'delivery_mode': 'plaintext_digest',
'delivery_status': 'by_bounces',
},
)
self.assertFalse(form.is_valid())
self.assertTrue('delivery_status' in form.errors)
class TestChangeSubscription(TestCase):
def test_subscription_changes_only_to_user_addresses(self):
user_emails = ['one@example.com', 'two@example.com']
form = ChangeSubscriptionForm(
user_emails,
None,
None,
{'subscriber': 'abcd@d.com', 'member_id': '1235sdfsd314'},
)
self.assertFalse(form.is_valid())
self.assertTrue('subscriber' in form.errors.keys())
self.assertEqual(
form.errors['subscriber'][0],
'Select a valid choice. '
'abcd@d.com is not one of the available choices.',
)
def test_subscription_works(self):
user_emails = ['one@example.com', 'two@example.com']
form = ChangeSubscriptionForm(
user_emails,
None,
None,
{'subscriber': 'two@example.com', 'member_id': '1235sdfsd314'},
)
self.assertTrue(form.is_valid())
def test_subscription_form_labels(self):
user_emails = ['one@example.com', 'two@example.com']
form = ChangeSubscriptionForm(
user_emails, None, None, {'member_id': '1235sdfsd314'}
)
self.assertTrue(form.is_valid())
self.assertEqual(form.fields['subscriber'].label, 'Select Email')
def test_form_validity(self):
form = ChangeSubscriptionForm(
['email@example.com', 'john@example.com', 'doe@example.com'],
None,
None,
{'subscriber': 'email@example.com', 'member_id': '1235sdfsd314'},
)
self.assertTrue(form.is_valid())
def test_required_fields(self):
# There is only one required fields.
form = ChangeSubscriptionForm(
['email@example.com', 'john@example.com', 'doe@example.com'],
None,
None,
{'member_id': '1235sdfsd314'},
)
self.assertTrue(form.is_valid())
def test_change_subscription_with_user_uuid(self):
user_emails = ['aperson@example.com']
form = ChangeSubscriptionForm(
user_emails,
'00000000000000000000000000000004',
'aperson@example.com',
{
'subscriber': '00000000000000000000000000000004',
'member_id': '1235sdfsd314',
},
)
self.assertEqual(form.is_valid(), True)
def test_subscribe_with_invalid_uuid(self):
# Test that invalid UUID returns errors.
user_emails = ['aperson@example.com']
# UUIDs are 32bit and 4 is not a valid email.
form = ChangeSubscriptionForm(
user_emails, '4', 'aperson@example.com', {'subscriber': '4'}
)
self.assertEqual(form.is_valid(), False)
self.assertEqual(
form.errors['subscriber'][0],
'Invalid: "4" should be either email or UUID',
)
class TestListNew(TestCase):
def test_form_fields_list(self):
domain_choices = [
('mailman.most-desirable.org', 'mailman.most-desirable.org')
]
style_choices = [
('legacy-default', 'Ordinary discussion mailing list style.'),
('legacy-announce', 'Announce only mailing list style.'),
]
form = ListNew(
domain_choices,
style_choices,
{
'listname': 'xyz',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'contact@mailman.most-desirable.org',
'advertised': 'True',
'list_style': 'legacy-default',
'description': 'The Most Desirable organization',
},
)
self.assertTrue(form.is_valid(), form.errors)
def test_form_fields_list_invalid(self):
domain_choices = [
('mailman.most-desirable.org', 'mailman.most-desirable.org')
]
style_choices = [
('legacy-default', 'Ordinary discussion mailing list style.'),
('legacy-announce', 'Announce only mailing list style.'),
]
form = ListNew(
domain_choices,
style_choices,
{
'listname': 'xy#z',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'mailman.most-desirable.org',
'advertised': 'abcd',
'list_style': 'defg',
'description': 'The Most Desirable organization',
},
)
self.assertFalse(form.is_valid())
# Test that all invalid fields are actually checked.
for field in ('list_owner', 'advertised'):
self.assertTrue(field in form.errors)
self.assertTrue(
'Enter a valid email address.' in form.errors['list_owner']
)
self.assertTrue(
'Select a valid choice. abcd is not one of the available choices.'
in form.errors['advertised']
)
def test_form_without_domain_choices(self):
form = ListNew(
[],
{
'listname': 'xyz',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'contact@mailman.most-desirable.org',
'advertised': 'True',
'description': 'The Most Desirable organization',
},
)
# Without domain choices, the form is not going to be valid.
self.assertFalse(form.is_valid())
self.assertTrue(
form.fields['mail_host'].help_text
== 'Site admin has not created any domains' # noqa: W504
)
def test_listname_validation(self):
domain_choices = [
('mailman.most-desirable.org', 'mailman.most-desirable.org')
]
style_choices = [
('legacy-default', 'Ordinary discussion mailing list style.'),
('legacy-announce', 'Announce only mailing list style.'),
]
form = ListNew(
domain_choices,
style_choices,
{
'listname': 'xy@z',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'mailman.most-desirable.org',
'advertised': 'abcd',
'description': 'The Most Desirable organization',
},
)
self.assertFalse(form.is_valid())
self.assertTrue('listname' in form.errors)
self.assertTrue(
'Please enter a valid listname' in form.errors['listname']
)
@unittest.expectedFailure
def test_listname_validation_errors_sane(self):
# This test is going to fail right now, but needs to be fixed.
form = ListNew(
[('mailman.most-desirable.org', 'mailman.most-desirable.org')],
{
'listname': 'xy#z',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'mailman.most-desirable.org',
'advertised': 'abcd',
'description': 'The Most Desirable organization',
},
)
self.assertFalse(form.is_valid())
self.assertTrue('listname' in form.errors)
self.assertEqual(
'Please enter a valid listname, "@" is not allowed in listname',
form.errors['listname'],
)
def test_form_fields_order(self):
domain_choices = [
('mailman.most-desirable.org', 'mailman.most-desirable.org')
]
style_choices = [
('legacy-default', 'Ordinary discussion mailing list style.'),
('legacy-announce', 'Announce only mailing list style.'),
]
form = ListNew(
domain_choices,
style_choices,
{
'listname': 'xyz',
'mail_host': 'mailman.most-desirable.org',
'list_owner': 'mailman@most-desirable.org',
'list_style': 'legacy-default',
'advertised': 'True',
'description': 'The Most Desirable organization',
},
)
self.assertTrue(form.is_valid())
# The order of the fields should remain exactly like this.
self.assertEqual(
list(form.fields),
[
'listname',
'mail_host',
'list_owner',
'advertised',
'list_style',
'description',
],
)
class TestListIdentityForm(TestCase):
def test_not_required_fields(self):
# Only advertised is the required form field.
form = ListIdentityForm(
{
'advertised': 'True',
},
mlist=None,
)
self.assertTrue(form.is_valid(), form.errors)
def test_field_validations(self):
form = ListIdentityForm(
{
'advertised': 'abcd',
'description': 'This is the most desirable organization',
'info': 'This is a larger description of this mailing list.',
'display_name': 'Most Desirable Mailing List',
'subject_prefix': ' [Most Desirable] ',
'preferred_language': 'en',
'member_roster_visibility': 'public',
},
mlist=None,
)
self.assertFalse(form.is_valid())
self.assertTrue('advertised' in form.errors)
self.assertEqual(
[
'Select a valid choice. abcd is not one of the available choices.' # noqa: E501
],
form.errors['advertised'],
)
# We shouldn't be removing trailing whitespaces, but we
# should remove the leading ones.
self.assertEqual(
form.cleaned_data['subject_prefix'],
'[Most Desirable] ',
)
class TestListMassSubscription(TestCase):
def test_all_valid_email_formats(self):
form = ListMassSubscription(
{
'emails': """
jdoe@example.com
<jdoe@example.com>
John Doe <jdoe@example.com>
"John Doe" <jdoe@example.com>
jdoe@example.com (John Doe)"""
}
)
self.assertTrue(form.is_valid())
def test_required_fields(self):
form = ListMassSubscription({'email': ' '})
self.assertFalse(form.is_valid())
self.assertEqual(['This field is required.'], form.errors['emails'])
form = ListMassSubscription({'email': '----'})
self.assertFalse(form.is_valid())
self.assertEqual(['This field is required.'], form.errors['emails'])
class TestListMassRemoval(TestCase):
def test_all_valid_formats(self):
form = ListMassRemoval(
{
'emails': """
jdoe@example.com
<jdoe@example.com>
John Doe <jdoe@example.com>
"John Doe" <jdoe@example.com>
jdoe@example.com (John Doe)"""
}
)
self.assertTrue(form.is_valid())
class TestAddBanForm(TestCase):
def test_form_validity(self):
form = AddBanForm({'email': 'jdoe@example.com'})
self.assertTrue(form.is_valid())
def test_missing_fields_errors(self):
form = AddBanForm({})
self.assertFalse(form.is_valid())
self.assertTrue('email' in form.errors)
self.assertEqual(
form.errors['email'], ['Please enter an email address.']
)
@unittest.expectedFailure
def test_invalid_fields_type(self):
# Valid values for email is either a regexp or an email address.
# However, this is currently not validated by the form.
form = AddBanForm({'email': 'invalid@'})
self.assertFalse(form.is_valid())
self.assertTrue('email' in form.errors)
self.assertEqual(
form.errors['email'], ['Please enter a valid email address.']
)
class TestListHeaderMatchForm(TestCase):
def test_form_validity(self):
# Test by putting only required fields.
form = ListHeaderMatchForm(
{'header': 'To', 'pattern': 'value@example.com'}
)
self.assertTrue(form.is_valid())
# Test all fileds.
form = ListHeaderMatchForm(
{
'header': 'To',
'pattern': 'value@example.com',
'action': 'accept',
}
)
self.assertTrue(form.is_valid())
# Defer is not a valid action, so validation should fail here.
form = ListHeaderMatchForm(
{'header': 'To', 'pattern': 'value@example.com', 'action': 'defer'}
)
self.assertFalse(form.is_valid())
self.assertTrue('action' in form.errors)
class TestMemberModeration(TestCase):
def test_moderation_action_validity(self):
form = MemberModeration({'moderation_action': 'moderation'})
self.assertFalse(form.is_valid())
self.assertTrue('moderation_action' in form.errors)
self.assertEqual(
form.errors['moderation_action'],
[
'Select a valid choice. moderation is not one of the available choices.' # noqa: E501
],
)
def test_required_fields(self):
form = MemberModeration({})
self.assertTrue(form.is_valid())
class TestListAutomaticResponsesForm(TestCase):
fields = (
'autorespond_owner',
'autoresponse_owner_text',
'autorespond_postings',
'autoresponse_postings_text',
'autorespond_requests',
'autoresponse_request_text',
'autoresponse_grace_period',
'send_welcome_message',
'welcome_message_uri',
'send_goodbye_message',
'goodbye_message_uri',
'admin_immed_notify',
'admin_notify_mchanges',
)
def prepare_formdata(self, values):
return dict(
(
(key, val)
for key, val in zip(self.fields, values)
if val is not None
)
) # noqa
def test_required_fields_only(self):
values = (
'respond_and_continue',
None,
'respond_and_continue',
None,
'respond_and_continue',
None,
'2',
None,
None,
None,
None,
None,
)
formdata = self.prepare_formdata(values)
form = ListAutomaticResponsesForm(formdata, mlist=None)
self.assertTrue(form.is_valid())
def test_all_values(self):
values = (
'respond_and_continue',
'Autorespond text',
'respond_and_continue',
'Autorespond text',
'respond_and_continue',
'Autorespond text',
'2',
'True',
'http://example.com/welcome_text',
'True',
'http://example.com/goodbye_message',
'True',
'False',
)
formdata = self.prepare_formdata(values)
form = ListAutomaticResponsesForm(formdata, mlist=None)
print(form.errors)
self.assertTrue(form.is_valid())
class TestAlterMessageForm(TestCase):
fields = (
'filter_content',
'collapse_alternatives',
'convert_html_to_plaintext',
'anonymous_list',
'include_rfc2369_headers',
'allow_list_posts',
'reply_list_posts',
'reply_to_address',
'first_strip_reply_to',
'reply_goes_to_list',
'posting_pipeline',
)
def prepare_formdata(self, values):
return dict(
(
(key, val)
for key, val in zip(self.fields, values)
if val is not None
)
) # noqa
class TestDMARCMitigationsForm(TestCase):
def test_required_fields(self):
# All fields in the form are optional, so an empty form should be
# valid.
form = DMARCMitigationsForm({}, mlist=None)
self.assertTrue(form.is_valid())
def test_all_fields(self):
formdata = dict(
dmarc_mitigate_action='munge_from',
dmarc_mitigate_unconditionally='True',
dmarc_addresses='user@example.com\n^.*@example.net',
dmarc_moderation_notice='This is a moderation notice',
dmarc_wrapped_message_text='This is wrapped message text',
)
form = DMARCMitigationsForm(formdata, mlist=None)
self.assertTrue(form.is_valid())
class TestDigestSettingsForm(TestCase):
def test_required_fields(self):
form = DigestSettingsForm({}, mlist=None)
self.assertFalse(form.is_valid())
self.assertTrue('digest_size_threshold' in form.errors)
self.assertEqual(
form.errors['digest_size_threshold'], ['This field is required.']
)
form = DigestSettingsForm({'digest_size_threshold': 40}, mlist=None)
self.assertTrue(form.is_valid())
def test_all_fields(self):
formdata = dict(
digests_enabled='True',
digests_send_periodic='True',
digests_volume_frequency='daily',
digest_size_threshold='10',
)
form = DigestSettingsForm(formdata, mlist=None)
self.assertTrue(form.is_valid())
class TestMessageAcceptanceForm(TestCase):
fields = (
'acceptable_aliases',
'require_explicit_destination',
'administrivia',
'default_member_action',
'default_nonmember_action',
'max_message_size',
'max_num_recipients',
)
def prepare_formdata(self, values):
return dict(
(
(key, val)
for key, val in zip(self.fields, values)
if val is not None
)
) # noqa
def test_required_fields(self):
# Without any fields, form should not be valid.
form = MessageAcceptanceForm({}, mlist=None)
self.assertFalse(form.is_valid())
# Now lets try with only required fields.
values = (None, None, None, 'hold', 'hold', 40, 100)
form = MessageAcceptanceForm(self.prepare_formdata(values), mlist=None)
print(form.errors)
self.assertTrue(form.is_valid())
def test_all_fields(self):
pass
class TestArchiveSettingsForm(TestCase):
def setUp(self):
self.mlist = create_mock_list()
archivers = {'pipermail': True, 'hyperkitty': True}
self.mlist.archivers.keys.side_effect = archivers.keys
self.mlist.archivers.__getitem__.side_effect = archivers.__getitem__
self.mlist.archivers.__iter__.side_effect = archivers.__iter__
self.mlist.archivers.__contains__.side_effect = archivers.__contains__
def test_required_fields(self):
# First try without any fields.
form = ArchiveSettingsForm({}, mlist=self.mlist)
self.assertFalse(form.is_valid())
self.assertTrue('archive_policy' in form.errors)
# Now, with only required fields, this should be a valid form.
form = ArchiveSettingsForm(
dict(archive_policy='public'), mlist=self.mlist
)
self.assertTrue(form.is_valid())
def test_all_fields(self):
formdata = dict(
archive_policy='public', archivers=['pipermail', 'hyperkitty']
)
form = ArchiveSettingsForm(formdata, mlist=self.mlist)
self.assertTrue(form.is_valid())
def test_setup_archivers_populated(self):
formdata = dict(
archive_policy='public', archivers=['pipermail', 'hyperkitty']
)
form = ArchiveSettingsForm(
formdata, mlist=self.mlist, initial={'archivers': None}
)
self.assertTrue(form.is_valid())
self.assertEqual(
form.initial['archivers'], ['hyperkitty', 'pipermail']
)
def test_optional_archive_rendering_field(self):
# Test that archive rendering mode is set only when Hyperkitty is
# installed.
formdata = dict(archive_policy='public', archivers=['pipermail'])
form = ArchiveSettingsForm(
formdata, mlist=self.mlist, initial={'archivers': None}
)
self.assertTrue(form.is_valid())
self.assertFalse('archive_rendering_mode' in form.fields)
# With Hyperkitty installed, the field should show up.
with unittest.mock.patch(
'postorius.forms.list_forms.apps.is_installed', return_value=True
):
formdata = dict(archive_policy='public', archivers=['pipermail'])
form = ArchiveSettingsForm(
formdata, mlist=self.mlist, initial={'archivers': None}
)
self.assertTrue(form.is_valid())
self.assertTrue('archive_rendering_mode' in form.fields)
class TestMemberPolicyForm(TestCase):
def test_required_fields(self):
form = MemberPolicyForm({}, mlist=None)
self.assertFalse(form.is_valid())
self.assertTrue('subscription_policy' in form.errors)
self.assertTrue('unsubscription_policy' in form.errors)
form = MemberPolicyForm(
dict(
subscription_policy='confirm', unsubscription_policy='confirm'
),
mlist=None,
)
self.assertTrue(form.is_valid())
class TestListAnonymousSubscribe(TestCase):
def test_required_fields_only(self):
form = ListAnonymousSubscribe(dict(email='bob@exmaple.com'))
self.assertTrue(form.is_valid())
def test_email_is_validated(self):
form = ListAnonymousSubscribe(dict(email='invalid'))
self.assertFalse(form.is_valid())
self.assertTrue('email' in form.errors)
self.assertEqual(
form.errors['email'], ['Please enter a valid email address.']
)
def test_all_fields(self):
form = ListAnonymousSubscribe(
dict(email='bob@example.com', display_name='Bob')
)
self.assertTrue(form.is_valid())