def test_validation_decorator(): class Root(Controller): @validate( query1=dict(required=True, type_=int, query=True), field1=dict(required=True, type_=float), field2=dict(required=True, type_=int), field3=dict(required=True, type_=lambda v: v.encode(), min_length=1), ) @action def index(self): query1 = context.query['query1'] field1 = context.form['field1'] field2 = context.form['field2'] field3 = context.form['field3'] yield \ f'{type(query1).__name__}: {query1}, '\ f'{type(field1).__name__}: {field1}, ' \ f'{type(field2).__name__}: {field2}, ' \ f'{type(field3).__name__}: {field3}' with Given( Root(), verb='POST', query=dict(query1=1), form=dict(field1='2.3', field2='2', field3='ab'), ): assert status == 200 assert response.text == 'int: 1, float: 2.3, int: 2, bytes: b\'ab\''
def test_http_multipart_form(): class Root(Controller): @action def index(self): def read_form_field(v): return v.file.read().decode() \ if isinstance(v, cgi.FieldStorage) else v yield context.request_content_type yield ', ' yield ', '.join( f'{k}=' f'{read_form_field(v)}' \ for k, v in sorted(context.form.items()) ) with Given(Root(), verb='POST'): assert status == 200 assert response.text == ', ' when(multipart=dict(a=1, b=2)) assert status == 200 assert response.text == 'multipart/form-data, a=1, b=2' filelike = io.BytesIO(b'abcdef') when(multipart=dict(a=filelike)) assert status == 200 assert response.text == 'multipart/form-data, a=abcdef'
def test_http_url_encoded_form(): class Root(Controller): @action def index(self): yield context.request_content_type yield ', ' yield ', '.join(f'{k}={v}' for k, v in sorted(context.form.items())) with Given(Root(), verb='POST'): assert status == 200 assert response.text == ', ' when(form=dict(a=1, b=2)) assert status == 200 assert response.text == 'application/x-www-form-urlencoded, a=1, b=2' when(body='a') assert status == 200 assert response.text == ', a=' # Duplicated fields when(body='a=1&a=2', content_type='application/x-www-form-urlencoded') assert status == 200 assert response.text == \ 'application/x-www-form-urlencoded, a=[\'1\', \'2\']'
def test_action_decorator_prevent_form(): class Root(Controller): @action(prevent_form=True) def index(self): yield 'default' @action(prevent_form='777 Form Not Allowed Here') def custom_status(self): yield 'custom' with Given(Root(), verb='POST'): assert status == 200 when(body='foo=1') assert status == '400 Form Not Allowed' when('/custom_status', form=dict(a=1)) assert status == 777 when('/custom_status') assert status == 200 # Trying custom verb #123 when(verb='LIST') assert status == 200
def test_json_form(): class Root(Controller): @action def index(self): form = context.form yield context.request_content_type yield ', ' yield ', '.join(f'{k}={v}' for k, v in sorted(form.items())) with Given(Root(), verb='POST', json={}, configuration='debug: false'): assert status == 200 assert response.text == ', ' when(json=dict(a=1, b=2)) assert status == 200 assert response.text == 'application/json, a=1, b=2' # No content length when(body='', content_type='application/json') assert status == 400 assert response.text == 'Content-Length required' when(body='malformed', content_type='application/json', headers={'Content-Length': '9'}) assert status == 400 assert response.text == 'Cannot parse the request'
def test_json_decorator(): class Root(Controller): @json def index(self, a, b): return dict(a=a, b=b) @json def custom(self): class A: def to_dict(self): return dict(c=1) return A() @json def badobject(self): class A: pass return A() with Given(Root(), '/1/2'): assert status == 200 assert response.json == dict(a='1', b='2') assert response.content_type == 'application/json' assert response.encoding == 'utf-8' when('/custom') assert status == 200 assert response.json == dict(c=1) with pytest.raises(ValueError): when('/badobject')
def test_static_controller(make_temp_directory): static = Static(make_temp_directory(a=dict(a1='A1', a2='A2'), b='B'), default_document='b') with Given(static): assert status == 200 assert response.text == 'B' when('/a/a1') assert status == 200 assert response.text == 'A1' when('/a/a2') assert status == 200 assert response.text == 'A2' when('/a/a3') assert status == 404 when('/../') assert status == 403 when('/a/../a/a2') assert status == 200 # When default document is not exists static.default_document = 'BadFile' when('/') assert status == 404 # When default document is not given static.default_document = None when('/') assert status == 404
def test_chunked_streaming(): class Root(Controller): @action @chunked def index(self): yield 'first' yield 'second' @action @chunked('trailer1', 'end') def trailer(self): yield 'first' yield 'second' @action @chunked def error(self): yield 'first' raise Exception('error in streaming') with Given(Root()): assert status == 200 assert response.text == \ '5\r\nfirst\r\n6\r\nsecond\r\n0\r\n\r\n' when('/trailer') assert status == 200 assert response.text == \ '5\r\nfirst\r\n6\r\nsecond\r\n0\r\ntrailer1: end\r\n\r\n' when('/error') assert status == 200 assert response.text == \ '5\r\nfirst\r\n18\r\nerror in streaming0\r\n\r\n'
def test_action_decorator_prevent_empty_form(): class Root(Controller): @action(prevent_empty_form=True) def index(self): yield 'default' @action(prevent_empty_form='777 Form Is Required Here') def custom_status(self): yield 'custom' with Given(Root(), verb='POST', form=dict(a=1)): assert status == 200 when(form={}) assert status == 400 when(form=None) assert status == 400 when('/custom_status', form={}) assert status == 777 when('/custom_status', form=None) assert status == 777 when('/custom_status', form=dict(a=1)) assert status == 200
def test_action_decorator_prevent_form_rest_controller(): class Root(RestController): @action(prevent_form=True) def foo(self): yield 'default' with Given(Root(), verb='foo'): assert status == 200
def test_not_iterable_response(): class Root(Controller): @action def index(self): return 352345352 with pytest.raises(ValueError): Given(Root())
def test_http_not_modified(): class Root(Controller): @action def index(self): raise HTTPNotModified() with Given(Root()): assert status == 304
def test_iterable_pipeline(): class Root(Controller): @action def index(self): return ['a', 'b'] with Given(Root()): assert status == 200 assert response.text == 'ab'
def test_http_status_no_debug_mode_json_content_type(): class Root(Controller): @json def index(self): raise HTTPStatus('603 Bad Happened') with Given(Root(), configuration='debug: false'): assert status == '603 Bad Happened' assert response.json == {}
def test_empty_response(): class Root(Controller): @action def index(self): return None with Given(Root()): assert status == 200 assert response.text == ''
def test_http_status_debug_mode(): class Root(Controller): @action def index(self): raise HTTPStatus('603 Bad Happened') with Given(Root()): assert status == '603 Bad Happened' assert 'traceback' in response.text.casefold()
def test_http_bad_request(): class Root(Controller): @action def index(self): raise HTTPBadRequest('My Bad') with Given(Root(), configuration='debug: false'): assert status == '400 My Bad' assert response.text == 'My Bad'
def test_iterable_but_bad_response(): class Root(Controller): @action def index(self): yield '1' yield 352345352 with pytest.raises(TypeError): Given(Root())
def test_basic_pipeline(): class Root(Controller): @action def index(self): yield f'Index: {context.request_scheme}, {context.request_uri}' with Given(Root()): assert status == 200 assert response.text == 'Index: http, http://bddrest-interceptor/'
def test_http_status_debug_mode_json_content_type(): class Root(Controller): @json def index(self): raise HTTPStatus('603 Bad Happened') with Given(Root()): assert status == '603 Bad Happened' assert 'stackTrace' in response.json
def test_http_redirect(): class Root(Controller): @action def index(self): raise HTTPMovedPermanently('http://example.com') with Given(Root(), configuration='debug: false'): assert status == '301 Moved Permanently' assert response.text == 'Moved Permanently' assert response.headers['Location'] == 'http://example.com'
def test_http_status_no_debug_mode(): class Root(Controller): @action def index(self): raise HTTPStatus('603 Bad Happened') with Given(Root(), configuration='debug: false'): assert status == '603 Bad Happened' assert 'traceback' not in response.text.casefold() assert response.text == 'Bad Happened'
def test_http_success_headers(http_success_exception): class Root(Controller): @action def index(self): context.response_headers['x-app-extra'] = 'yep' raise http_success_exception with Given(Root()): assert status == http_success_exception.status assert response.headers['x-app-extra'] == 'yep'
def test_unhandled_exceptions_no_debug_mode(): class E(Exception): pass class Root(Controller): @action def index(self): raise E() with pytest.raises(E): Given(Root(), configuration='debug: false')
def test_action_decorator_content_type(): class Root(Controller): @action(encoding='utf32', content_type='text/plain') def index(self, a, b): yield f'{a}, {b}' with Given(Root(), '/1/2'): assert status == 200 assert response.encoding == 'utf32' assert response.content_type == 'text/plain' assert response.text == '1, 2'
def test_text_decorator(): class Root(Controller): @text def index(self): yield 'abc' with Given(Root()): assert status == 200 assert response.text == 'abc' assert response.content_type == 'text/plain' assert response.encoding == 'utf-8'
def test_xml_decorator(): class Root(Controller): @xml def index(self): yield '<xml></xml>' with Given(Root()): assert status == 200 assert response.text == '<xml></xml>' assert response.content_type == 'application/xml' assert response.encoding == 'utf-8'
def test_binary_decorator(): class Root(Controller): @binary def index(self): yield b'abc' with Given(Root()): assert status == 200 assert response.body == b'abc' assert response.content_type == 'application/octet' assert response.encoding is None
def test_no_default_handler(): class Root(Controller): @action def foo(self): yield 'Foo' with Given(Root(), '/foo'): assert status == 200 assert response.text == 'Foo' when('/') assert status == 404
def test_action_decorator_verbs(): class Root(Controller): @action(verbs=['get', 'view']) def index(self, a, b): yield f'{a}, {b}' with Given(Root(), '/1/2'): assert status == 200 assert response.text == '1, 2' when(verb='put') assert status == 405