~davidc3/ubuntu-rest-scopes/testing-newyorktimes

« back to all changes in this revision

Viewing changes to src/scopes/tests/test_base.py

  • Committer: David Callé
  • Date: 2014-02-11 09:16:57 UTC
  • mfrom: (3.1.15 ubuntu-rest-scopes)
  • Revision ID: davidc@framli.eu-20140211091657-2759quotvgxqg318
Merge trunk, fix conflitcts, add secrets config

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf8 -*-
 
2
 
 
3
# Copyright 2014 Canonical
 
4
# All Rights Reserved
 
5
 
 
6
"""Tests for the Simple App base stuff."""
 
7
 
 
8
import json
 
9
import types
 
10
import urllib
 
11
 
 
12
from unittest import TestCase
 
13
 
 
14
from mock import Mock
 
15
 
 
16
from src import scopes
 
17
 
 
18
 
 
19
class CallTestCase(TestCase):
 
20
    """Test when calling the class."""
 
21
 
 
22
    def setUp(self):
 
23
        self.app = scopes.SimpleApp(config={})
 
24
        self.start_response = Mock()
 
25
 
 
26
    def test_endpoints(self):
 
27
        self.app.error = mock = Mock()
 
28
        mock.return_value = 'error response'
 
29
 
 
30
        environ = {
 
31
            'PATH_INFO': '/bad_endpoint',  # 'search' or 'preview' only
 
32
        }
 
33
        resp = self.app(environ, 'start_response')
 
34
        self.assertEqual(resp, 'error response')
 
35
        mock.assert_called_with('404 NOT FOUND', 'start_response')
 
36
 
 
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]])
 
44
 
 
45
        environ = {
 
46
            'PATH_INFO': '/search',
 
47
            'FOO': 'bar',
 
48
        }
 
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')])
 
57
 
 
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]])
 
65
 
 
66
        environ = {
 
67
            'PATH_INFO': '/preview',
 
68
            'FOO': 'bar',
 
69
        }
 
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')])
 
78
 
 
79
 
 
80
class SearchParamsValidationTestCase(TestCase):
 
81
    """Test the validation of parameters needed in the search."""
 
82
 
 
83
    def setUp(self):
 
84
        self.app = scopes.SimpleApp(config={})
 
85
 
 
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})
 
89
        should = {
 
90
            'query': u'foo',
 
91
            'session_id': None,
 
92
            'query_id': None,
 
93
            'locale': 'es_AR',
 
94
            'platform': 'desktop',
 
95
            'country': 'ar',
 
96
            'latitude': None,
 
97
            'longitude': None,
 
98
            'limit': 4,
 
99
        }
 
100
        self.assertEqual(resp, should)
 
101
 
 
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})
 
105
        should = {
 
106
            'query': u'moño',
 
107
            'session_id': None,
 
108
            'query_id': None,
 
109
            'locale': 'es_AR',
 
110
            'platform': 'desktop',
 
111
            'country': 'ar',
 
112
            'latitude': None,
 
113
            'longitude': None,
 
114
            'limit': 4,
 
115
        }
 
116
        self.assertEqual(resp, should)
 
117
 
 
118
    def test_latitude_longitude(self):
 
119
        q = (
 
120
            'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
 
121
            '&latitude=1.2312&longitude=3.13123'
 
122
        )
 
123
        resp = self.app._get_search_args({'QUERY_STRING': q})
 
124
        should = {
 
125
            'query': u'moño',
 
126
            'session_id': None,
 
127
            'query_id': None,
 
128
            'locale': 'es_AR',
 
129
            'platform': 'desktop',
 
130
            'country': 'ar',
 
131
            'latitude': 1.2312,
 
132
            'longitude': 3.13123,
 
133
            'limit': 4,
 
134
        }
 
135
        self.assertEqual(resp, should)
 
136
 
 
137
    def test_latitude_only(self):
 
138
        q = (
 
139
            'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
 
140
            '&latitude=1.2312'
 
141
        )
 
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)
 
146
 
 
147
    def test_longitude_only(self):
 
148
        q = (
 
149
            'q=mo\xc3\xb1o&platform=desktop&country=ar&limit=4&locale=es_AR'
 
150
            '&longitude=1.2312'
 
151
        )
 
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)
 
156
 
 
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})
 
160
        should = {
 
161
            'query': u'moño',
 
162
            'session_id': None,
 
163
            'query_id': None,
 
164
            'locale': scopes.DEFAULT_LOCALE,
 
165
            'platform': 'desktop',
 
166
            'country': scopes.DEFAULT_COUNTRY,
 
167
            'latitude': None,
 
168
            'longitude': None,
 
169
            'limit': scopes.DEFAULT_LIMIT,
 
170
        }
 
171
        self.assertEqual(resp, should)
 
172
 
 
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')
 
178
 
 
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})
 
