3
# Copyright 2014 Canonical
6
"""Tests for the Simple App base stuff."""
12
from unittest import TestCase
16
from src import scopes
19
class CallTestCase(TestCase):
20
"""Test when calling the class."""
23
self.app = scopes.SimpleApp(config={})
24
self.start_response = Mock()
26
def test_endpoints(self):
27
self.app.error = mock = Mock()
28
mock.return_value = 'error response'
31
'PATH_INFO': '/bad_endpoint', # 'search' or 'preview' only
33
resp = self.app(environ, 'start_response')
34
self.assertEqual(resp, 'error response')
35
mock.assert_called_with('404 NOT FOUND', 'start_response')
37
def test_endpoints_search(self):
38
self.app = scopes.SimpleApp(config={})
39
self.app._get_search_args = check_mock = Mock()
40
validated_args = dict(some='args', foo='bar')
41
check_mock.return_value = validated_args
42
self.app.search = action_mock = Mock()
43
action_mock.return_value = iter([{'resp': 'data'}, [1, 2]])
46
'PATH_INFO': '/search',
49
chunked = self.app(environ, self.start_response)
50
self.assertTrue(isinstance(chunked, types.GeneratorType))
51
response = list(chunked)
52
check_mock.assert_called_with(environ)
53
action_mock.assert_called_with(**validated_args)
54
self.assertEqual(response, ['{"resp": "data"}\r\n', '[1, 2]\r\n'])
55
self.start_response.assert_called_with("200 OK", [
56
('Content-type', 'application/json')])
58
def test_endpoints_preview(self):
59
self.app = scopes.SimpleApp(config={})
60
self.app._get_preview_args = check_mock = Mock()
61
validated_args = dict(some='args', foo='bar')
62
check_mock.return_value = validated_args
63
self.app.preview = action_mock = Mock()
64
action_mock.return_value = iter([{'resp': 'data'}, [1, 2]])
67
'PATH_INFO': '/preview',
70
chunked = self.app(environ, self.start_response)
71
self.assertTrue(isinstance(chunked, types.GeneratorType))
72
response = list(chunked)
73
check_mock.assert_called_with(environ)
74
action_mock.assert_called_with(**validated_args)
75
self.assertEqual(response, ['{"resp": "data"}\r\n', '[1, 2]\r\n'])
76
self.start_response.assert_called_with("200 OK", [
77
('Content-type', 'application/json')])
80
class SearchParamsValidationTestCase(TestCase):
81
"""Test the validation of parameters needed in the search."""
84
self.app = scopes.SimpleApp(config={})
86
def test_simple_ok(self):
87
q = 'q=foo&platform=desktop&country=ar&limit=4&locale=es_AR'
88
resp = self.app._get_search_args({'QUERY_STRING': q})
94
'platform': 'desktop',
100
self.assertEqual(resp, should)
102
def test_query_unicode(self):
103
q = 'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
104
resp = self.app._get_search_args({'QUERY_STRING': q})
110
'platform': 'desktop',
116
self.assertEqual(resp, should)
118
def test_latitude_longitude(self):
120
'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
121
'&latitude=1.2312&longitude=3.13123'
123
resp = self.app._get_search_args({'QUERY_STRING': q})
129
'platform': 'desktop',
132
'longitude': 3.13123,
135
self.assertEqual(resp, should)
137
def test_latitude_only(self):
139
'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
142
msg = "latitude and longitude must be paired, both present or none"
143
with self.assertRaises(ValueError) as cm:
144
self.app._get_search_args({'QUERY_STRING': q})
145
self.assertEqual(str(cm.exception), msg)
147
def test_longitude_only(self):
149
'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
152
msg = "latitude and longitude must be paired, both present or none"
153
with self.assertRaises(ValueError) as cm:
154
self.app._get_search_args({'QUERY_STRING': q})
155
self.assertEqual(str(cm.exception), msg)
157
def test_no_locale_no_country_no_limit(self):
158
q = 'q=mo\xc3\xb1o&platform=desktop'
159
resp = self.app._get_search_args({'QUERY_STRING': q})
164
'locale': scopes.DEFAULT_LOCALE,
165
'platform': 'desktop',
166
'country': scopes.DEFAULT_COUNTRY,
169
'limit': scopes.DEFAULT_LIMIT,
171
self.assertEqual(resp, should)
173
def test_bad_locale(self):
174
q = 'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es|AR'
175
with self.assertRaises(ValueError) as cm:
176
self.app._get_search_args({'QUERY_STRING': q})
177
self.assertEqual(str(cm.exception), 'Bad locale')
179
def test_locale_C(self):
180
q = 'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=C'
181
resp = self.app._get_search_args({'QUERY_STRING': q})
187
'platform': 'desktop',
193
self.assertEqual(resp, should)
196
class PreviewParamsValidationTestCase(TestCase):
197
"""Test the validation of parameters needed in the preview."""
200
self.app = scopes.SimpleApp(config={})
201
self.prev_res_dict = dict(example='foo', stuff=23)
202
self.prev_res = urllib.quote(json.dumps(self.prev_res_dict))
204
def test_simple_ok(self):
206
'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
207
'&result=' + self.prev_res
209
resp = self.app._get_preview_args({'QUERY_STRING': q})
213
'platform': 'desktop',
214
'widgets_api_version': 1,
218
'result': self.prev_res_dict,
220
self.assertEqual(resp, should)
222
def test_latitude_longitude(self):
224
'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
225
'&latitude=1.2312&longitude=3.13123&result=' + self.prev_res
227
resp = self.app._get_preview_args({'QUERY_STRING': q})
231
'platform': 'desktop',
232
'widgets_api_version': 1,
235
'longitude': 3.13123,
236
'result': self.prev_res_dict,
238
self.assertEqual(resp, should)
240
def test_latitude_only(self):
242
'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
243
'&latitude=1.2312&result=' + self.prev_res
245
msg = "latitude and longitude must be paired, both present or none"
246
with self.assertRaises(ValueError) as cm:
247
self.app._get_preview_args({'QUERY_STRING': q})
248
self.assertEqual(str(cm.exception), msg)
250
def test_longitude_only(self):
252
'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
253
'&longitude=1.2312&result=' + self.prev_res
255
msg = "latitude and longitude must be paired, both present or none"
256
with self.assertRaises(ValueError) as cm:
257
self.app._get_preview_args({'QUERY_STRING': q})
258
self.assertEqual(str(cm.exception), msg)
260
def test_no_locale_no_country(self):
261
q = 'platform=desktop&widgets_api_version=1&result=' + self.prev_res
262
resp = self.app._get_preview_args({'QUERY_STRING': q})
265
'locale': scopes.DEFAULT_LOCALE,
266
'platform': 'desktop',
267
'widgets_api_version': 1,
268
'country': scopes.DEFAULT_COUNTRY,
271
'result': self.prev_res_dict,
273
self.assertEqual(resp, should)
275
def test_bad_locale(self):
277
'platform=desktop&locale=es|AR&country=ar&widgets_api_version=1'
278
'&result=' + self.prev_res
280
with self.assertRaises(ValueError) as cm:
281
self.app._get_preview_args({'QUERY_STRING': q})
282
self.assertEqual(str(cm.exception), 'Bad locale')
284
def test_locale_C(self):
286
'platform=desktop&locale=C&country=ar&widgets_api_version=1'
287
'&result=' + self.prev_res
289
resp = self.app._get_preview_args({'QUERY_STRING': q})
293
'platform': 'desktop',
294
'widgets_api_version': 1,
298
'result': self.prev_res_dict,
300
self.assertEqual(resp, should)
302
def test_broken_prev_result(self):
304
'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
307
with self.assertRaises(ValueError) as cm:
308
self.app._get_preview_args({'QUERY_STRING': q})
309
self.assertEqual(str(cm.exception), 'Broken previous result')
312
class HelpersTestCase(TestCase):
313
"""Test some helper methods."""
316
self.app = scopes.SimpleApp(config={})
317
self.start_response = Mock()
319
def test_error_sanity(self):
320
resp = self.app.error("400 test", self.start_response,
322
should_error_message = json.dumps(
323
{'error': '400 test', 'error_msg': 'test message'}, indent=4)
325
self.assertEqual(resp, [should_error_message])
326
should_status = "400 test"
328
('Content-type', "application/json"),
329
('Content-Length', str(len(should_error_message))),
331
self.start_response.assert_called_with(should_status, should_headers)