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

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

Issue 29374647: Issue 4814 - Adds csv log to formmail2 (Closed) Base URL: https://hg.adblockplus.org/sitescripts
Patch Set: Created March 7, 2017, 8:24 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-2016 Eyeo GmbH 2 # Copyright (C) 2006-2016 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
16 import datetime
17 from csv import DictReader
15 from urllib import urlencode 18 from urllib import urlencode
16 from urllib2 import urlopen, HTTPError 19 from urllib2 import urlopen, HTTPError
17 20
18 import pytest 21 import pytest
19 from wsgi_intercept import (urllib_intercept, add_wsgi_intercept, 22 from wsgi_intercept import (urllib_intercept, add_wsgi_intercept,
20 remove_wsgi_intercept) 23 remove_wsgi_intercept)
21 24
22 from sitescripts.formmail.web import formmail2 25 from sitescripts.formmail.web import formmail2
23 26
24 27
25 @pytest.fixture() 28 @pytest.fixture
26 def form_config(): 29 def form_config():
27 return formmail2.conf_parse(formmail2.get_config_items())['test'] 30 return formmail2.conf_parse(formmail2.get_config_items())['test']
28 31
29 32
30 @pytest.fixture() 33 @pytest.fixture
31 def form_handler(form_config): 34 def form_handlers(form_config, log_path):
32 return formmail2.make_handler('test', form_config)[1] 35 """ Returns two handlers, one with logging configured and one without """
Vasily Kuznetsov 2017/03/09 19:58:09 It would be better to have all the docstrings foll
Jon Sonesen 2017/03/14 19:41:26 Done.
36 # override configured path to log file with tmpdir path
37 form_config['csv_log'].value = log_path
38 log_handler = formmail2.make_handler('log_test', form_config)[1]
39
40 # parse a new config because the make_handler function changes the provided
41 # config object which causes the config parsing to break when creating
42 # the handler which has no log
43 no_log_config = formmail2.conf_parse(formmail2.get_config_items())['test']
44 del no_log_config['csv_log']
Jon Sonesen 2017/03/14 19:41:25 it seems that this is actually not working as expe
45
46 return log_handler, formmail2.make_handler('log_test', no_log_config)[1]
Vasily Kuznetsov 2017/03/09 19:58:09 Maybe we also assign the result of `make_handler`
Jon Sonesen 2017/03/10 09:28:51 I was just thinking about what someone else on the
Vasily Kuznetsov 2017/03/10 09:54:28 Acknowledged.
47
48
49 @pytest.fixture
50 def log_path(tmpdir):
51 return str(tmpdir.join('test.csv_log'))
33 52
34 53
35 # We make this a fixture instead of a constant so we can modify it in each 54 # We make this a fixture instead of a constant so we can modify it in each
36 # test as needed without affecting other tests. 55 # test as needed without affecting other tests.
37 @pytest.fixture 56 @pytest.fixture
38 def form_data(): 57 def form_data():
39 return { 58 return {
40 'email': 'john_doe@gmail.com', 59 'email': 'john_doe@gmail.com',
41 'mandatory': 'john_doe@gmail.com', 60 'mandatory': 'john_doe@gmail.com',
42 'non_mandatory_message': 'Once upon a time\nthere lived a king.', 61 'non_mandatory_message': 'Once upon a time\nthere lived a king.',
43 'non_mandatory_email': 'test@test.com' 62 'non_mandatory_email': 'test@test.com',
44 } 63 }
45 64
46 65
47 @pytest.fixture() 66 @pytest.fixture
48 def response_for(form_handler): 67 def responses_for(form_handlers, log_path):
49 host, port = 'test.local', 80 68 """
50 urllib_intercept.install_opener() 69 Returns a list of response functions for handlers configured both with and
51 add_wsgi_intercept(host, port, lambda: form_handler) 70 without logging configured
52 url = 'http://{}:{}'.format(host, port) 71 """
53 72 responses = []
54 def response_for(data): 73 for form_handler in form_handlers:
Vasily Kuznetsov 2017/03/09 19:58:09 Nifty!
Jon Sonesen 2017/03/10 09:28:51 Thanks :)
55 if data is None: 74 host, port = 'test.local', 80
56 response = urlopen(url) 75 urllib_intercept.install_opener()
57 else: 76 add_wsgi_intercept(host, port, lambda: form_handler)
58 response = urlopen(url, urlencode(data)) 77 url = 'http://{}:{}'.format(host, port)
59 return response.code, response.read() 78
60 79 def response_for(data):
61 yield response_for 80 if data is None:
81 response = urlopen(url)
82 else:
83 response = urlopen(url, urlencode(data))
84 return response.code, response.read()
85 responses.append(response_for)
86 yield responses
62 remove_wsgi_intercept() 87 remove_wsgi_intercept()
63 88
64 89
65 def test_config_parse(form_config): 90 def test_config_parse(form_config):
66 assert form_config['url'].value == 'test/apply/submit' 91 assert form_config['url'].value == 'test/apply/submit'
67 assert form_config['fields']['email'].value == 'mandatory, email' 92 assert form_config['fields']['email'].value == 'mandatory, email'
68 93
69 94
70 def test_success(response_for, form_data, mocker): 95 def test_success(responses_for, form_data, mocker):
Jon Sonesen 2017/03/14 19:41:26 Should this test check for the existence of the lo
71 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail') 96 for response_for in responses_for:
72 assert response_for(form_data) == (200, '') 97 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
73 assert sm_mock.call_count == 1 98 assert response_for(form_data) == (200, '')
74 params = sm_mock.call_args[0][1]['fields'] 99 assert sm_mock.call_count == 1
75 assert set(params.keys()) == set(form_data.keys()) 100 params = sm_mock.call_args[0][1]['fields']
76 for key, value in form_data.items(): 101 assert set(params.keys()) == set(form_data.keys())
77 assert params[key] == value 102 for key, value in form_data.items():
78 103 assert params[key] == value
79 104
80 def test_non_mandatory_no_msg(response_for, form_data, mocker): 105
106 def test_utf8_success(responses_for, form_data, mocker):
107 form_data['non_mandatory_message'] = '\xc3\xb6'
108 for response_for in responses_for:
109 sm_mock = mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
110 assert response_for(form_data) == (200, '')
111 assert sm_mock.call_count == 1
112 params = sm_mock.call_args[0][1]['fields']
113 assert set(params.keys()) == set(form_data.keys())
114 for key, value in form_data.items():
115 assert params[key] == value
116
117
118 def test_non_mandatory_no_msg(responses_for, form_data, mocker):
81 mocker.patch('sitescripts.formmail.web.formmail2.sendMail') 119 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
82 form_data['non_mandatory'] = '' 120 form_data['non_mandatory'] = ''
83 assert response_for(form_data) == (200, '') 121 for response_for in responses_for:
84 122 assert response_for(form_data) == (200, '')
85 123
86 def test_invalid_email_cstm_msg(response_for, form_data, mocker, form_config): 124
125 def test_invalid_email_cstm_msg(responses_for, form_data, mocker, form_config):
87 mocker.patch('sitescripts.formmail.web.formmail2.sendMail') 126 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
88 form_data['email'] = 'bademail' 127 form_data['email'] = 'bademail'
89 with pytest.raises(HTTPError) as error: 128 for response_for in responses_for:
90 response_for(form_data) 129 with pytest.raises(HTTPError) as error:
91 assert error.value.read() == 'You failed the email validation' 130 response_for(form_data)
92 131 assert error.value.read() == 'You failed the email validation'
93 132
94 def test_valid_nan_mandatory_email(response_for, form_data, mocker): 133
134 def test_valid_nan_mandatory_email(responses_for, form_data, mocker):
Jon Sonesen 2017/03/14 19:41:25 Yikes! this is actually meant to test 'invalid_non
95 mocker.patch('sitescripts.formmail.web.formmail2.sendMail') 135 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
96 form_data['non_mandatory_email'] = 'asfaf' 136 form_data['non_mandatory_email'] = 'asfaf'
97 with pytest.raises(HTTPError) as error: 137 for response_for in responses_for:
98 response_for(form_data) 138 with pytest.raises(HTTPError) as error:
99 assert error.value.read() == 'Invalid email' 139 response_for(form_data)
140 assert error.value.read() == 'Invalid email'
100 141
101 del form_data['non_mandatory_email'] 142 del form_data['non_mandatory_email']
102 assert response_for(form_data) == (200, '') 143 for response_for in responses_for:
103 144 assert response_for(form_data) == (200, '')
104 145
105 def test_mandatory_fail_dflt_msg(response_for, form_data, mocker): 146
147 def test_mandatory_fail_dflt_msg(responses_for, form_data, mocker):
106 mocker.patch('sitescripts.formmail.web.formmail2.sendMail') 148 mocker.patch('sitescripts.formmail.web.formmail2.sendMail')
107 del form_data['mandatory'] 149 del form_data['mandatory']
Jon Sonesen 2017/03/14 19:41:26 it is actually unlikely the request will be sent m
108 with pytest.raises(HTTPError) as error: 150 for response_for in responses_for:
109 response_for(form_data) 151 with pytest.raises(HTTPError) as error:
110 assert error.value.read() == 'No mandatory entered' 152 response_for(form_data)
153 assert error.value.read() == 'No mandatory entered'
154
155
156 def test_collect_with_tmpl(log_path, form_data):
157 form_data['time'] = 'test'
158 formmail2.log_formdata(form_data, log_path)
159 with open(log_path) as csvfile:
160 assert DictReader(csvfile).next() == form_data
161
162
163 def test_collect_no_tmpl(log_path, form_data, form_config):
164 del(form_config['template'])
165 form_data['time'] = 'test'
166 formmail2.log_formdata(form_data, log_path)
167 with open(log_path) as csvfile:
168 assert DictReader(csvfile).next() == form_data
169
170
171 def test_fieldnames(log_path, form_data):
172 form_data['time'] = str(datetime.datetime.now())
173 formmail2.log_formdata(form_data, log_path)
174 with open(log_path) as csvfile:
175 for field in DictReader(csvfile).fieldnames:
176 assert field in tuple(form_data.keys())
177
178
179 def test_field_err(form_config, form_data, log_path):
180 """
181 Submits a form that does not have the dame fields as previous submissions
182 that have the same form name, asserts that proper message is returned and
183 the row was properly written
184 """
185 formmail2.log_formdata(form_data, log_path)
186 del(form_config['fields']['email'])
187 del(form_data['email'])
188 try:
189 formmail2.log_formdata(form_data, log_path)
190 except Exception as e:
191 assert e.message == ('Field names have changed, error log '
192 'written to {}_error').format(log_path)
193
194 with open(log_path+'_error') as error_log:
195 assert DictReader(error_log).next() == form_data
196
197
198 def test_append_field_err(form_config, form_data, log_path):
199 """
200 Submits two identical forms that do not match the previous fields
201 found in the log file, triggering two rows to be added to the error
202 log and asserting the proper message is returned and that the rows
203 were written as expected
204 """
205 formmail2.log_formdata(form_data, log_path)
206 del(form_config['fields']['email'])
207 del(form_data['email'])
208 try:
209 formmail2.log_formdata(form_data, log_path)
210 except Exception:
211 pass
212 try:
213 formmail2.log_formdata(form_data, log_path)
214 except Exception as e:
215 assert e.message == ('Field names have changed, error log'
216 ' appended to {}_error').format(log_path)
217
218 with open(log_path+'_error') as error_log:
219 reader = DictReader(error_log)
220 # two identical rows should be in the error log
221 assert reader.next() == form_data
222 assert reader.next() == form_data
223
224
225 def test_append_log(form_data, log_path):
226 """
227 Collect data twice, altering a field in the second call
228 assert that the 2nd row is equal to the resulting form data
229 """
230 form_data['time'] = str(datetime.datetime.now())
231 formmail2.log_formdata(form_data, log_path)
232 form_data['email'] = 'test@foo.com'
233 formmail2.log_formdata(form_data, log_path)
234 with open(log_path) as csvfile:
235 reader = DictReader(csvfile, fieldnames=form_data.keys())
236 # header
237 reader.next()
238 row1 = reader.next()
239 row2 = reader.next()
240
241 assert row2['email'] == form_data['email']
242 assert row2['email'] != row1['email']
OLDNEW

Powered by Google App Engine
This is Rietveld