Update po files
[mailman-postorious.git] / src / postorius / tests / utils.py
blob0e1cf8b4353198c39ab9e0151d7ddcb3c270065b
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2012-2021 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.
10 # Postorius is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 # more details.
15 # You should have received a copy of the GNU General Public License along with
16 # Postorius. If not, see <http://www.gnu.org/licenses/>.
18 import os
19 import tempfile
20 from unittest.mock import MagicMock
22 from django.conf import settings
23 from django.contrib import messages
24 from django.test import TransactionTestCase
25 from django.urls import reverse
27 from django_mailman3.lib.mailman import get_mailman_client
28 from django_mailman3.tests.utils import get_flash_messages
29 from six import PY3, binary_type, text_type
30 from six.moves.urllib_parse import (
31 parse_qsl, quote, urlencode, urlparse, urlunparse)
34 def get_test_file(*fileparts):
35 return os.path.join(os.path.dirname(__file__), "test_data", *fileparts)
36 get_test_file.__test__ = False # noqa: E305
39 def reorder_request_params(request):
40 def reorder_params(params):
41 parsed = None
42 if PY3:
43 if isinstance(params, binary_type):
44 params = params.decode("ascii")
45 parsed = parse_qsl(params, encoding="utf-8")
46 else:
47 parsed = parse_qsl(params)
48 if parsed:
49 return urlencode(sorted(parsed, key=lambda kv: kv[0]))
50 else:
51 # Parsing failed, it may be a simple string.
52 return params
53 # sort the URL query-string by key names.
54 uri_parts = urlparse(request.uri)
55 if uri_parts.query:
56 request.uri = urlunparse((
57 uri_parts.scheme, uri_parts.netloc, uri_parts.path,
58 uri_parts.params, reorder_params(uri_parts.query),
59 uri_parts.fragment,
61 # convert the request body to text and sort the parameters.
62 if isinstance(request.body, binary_type):
63 try:
64 request._body = request._body.decode('utf-8')
65 except UnicodeDecodeError:
66 pass
67 if isinstance(request.body, text_type):
68 request._body = reorder_params(request._body.encode('utf-8'))
69 return request
72 def filter_response_headers(response):
73 for header in ('Date', 'Server', 'date', 'server'):
74 # The headers are lowercase on Python 2 and capitalized on Python 3
75 if header in response['headers']:
76 del response['headers'][header]
77 return response
80 def create_mock_domain(properties=None):
81 """Create and return a mocked Domain.
83 :param properties: A dictionary of the domain's properties.
84 :type properties: dict
85 :return: A MagicMock object with the properties set.
86 :rtype: MagicMock
87 """
88 mock_object = MagicMock(name='Domain')
89 mock_object.contact_address = ''
90 mock_object.description = ''
91 mock_object.mail_host = ''
92 mock_object.lists = []
93 if properties is not None:
94 for key in properties:
95 setattr(mock_object, key, properties[key])
96 return mock_object
99 def create_mock_list(properties=None):
100 """Create and return a mocked List.
102 :param properties: A dictionary of the list's properties.
103 :type properties: dict
104 :return: A MagicMock object with the properties set.
105 :rtype: MagicMock
107 mock_object = MagicMock(name='List')
108 mock_object.members = []
109 mock_object.moderators = []
110 mock_object.owners = []
111 # like in mock_domain, some defaults need to be added...
112 if properties is not None:
113 for key in properties:
114 setattr(mock_object, key, properties[key])
115 return mock_object
118 def create_mock_member(properties=None):
119 """Create and return a mocked Member.
121 :param properties: A dictionary of the member's properties.
122 :type properties: dict
123 :return: A MagicMock object with the properties set.
124 :rtype: MagicMock
126 mock_object = MagicMock(name='Member')
127 # like in mock_domain, some defaults need to be added...
128 if properties is not None:
129 for key in properties:
130 setattr(mock_object, key, properties[key])
131 return mock_object
134 class ViewTestCase(TransactionTestCase):
136 def setUp(self):
137 self.mm_client = get_mailman_client()
139 def tearDown(self):
140 for d in self.mm_client.domains:
141 d.delete()
142 for u in self.mm_client.users:
143 u.delete()
145 def assertHasSuccessMessage(self, response, count=1):
146 msgs = get_flash_messages(response)
147 self.assertEqual(len(msgs), count)
148 self.assertEqual(
149 msgs[0].level, messages.SUCCESS,
150 "%s: %s" % (messages.DEFAULT_TAGS[msgs[0].level], msgs[0].message))
151 return msgs[0].message
153 def assertHasErrorMessage(self, response):
154 msgs = get_flash_messages(response)
155 self.assertEqual(len(msgs), 1)
156 self.assertEqual(
157 msgs[0].level, messages.ERROR,
158 "%s: %s" % (messages.DEFAULT_TAGS[msgs[0].level], msgs[0].message))
159 return msgs[0].message
161 def assertHasNoMessage(self, response):
162 msgs = get_flash_messages(response)
163 self.assertEqual(len(msgs), 0)
165 def assertRedirectsToLogin(self, url):
166 response = self.client.get(url)
167 self.assertRedirects(response, '{}?next={}'.format(
168 reverse(settings.LOGIN_URL), quote(url)))
170 @classmethod
171 def write_response(cls, response):
172 """Print the response in a tmp file and open it in browser."""
173 tmp = tempfile.NamedTemporaryFile(suffix='.html', delete=False)
174 tmp.write(response.content)
175 tmp.close()
176 print(f'Wrote response to file://{tmp.name}')