182
        should = {
 
183
            'query': u'moño',
 
184
            'session_id': None,
 
185
            'query_id': None,
 
186
            'locale': 'en_US',
 
187
            'platform': 'desktop',
 
188
            'country': 'ar',
 
189
            'latitude': None,
 
190
            'longitude': None,
 
191
            'limit': 4,
 
192
        }
 
193
        self.assertEqual(resp, should)
 
194
 
 
195
 
 
196
class PreviewParamsValidationTestCase(TestCase):
 
197
    """Test the validation of parameters needed in the preview."""
 
198
 
 
199
    def setUp(self):
 
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))
 
203
 
 
204
    def test_simple_ok(self):
 
205
        q = (
 
206
            'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
 
207
            '&result=' + self.prev_res
 
208
        )
 
209
        resp = self.app._get_preview_args({'QUERY_STRING': q})
 
210
        should = {
 
211
            'session_id': None,
 
212
            'locale': 'es_AR',
 
213
            'platform': 'desktop',
 
214
            'widgets_api_version': 1,
 
215
            'country': 'ar',
 
216
            'latitude': None,
 
217
            'longitude': None,
 
218
            'result': self.prev_res_dict,
 
219
        }
 
220
        self.assertEqual(resp, should)
 
221
 
 
222
    def test_latitude_longitude(self):
 
223
        q = (
 
224
            'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
 
225
            '&latitude=1.2312&longitude=3.13123&result=' + self.prev_res
 
226
        )
 
227
        resp = self.app._get_preview_args({'QUERY_STRING': q})
 
228
        should = {
 
229
            'session_id': None,
 
230
            'locale': 'es_AR',
 
231
            'platform': 'desktop',
 
232
            'widgets_api_version': 1,
 
233
            'country': 'ar',
 
234
            'latitude': 1.2312,
 
235
            'longitude': 3.13123,
 
236
            'result': self.prev_res_dict,
 
237
        }
 
238
        self.assertEqual(resp, should)
 
239
 
 
240
    def test_latitude_only(self):
 
241
        q = (
 
242
            'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
 
243
            '&latitude=1.2312&result=' + self.prev_res
 
244
        )
 
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)
 
249
 
 
250
    def test_longitude_only(self):
 
251
        q = (
 
252
            'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
 
253
            '&longitude=1.2312&result=' + self.prev_res
 
254
        )
 
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)
 
259
 
 
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})
 
263
        should = {
 
264
            'session_id': None,
 
265
            'locale': scopes.DEFAULT_LOCALE,
 
266
            'platform': 'desktop',
 
267
            'widgets_api_version': 1,
 
268
            'country': scopes.DEFAULT_COUNTRY,
 
269
            'latitude': None,
 
270
            'longitude': None,
 
271
            'result': self.prev_res_dict,
 
272
        }
 
273
        self.assertEqual(resp, should)
 
274
 
 
275
    def test_bad_locale(self):
 
276
        q = (
 
277
            'platform=desktop&locale=es|AR&country=ar&widgets_api_version=1'
 
278
            '&result=' + self.prev_res
 
279
        )
 
280
        with self.assertRaises(ValueError) as cm:
 
281
            self.app._get_preview_args({'QUERY_STRING': q})
 
282
            self.assertEqual(str(cm.exception), 'Bad locale')
 
283
 
 
284
    def test_locale_C(self):
 
285
        q = (
 
286
            'platform=desktop&locale=C&country=ar&widgets_api_version=1'
 
287
            '&result=' + self.prev_res
 
288
        )
 
289
        resp = self.app._get_preview_args({'QUERY_STRING': q})
 
290
        should = {
 
291
            'session_id': None,
 
292
            'locale': 'en_US',
 
293
            'platform': 'desktop',
 
294
            'widgets_api_version': 1,
 
295
            'country': 'ar',
 
296
            'latitude': None,
 
297
            'longitude': None,
 
298
            'result': self.prev_res_dict,
 
299
        }
 
300
        self.assertEqual(resp, should)
 
301
 
 
302
    def test_broken_prev_result(self):
 
303
        q = (
 
304
            'platform=desktop&locale=es_AR&country=ar&widgets_api_version=1'
 
305
            '&result=|no|json|'
 
306
        )
 
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')
 
310
 
 
311
 
 
312
class HelpersTestCase(TestCase):
 
313
    """Test some helper methods."""
 
314
 
 
315
    def setUp(self):
 
316
        self.app = scopes.SimpleApp(config={})
 
317
        self.start_response = Mock()
 
318
 
 
319
    def test_error_sanity(self):
 
320
        resp = self.app.error("400 test", self.start_response,
 
321
                              "test message")
 
322
        should_error_message = json.dumps(
 
323
            {'error': '400 test', 'error_msg': 'test message'}, indent=4)
 
324
 
 
325
        self.assertEqual(resp, [should_error_message])
 
326
        should_status = "400 test"
 
327
        should_headers = [
 
328
            ('Content-type', "application/json"),
 
329
            ('Content-Length', str(len(should_error_message))),
 
330
        ]
 
331
        self.start_response.assert_called_with(should_status, should_headers)