Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: sitescripts/formmail/test/test_formmail.py

Issue 29984580: Issue 4413 - Merge formmail.py and formmail2.py (Closed) Base URL: https://hg.adblockplus.org/sitescripts/
Patch Set: More work on README Created Jan. 22, 2019, 10:52 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # This file is part of the Adblock Plus web scripts, 1 # This file is part of the Adblock Plus web scripts,
2 # Copyright (C) 2006-present eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details. 11 # GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License 13 # You should have received a copy of the GNU General Public License
14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
15 15
16 from urllib import urlencode 16 from urllib import urlencode
17 from urllib2 import urlopen 17 from urllib2 import urlopen, HTTPError
18 from csv import DictReader
18 19
19 import pytest 20 import pytest
20 from wsgi_intercept import (urllib_intercept, add_wsgi_intercept, 21 from wsgi_intercept import (urllib_intercept, add_wsgi_intercept,
21 remove_wsgi_intercept) 22 remove_wsgi_intercept)
22 23
23 from sitescripts.formmail.web.formmail import handleRequest 24 from sitescripts.formmail.web import formmail
25
26 HOST = 'test.local'
27 LOG_PORT = 80
28 NO_LOG_PORT = 81
29
30
31 @pytest.fixture
32 def log_path(tmpdir):
33 return str(tmpdir.join('test.csv_log'))
34
35
36 @pytest.fixture
37 def log_form_config():
38 return formmail.conf_parse(formmail.get_config_items())['test']
39
40
41 @pytest.fixture
42 def form_config():
43 config = formmail.conf_parse(formmail.get_config_items())['test']
44 del config['csv_log']
45 return config
46
47
48 @pytest.fixture
49 def form_handler(log_path, form_config, log_form_config):
50 """ Create two handlers, one that logs and another that doesn't """
51 log_form_config['csv_log'].value = log_path
52 return (formmail.make_handler('test', log_form_config)[1],
53 formmail.make_handler('test', form_config)[1])
24 54
25 55
26 # We make this a fixture instead of a constant so we can modify it in each 56 # We make this a fixture instead of a constant so we can modify it in each
27 # test as needed without affecting other tests. 57 # test as needed without affecting other tests.
28 @pytest.fixture 58 @pytest.fixture
29 def form_data(): 59 def form_data():
30 return { 60 return {
31 'name': 'John Doe',
32 'email': 'john_doe@gmail.com', 61 'email': 'john_doe@gmail.com',
33 'subject': 'Hello there!', 62 'mandatory': 'john_doe@gmail.com',
34 'message': 'Once upon a time\nthere lived a king.', 63 'non_mandatory_message': 'Once upon a time\nthere lived a king.',
64 'non_mandatory_email': 'test@test.com',
35 } 65 }
36 66
37 67
38 @pytest.fixture() 68 @pytest.fixture
39 def response_for(): 69 def response_for(form_handler):
40 host, port = 'test.local', 80 70 """ Registers two intercepts, returns responses for them based on bool """
41 urllib_intercept.install_opener() 71 urllib_intercept.install_opener()
42 add_wsgi_intercept(host, port, lambda: handleRequest) 72 add_wsgi_intercept(HOST, LOG_PORT, lambda: form_handler[0])
43 url = 'http://{}:{}'.format(host, port) 73 add_wsgi_intercept(HOST, NO_LOG_PORT, lambda: form_handler[1])
44 74
45 def response_for(data): 75 def response_for(data, log=False):
76 if log:
77 url = 'http://{}:{}'.format(HOST, LOG_PORT)
78 else:
79 url = 'http://{}:{}'.format(HOST, NO_LOG_PORT)
46 if data is None: 80 if data is None:
47 response = urlopen(url) 81 response = urlopen(url)
48 else: 82 else:
49 response = urlopen(url, urlencode(data)) 83 response = urlopen(url, urlencode(data))
50 assert response.getcode() == 200 84 return response.code, response.read()
51 return response.read()
52 85
53 yield response_for 86 yield response_for
54 remove_wsgi_intercept() 87 remove_wsgi_intercept()
55 88
56 89
57 def test_get_error(response_for): 90 @pytest.fixture
58 assert response_for(None) == 'Unsupported request method' 91 def sm_mock(mocker):
92 return mocker.patch('sitescripts.formmail.web.formmail.sendMail')
59 93
60 94
61 def test_no_name(response_for, form_data): 95 @pytest.mark.parametrize('key,message', [
62 del form_data['name'] 96 ('url', 'No URL configured for form handler: test'),
63 assert response_for(form_data) == 'No name entered' 97 ('fields', 'No fields configured for form handler: test'),
98 ('template', 'No template configured for form handler: test'),
99 ])
100 def test_config_errors(key, message, form_config):
101 del form_config[key]
102 with pytest.raises(Exception) as error:
103 formmail.make_handler('test', form_config)[1]
104 assert error.value.message == message
64 105
65 106
66 def test_no_email(response_for, form_data): 107 @pytest.mark.parametrize('field,message', [
67 del form_data['email'] 108 (('new_field', 'foo'), 'Unexpected field/fields: new_field'),
68 assert response_for(form_data) == 'No email address entered' 109 (('mandatory', ''), 'No mandatory entered'),
110 (('non_mandatory_email', 'asfaf'), 'Invalid email'),
111 (('email', 'asfaf'), 'You failed the email validation'),
112 (('email', ''), 'You failed the email test'),
113 ])
114 def test_http_errs(field, message, response_for, form_data, sm_mock):
115 key, value = field
116 form_data[key] = value
117 with pytest.raises(HTTPError) as error:
118 response_for(form_data)
119 assert error.value.read() == message
69 120
70 121
71 def test_no_subject(response_for, form_data): 122 @pytest.mark.parametrize('field,expected', [
72 del form_data['subject'] 123 (('non_mandatory_message', '\xc3\xb6'), (200, '')),
73 assert response_for(form_data) == 'No subject entered' 124 (('non_mandatory_message', ''), (200, '')),
125 ])
126 def test_success(field, expected, log_path, response_for, form_data, sm_mock):
127 key, value = field
128 form_data[key] = value
129 assert response_for(form_data, log=False) == expected
130 assert sm_mock.call_count == 1
131
132 params = sm_mock.call_args[0][1]['fields']
133 assert set(params.keys()) == set(form_data.keys())
134 for key, value in form_data.items():
135 assert params[key] == value.decode('utf8')
136
137 assert response_for(form_data, log=True) == expected
138 assert sm_mock.call_count == 2
139
140 assert response_for(form_data, log=True) == expected
141 assert sm_mock.call_count == 3
142
143 with open(log_path) as log_file:
144 reader = DictReader(log_file)
145 row = reader.next()
146 # rows should not be equal because the time field
147 # is added by the logging function.
148 assert row != reader.next()
74 149
75 150
76 def test_no_message(response_for, form_data): 151 def test_config_field_errors(form_config):
77 del form_data['message'] 152 form_config['fields'] = {}
78 assert response_for(form_data) == 'No message entered' 153 with pytest.raises(Exception) as error:
154 formmail.make_handler('test', form_config)[1]
155 assert error.value.message == 'No fields configured for form handler: test'
79 156
80 157
81 def test_bad_email(response_for, form_data): 158 def test_config_template_errors(form_config):
82 form_data['email'] = 'bad_email' 159 form_config['template'].value = 'no'
83 assert response_for(form_data) == 'Invalid email address' 160 with pytest.raises(Exception) as error:
161 formmail.make_handler('test', form_config)[1]
162 assert error.value.message == 'Template not found at: no'
84 163
85 164
86 def test_success(response_for, form_data, mocker): 165 def test_config_parse(form_config):
87 sm_mock = mocker.patch('sitescripts.formmail.web.formmail.sendMail') 166 assert form_config['url'].value == 'test/apply/submit'
88 assert response_for(form_data) == 'Message sent' 167 assert form_config['fields']['email'].value == 'mandatory, email'
89 assert sm_mock.call_count == 1 168
90 params = sm_mock.call_args[0][1] 169
91 assert set(params.keys()) == set(form_data.keys()) | {'time'} 170 def test_sendmail_fail(log_path, response_for, form_data, sm_mock):
92 for key, value in form_data.items(): 171 sm_mock.side_effect = Exception('Sendmail Fail')
93 assert params[key] == value 172 with pytest.raises(HTTPError):
173 response_for(form_data, log=True)
174
175 with open(log_path) as log_file:
176 row = DictReader(log_file).next()
177 assert row != form_data
178
179
180 def test_append_field_err(form_config, form_data, log_path):
181 """ Checks that error logs are correctly written and appended
182
183 Submits three forms, the second two have different fields to the first
184 and should be added to the same log file as each other, and be identical
185 """
186 formmail.log_formdata(form_data, log_path)
187 del form_data['email']
188
189 # submit two forms with fields that dont match the config
190 # this should append the second form to the error log file
191 with pytest.raises(Exception):
192 formmail.log_formdata(form_data, log_path)
193 with pytest.raises(Exception):
194 formmail.log_formdata(form_data, log_path)
195
196 with open(log_path + '_error') as error_log:
197 reader = DictReader(error_log)
198 assert reader.next() == form_data
199 assert reader.next() == form_data
OLDNEW

Powered by Google App Engine
This is Rietveld