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

Delta Between Two Patch Sets: sitescripts/formmail/test/test_formmail2.py

Issue 29374647: Issue 4814 - Adds csv log to formmail2 (Closed) Base URL: https://hg.adblockplus.org/sitescripts
Left Patch Set: Created March 18, 2017, 4:13 p.m.
Right Patch Set: Created March 23, 2017, 6:50 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « .sitescripts.example ('k') | sitescripts/formmail/web/formmail2.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2016 Eyeo GmbH 2 # Copyright (C) 2006-2017 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 #
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 54
55 55
56 # 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
57 # test as needed without affecting other tests. 57 # test as needed without affecting other tests.
58 @pytest.fixture 58 @pytest.fixture
59 def form_data(): 59 def form_data():
60 return { 60 return {
61 'email': 'john_doe@gmail.com', 61 'email': 'john_doe@gmail.com',
62 'mandatory': 'john_doe@gmail.com', 62 'mandatory': 'john_doe@gmail.com',
63 'non_mandatory_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' 64 'non_mandatory_email': 'test@test.com',
Vasily Kuznetsov 2017/03/21 14:00:34 I usually put the comma at the end of last item in
Jon Sonesen 2017/03/22 14:28:20 Done.
65 } 65 }
66 66
67 67
68 @pytest.fixture 68 @pytest.fixture
69 def response_for(form_handler): 69 def response_for(form_handler):
70 """ Registers two intercepts, returns responses for them based on bool """ 70 """ Registers two intercepts, returns responses for them based on bool """
71 urllib_intercept.install_opener() 71 urllib_intercept.install_opener()
72 add_wsgi_intercept(HOST, LOG_PORT, lambda: form_handler[0]) 72 add_wsgi_intercept(HOST, LOG_PORT, lambda: form_handler[0])
73 add_wsgi_intercept(HOST, NO_LOG_PORT, lambda: form_handler[1]) 73 add_wsgi_intercept(HOST, NO_LOG_PORT, lambda: form_handler[1])
74 74
75 def response_for(data, log=False): 75 def response_for(data, log=False):
76 url = 'http://{}:{}'.format(HOST, NO_LOG_PORT)
77 if log: 76 if log:
Vasily Kuznetsov 2017/03/21 14:00:34 I think this would be more readable as: if log:
Jon Sonesen 2017/03/22 14:28:20 Done.
78 url = 'http://{}:{}'.format(HOST, LOG_PORT) 77 url = 'http://{}:{}'.format(HOST, LOG_PORT)
78 else:
79 url = 'http://{}:{}'.format(HOST, NO_LOG_PORT)
79 if data is None: 80 if data is None:
80 response = urlopen(url) 81 response = urlopen(url)
81 else: 82 else:
82 response = urlopen(url, urlencode(data)) 83 response = urlopen(url, urlencode(data))
83 return response.code, response.read() 84 return response.code, response.read()
84 85
85 yield response_for 86 yield response_for
86 remove_wsgi_intercept() 87 remove_wsgi_intercept()
87 88
88 89
89 def test_form_handler_email_errors(form_config): 90 @pytest.fixture
90 tmp_config = form_config 91 def sm_mock(mocker):
Vasily Kuznetsov 2017/03/21 14:00:34 What is the purpose of this assignment? Why don't
Jon Sonesen 2017/03/22 14:28:20 whoops. Done
91 del tmp_config['url'].value 92 return mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
92 with pytest.raises(Exception) as error:
93 formmail2.make_handler('test', tmp_config)[1]
94 assert error.value.message == 'No URL configured for form handler: test'
95 93
96 94
97 def test_form_handler_field_errors(form_config): 95 @pytest.mark.parametrize('key,message', [
98 tmp_config = form_config 96 ('url', 'No URL configured for form handler: test'),
99 tmp_config['fields'] = {} 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]
100 with pytest.raises(Exception) as error: 102 with pytest.raises(Exception) as error:
101 formmail2.make_handler('test', tmp_config)[1] 103 formmail2.make_handler('test', form_config)[1]
102 assert error.value.message == 'No fields configured for form handler: test' 104 assert error.value.message == message
103 105
104 del tmp_config['fields'] 106
107 @pytest.mark.parametrize('field,message', [
108 (('new_field', 'foo'), 'Unexpected field/fields: new_field'),
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
120
121
122 @pytest.mark.parametrize('field,expected', [
123 (('non_mandatory_message', '\xc3\xb6'), (200, '')),
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()
149
150
151 def test_config_field_errors(form_config):
152 form_config['fields'] = {}
105 with pytest.raises(Exception) as error: 153 with pytest.raises(Exception) as error:
106 formmail2.make_handler('test', tmp_config)[1] 154 formmail2.make_handler('test', form_config)[1]
107 assert error.value.message == 'No fields configured for form handler: test' 155 assert error.value.message == 'No fields configured for form handler: test'
108 156
109 157
110 def test_form_handler_template_errors(form_config): 158 def test_config_template_errors(form_config):
111 tmp_config = form_config 159 form_config['template'].value = 'no'
112 tmp_config['template'].value = 'no'
113 with pytest.raises(Exception) as error: 160 with pytest.raises(Exception) as error:
114 formmail2.make_handler('test', tmp_config)[1] 161 formmail2.make_handler('test', form_config)[1]
115 assert error.typename == 'TemplateNotFound' 162 assert error.value.message == 'Template not found at: no'
116
117 del tmp_config['template'].value
118 with pytest.raises(Exception) as error:
119 formmail2.make_handler('test', tmp_config)[1]
120 assert error.value.message == ('No template configured for form handler'
121 ': test')
122 del tmp_config['template']
123 with pytest.raises(Exception) as error:
124 formmail2.make_handler('test', tmp_config)[1]
125 assert error.value.message == ('No template configured for form handler'
126 ': test')
127 163
128 164
129 def test_config_parse(form_config): 165 def test_config_parse(form_config):
130 assert form_config['url'].value == 'test/apply/submit' 166 assert form_config['url'].value == 'test/apply/submit'
131 assert form_config['fields']['email'].value == 'mandatory, email' 167 assert form_config['fields']['email'].value == 'mandatory, email'
132 168
133 169
134 def test_sendmail_fail(log_path, response_for, form_data, mocker): 170 def test_sendmail_fail(log_path, response_for, form_data, sm_mock):
135 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
136 sm_mock.side_effect = Exception('Sendmail Fail') 171 sm_mock.side_effect = Exception('Sendmail Fail')
137 with pytest.raises(HTTPError) as error: 172 with pytest.raises(HTTPError):
138 response_for(form_data, log=True) 173 response_for(form_data, log=True)
139 assert error.typename == 'HTTPError'
140 174
141 with open(log_path) as log_file: 175 with open(log_path) as log_file:
142 row = DictReader(log_file).next() 176 row = DictReader(log_file).next()
143 assert 'time' in row 177 assert row != form_data
144
145
146 @pytest.mark.parametrize('log, res',
147 [(True, (200, '')), (False, (200, ''))])
148 def test_utf8_success(log, res, log_path, response_for, form_data, mocker):
149 """ DictWriter does not accpet utf-8, call log handler """
Vasily Kuznetsov 2017/03/21 14:00:34 typo in "accpet".
Jon Sonesen 2017/03/22 14:28:19 Done.
150 form_data['non_mandatory_message'] = '\xc3\xb6'
151 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
152 assert response_for(form_data, log) == res
153 assert sm_mock.call_count == 1
154 params = sm_mock.call_args[0][1]['fields']
155 assert set(params.keys()) == set(form_data.keys())
156 for key, value in form_data.items():
157 assert params[key] == value.decode('utf8')
158
159
160 def test_success(response_for, form_data, mocker):
161 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
Vasily Kuznetsov 2017/03/21 14:00:34 This and some following lines seem to be duplicate
Jon Sonesen 2017/03/22 14:28:20 The thing is that some of the test's have differen
162 assert response_for(form_data) == (200, '')
163 assert sm_mock.call_count == 1
164 params = sm_mock.call_args[0][1]['fields']
165 assert set(params.keys()) == set(form_data.keys())
166 for key, value in form_data.items():
167 assert params[key] == value
168
169
170 def test_log_success(log_path, response_for, form_data, mocker):
171 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
172 assert response_for(form_data, log=True) == (200, '')
173 assert sm_mock.call_count == 1
174 params = sm_mock.call_args[0][1]['fields']
175 assert set(params.keys()) == set(form_data.keys())
176 for key, value in form_data.items():
177 assert params[key] == value
178 with open(log_path) as log_file:
179 row = DictReader(log_file).next()
180 assert 'time' in row
181
182
183 def test_log_append_success(log_path, response_for, form_data, mocker):
184 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
185 assert response_for(form_data, log=True) == (200, '')
186 form_data['non_mandatory_message'] = ''
187 assert response_for(form_data, log=True) == (200, '')
188 assert sm_mock.call_count == 2
189 params = sm_mock.call_args[0][1]['fields']
190 assert set(params.keys()) == set(form_data.keys())
191 for key, value in form_data.items():
192 assert params[key] == value
193 with open(log_path) as log_file:
194 reader = DictReader(log_file)
195 row = reader.next()
196 assert row != reader.next()
197
198
199 def test_non_mandatory_no_msg(response_for, form_data, mocker):
200 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
201 form_data['non_mandatory_message'] = ''
202 assert response_for(form_data) == (200, '')
203
204
205 def test_invalid_email_cstm_msg(response_for, form_data, mocker, form_config):
206 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
207 form_data['email'] = 'bademail'
208 with pytest.raises(HTTPError) as error:
209 response_for(form_data)
210 assert error.value.read() == 'You failed the email validation'
211
212
213 def test_valid_nan_mandatory_email(response_for, form_data, mocker):
Vasily Kuznetsov 2017/03/21 14:00:34 ...non_mandatory...? :)
Jon Sonesen 2017/03/22 14:28:20 Done.
214 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
215 form_data['non_mandatory_email'] = 'asfaf'
216 with pytest.raises(HTTPError) as error:
217 response_for(form_data)
218 assert error.value.read() == 'Invalid email'
219
220 del form_data['non_mandatory_email']
221 assert response_for(form_data) == (200, '')
222
223
224 def test_mandatory_fail_dflt_msg(response_for, form_data, mocker):
225 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
226 del form_data['mandatory']
227 with pytest.raises(HTTPError) as error:
228 response_for(form_data)
229 assert error.value.read() == 'No mandatory entered'
230
231
232 def test_field_err(form_config, form_data, log_path):
233 """ Submits a form that does not have the dame fields as previous submission s
Vasily Kuznetsov 2017/03/21 14:00:35 typo in "dame"?
Jon Sonesen 2017/03/22 14:28:20 Done.
234
Vasily Kuznetsov 2017/03/21 14:00:34 Here you're continuing the same sentence in the li
Jon Sonesen 2017/03/22 14:28:20 Done.
235 that have the same form name, asserts that proper message is returned and
236 the row was properly written
237 """
238 formmail2.log_formdata(form_data, log_path)
239 del(form_config['fields']['email'])
240 del(form_data['email'])
241 try:
242 formmail2.log_formdata(form_data, log_path)
243 except Exception as e:
244 assert e.message == ('Field names have changed, error log '
245 'written to {}_error').format(log_path)
246
247 with open(log_path+'_error') as error_log:
248 assert DictReader(error_log).next() == form_data
249 178
250 179
251 def test_append_field_err(form_config, form_data, log_path): 180 def test_append_field_err(form_config, form_data, log_path):
252 """ Submits two identical forms that do not match the previous fields 181 """ Checks that error logs are correctly written and appended
253 182
254 found in the log file, triggering two rows to be added to the error 183 Submits three forms, the second two have different fields to the first
255 log and asserting the proper message is returned and that the rows 184 and should be added to the same log file as each other, and be identical
256 were written as expected
257 """ 185 """
258 formmail2.log_formdata(form_data, log_path) 186 formmail2.log_formdata(form_data, log_path)
259 del(form_config['fields']['email']) 187 del form_data['email']
260 del(form_data['email']) 188
261 try: 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):
262 formmail2.log_formdata(form_data, log_path) 192 formmail2.log_formdata(form_data, log_path)
263 except Exception: 193 with pytest.raises(Exception):
264 pass
265 try:
266 formmail2.log_formdata(form_data, log_path) 194 formmail2.log_formdata(form_data, log_path)
267 except Exception as e:
268 assert e.message == ('Field names have changed, error log'
269 ' appended to {}_error').format(log_path)
270 195
271 with open(log_path+'_error') as error_log: 196 with open(log_path + '_error') as error_log:
272 reader = DictReader(error_log) 197 reader = DictReader(error_log)
273 # two identical rows should be in the error log
274 assert reader.next() == form_data 198 assert reader.next() == form_data
275 assert reader.next() == form_data 199 assert reader.next() == form_data
LEFTRIGHT

Powered by Google App Engine
This is Rietveld