forked from dave-shawley/tornado-problem-details
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtests.py
More file actions
154 lines (124 loc) · 6 KB
/
tests.py
File metadata and controls
154 lines (124 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import json
try:
from urllib.parse import urlencode
except ImportError: # pragma: no cover
from urllib import urlencode
from tornado import httputil, testing, web
from problemdetails import handlers
import problemdetails
class Application(web.Application):
def __init__(self, **settings):
super(Application, self).__init__([web.url('/', Handler)], settings)
class Handler(problemdetails.ErrorWriter, web.RequestHandler):
def get(self):
sentinel = object() # safely detect missing query params
status = int(self.get_query_argument('status', default='200'))
raise_error = self.get_query_argument('raise_error', default=sentinel)
if raise_error is not sentinel:
query_args = [
arg for arg in self.request.query_arguments.keys()
if arg not in ('raise_error', 'status')
]
kwargs = {}
for name in query_args:
kwargs[name] = self.get_query_argument(name)
if kwargs[name].lower() == 'none':
kwargs[name] = None
elif kwargs[name].startswith(('{', '[')):
kwargs[name] = json.loads(kwargs[name])
raise problemdetails.Problem(status_code=status, **kwargs)
else:
kwargs = {}
for name in ('detail', 'instance', 'title', 'type'):
value = self.get_query_argument(name, sentinel)
if value is not sentinel:
if value.lower() == 'none':
value = None
kwargs[name] = value
if status not in httputil.responses:
kwargs['reason'] = 'Abnormal Status'
self.send_error(status, **kwargs)
class ErrorWriterTests(testing.AsyncHTTPTestCase):
def setUp(self):
super(ErrorWriterTests, self).setUp()
self._original_content_type = (
handlers.ErrorWriter.PROBLEM_DETAILS_MIME_TYPE)
def tearDown(self):
super(ErrorWriterTests, self).tearDown()
handlers.ErrorWriter.PROBLEM_DETAILS_MIME_TYPE = (
self._original_content_type)
def get_app(self):
return Application()
def send_query(self, **query):
return self.fetch('/?{0}'.format(urlencode(query)))
def test_that_send_error_sets_content_type(self):
response = self.send_query(status=500)
self.assertEqual(response.code, 500)
self.assertEqual(response.headers['Content-Type'],
'application/problem+json')
def test_that_send_error_includes_status(self):
response = self.send_query(status=500)
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['status'], 500)
def test_that_send_error_sets_type_to_rfc_url(self):
response = self.send_query(status=500)
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['type'],
handlers.type_link_map[response.code])
self.assertEqual(body['type'],
'https://tools.ietf.org/html/rfc7231#section-6.6.1')
def test_that_type_is_not_set_for_unknown_status_code(self):
response = self.send_query(status=600)
self.assertEqual(response.code, 600)
body = json.loads(response.body.decode('utf-8'))
self.assertNotIn('type', body)
def test_that_type_can_be_overridden(self):
response = self.send_query(
status=500, type='http://example.com/errors#500')
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['type'], 'http://example.com/errors#500')
def test_that_title_can_be_set(self):
response = self.send_query(status=500, title='Uh oh')
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['title'], 'Uh oh')
def test_that_instance_can_be_set(self):
response = self.send_query(
status=500, instance='http://example.com/probs/out-of-credit')
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['instance'],
'http://example.com/probs/out-of-credit')
def test_that_detail_can_be_set(self):
response = self.send_query(status=500, detail='something bad happened')
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['detail'], 'something bad happened')
def test_that_instance_can_be_null(self):
response = self.send_query(status=500, instance=None)
body = json.loads(response.body.decode('utf-8'))
self.assertIsNone(body['instance'], repr(body))
def test_that_content_type_can_be_set(self):
handlers.ErrorWriter.PROBLEM_DETAILS_MIME_TYPE = 'application/json'
response = self.send_query()
self.assertEqual(response.headers['Content-Type'], 'application/json')
class ProblemTests(ErrorWriterTests):
def get_app(self):
return Application()
def send_query(self, **query):
query['raise_error'] = True
return self.fetch('/?{0}'.format(urlencode(query)))
def test_that_custom_attributes_can_be_set(self):
response = self.send_query(
status=401, custom=json.dumps({'a': ['list']}))
body = json.loads(response.body.decode('utf-8'))
self.assertEqual(body['custom'], {'a': ['list']}, repr(body['custom']))
def test_that_http_reason_added_for_nonstandard_response_codes(self):
response = self.send_query(status=600)
self.assertEqual(response.code, 600)
self.assertEqual(response.reason, 'Abnormal Status')
def test_that_reason_param_is_dropped_from_body(self):
response = self.send_query(status=401, reason='whatever')
body = json.loads(response.body.decode('utf-8'))
self.assertNotIn('reason', body)
def test_that_log_message_param_is_dropped_from_body(self):
response = self.send_query(status=401, log_message='whatever')
body = json.loads(response.body.decode('utf-8'))
self.assertNotIn('log_message', body)