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

Delta Between Two Patch Sets: sitescripts/reports/tests/test_updateReport.py

Issue 29993614: Issue 2267 - Unify form handling by reusing form_handler() (Closed) Base URL: https://hg.adblockplus.org/sitescripts/
Left Patch Set: Created Jan. 30, 2019, 11:43 p.m.
Right Patch Set: Remove unnecessary checks Created Feb. 8, 2019, 1:32 a.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 | « no previous file | sitescripts/reports/web/updateReport.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) 2017-present eyeo GmbH 2 # Copyright (C) 2017-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 import sys
16 from urllib import urlencode 17 from urllib import urlencode
17 from urllib2 import urlopen, HTTPError 18 from urllib2 import urlopen, HTTPError
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
24 # We are mocking the functions that use MySQLdb, so it is not needed. This
25 # is to prevent the tests from crashing when they try to import it.
26 sys.modules['MySQLdb'] = sys
23 from sitescripts.reports.web.updateReport import handleRequest 27 from sitescripts.reports.web.updateReport import handleRequest
24 28
25 HOST = 'localhost' 29 LOCAL_HOST = 'test.local'
26 PORT = 3306 30 REMOTE_HOST = 'reports.adblockplus.org'
31 PORT = 80
32 PLAINTEXT_GUID = '12345678-1234-1234-1234-123456789abc'
33 UR_PATH = 'sitescripts.reports.web.updateReport.'
27 34
28 PLAINTEXT_GUID = '12345678-1234-1234-1234-123456789abc' 35
36 def intercept_fn(environ, start_response):
37 assert environ['SERVER_NAME'] == REMOTE_HOST
38 assert PLAINTEXT_GUID in environ['PATH_INFO']
39 return 'Intercepted!'
29 40
30 41
31 @pytest.fixture 42 @pytest.fixture
32 def response_for(): 43 def response_for():
33 """ Registers two intercepts, returns responses for them based on bool """ 44 """Register two intercepts, and return responses for them."""
34 urllib_intercept.install_opener() 45 urllib_intercept.install_opener()
35 add_wsgi_intercept(HOST, PORT, lambda: handleRequest, 46 add_wsgi_intercept(LOCAL_HOST, PORT, lambda: handleRequest)
36 script_name='test script_name') 47 add_wsgi_intercept(REMOTE_HOST, 443, lambda: intercept_fn)
37 48
38 def response_for(data): 49 def response_for(data):
39 url = 'http://{}:{}'.format(HOST, PORT) 50 url = 'http://{}:{}'.format(LOCAL_HOST, PORT)
40 if data is None: 51 response = urlopen(url, urlencode(data))
41 response = urlopen(url)
42 else:
43 response = urlopen(url, urlencode(data))
44 return response.code, response.read() 52 return response.code, response.read()
45 53
46 yield response_for 54 yield response_for
47 remove_wsgi_intercept() 55 remove_wsgi_intercept()
48 56
49 57
50 @pytest.fixture 58 @pytest.fixture
51 def form_data(): 59 def form_data():
52 return { 60 return {
53 'email': 'john_doe@gmail.com', 61 'email': 'jane_doe@example.com',
54 'secret': '92b3e705f2abe74c20c1c5ea9abd9ba2', 62 'secret': '92b3e705f2abe74c20c1c5ea9abd9ba2',
55 'guid': PLAINTEXT_GUID, 63 'guid': PLAINTEXT_GUID,
56 'status': 'test STATUS', 64 'status': 'x' * 1025,
57 'usefulness': 'test USEFULNESS', 65 'usefulness': 0,
58 'notify': 'test NOTIFY' 66 'notify': 'test NOTIFY',
67 'message': 'test MESSAGE',
68 'subject': 'test SUBJECT',
69 'name': 'test NAME',
59 } 70 }
60 71
61 72
62 @pytest.mark.parametrize('field,message', [ 73 @pytest.mark.parametrize('field,message', [
63 (('guid', ''), 'Invalid or missing report GUID'), 74 (('guid', 'badGUID'), 'Invalid or missing report GUID'),
64 (('secret', ''), 'Wrong secret value'), 75 (('secret', 'badSECRET'), 'Wrong secret value'),
65 ]) 76 ])
66 def test_http_errs(field, message, response_for, form_data): 77 def test_http_errs(field, message, response_for, form_data, mocker):
78 mocker.patch(UR_PATH + 'getReport', new=lambda *args: {'usefulness': 1})
67 key, value = field 79 key, value = field
68 form_data[key] = value 80 form_data[key] = value
69 with pytest.raises(HTTPError) as error: 81 with pytest.raises(HTTPError) as error:
70 response_for(form_data) 82 response_for(form_data)
71 83
72 assert message in error.value.read() 84 assert message in error.value.read()
73 85
74 86
75 def test_success(response_for, form_data): 87 def test_success(response_for, form_data, mocker):
76 assert response_for(form_data) == 'test RESULT' 88 # These methods are patched to avoid the need for a MySQL database
89 mocker.patch(UR_PATH + 'getReport', new=lambda *args: {'usefulness': 1,
90 'email': 'jane_doe@example.com'})
91 sr_mock = mocker.patch(UR_PATH + 'saveReport')
92 uuu_mock = mocker.patch(UR_PATH + 'updateUserUsefulness')
93 sun_mock = mocker.patch(UR_PATH + 'sendUpdateNotification')
94
95 assert response_for(form_data) == (200, '\nIntercepted!')
96
97 assert sr_mock.call_count == 1
98 for key in ['usefulness', 'email']:
99 assert key in sr_mock.call_args[0][1]
100 assert sr_mock.call_args[0][1][key] == str(form_data[key])
101
102 assert '0' in uuu_mock.call_args[0] and 1 in uuu_mock.call_args[0]
103
104 for key in ['email', 'status']:
105 assert key in sun_mock.call_args[0][0]
106 assert sun_mock.call_args[0][0]['email'] == form_data['email']
107
108 # These should not be equal, because updateReport.py strips characters
109 # over 1024, and form_data['status'] has 1025.
110 assert str(sr_mock.call_args[0][1]['status']) != form_data['status']
111 assert str(sun_mock.call_args[0][0]['status']) != form_data['status']
112
113
114 def test_get_report_error(response_for, form_data, mocker):
115 mocker.patch(UR_PATH + 'getReport', new=lambda *args: None)
116 with pytest.raises(HTTPError) as error:
117 response_for(form_data)
118
119 assert 'Report does not exist' in error.value.read()
LEFTRIGHT

Powered by Google App Engine
This is Rietveld