def test_get_resource(): request = MockRequest(body='{"$": "tests.User", "id":10, "name": "Dave"}') request.request_codec = json_codec user = helpers.get_resource(request, User) assert isinstance(user, User) assert user.id == 10 assert user.name == 'Dave'
def test_get_resource__multiple(): request = MockRequest( body='[{"$": "tests.User", "id":10, "name": "Dave"}]') request.request_codec = json_codec users = helpers.get_resource(request, User, allow_multiple=True) assert len(users) == 1 user = users[0] assert isinstance(user, User) assert user.id == 10 assert user.name == 'Dave'
def test_bind_to_instance(self): @decorators.Operation(tags=('eek', 'bar')) def target(binding, request): """ Test target """ assert binding == api return 'foo' class MockApi(object): def __init__(self): self.call_count = defaultdict(int) self.resource = User self.tags = {'bar'} def pre_dispatch(self, request, path_args): self.call_count['pre_dispatch'] += 1 def post_dispatch(self, request, response): self.call_count['post_dispatch'] += 1 return response api = MockApi() request = MockRequest() target.bind_to_instance(api) assert target.binding == api assert target.resource is User assert target.is_bound assert target.tags == {'eek', 'bar'} actual = target(request, {}) assert actual == 'foo' assert api.call_count == {'pre_dispatch': 1, 'post_dispatch': 1}
def test_no_body_custom_status(self): request = MockRequest() actual = helpers.create_response(request, status=HTTPStatus.CREATED) assert isinstance(actual, HttpResponse) assert actual.status == HTTPStatus.CREATED assert actual.body is None
def test_dispatch__with_middleware(self): calls = [] class Middleware(object): def pre_request(self, request, path_args): calls.append('pre_request') def pre_dispatch(self, request, path_args): calls.append('pre_dispatch') path_args['foo'] = 'bar' def post_dispatch(self, request, response): calls.append('post_dispatch') return 'eek' + response def post_request(self, request, response): calls.append('post_request') response['test'] = 'header' return response def callback(request, **args): assert args['foo'] == 'bar' return 'boo' target = containers.ApiInterfaceBase(middleware=[Middleware()]) operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.body == '"eekboo"' assert actual.status == 200 assert 'test' in actual.headers assert calls == [ 'pre_request', 'pre_dispatch', 'post_dispatch', 'post_request' ]
def test_no_body(self): request = MockRequest() actual = helpers.create_response(request) assert isinstance(actual, HttpResponse) assert actual.status == HTTPStatus.NO_CONTENT assert actual.body is None
def test_execute(self): @decorators.ResourceOperation(resource=User) def my_func(request, user): assert isinstance(user, User) assert user.name == "Stephen" request = MockRequest(body='{"id": 1, "name": "Stephen"}') my_func(request, {})
def test_get_resource__codec_exceptions(body, error_code): request = MockRequest(body=body) with pytest.raises(HttpError) as exc_info: helpers.get_resource(request, User) assert exc_info.value.status == HTTPStatus.BAD_REQUEST assert exc_info.value.resource.code == error_code
def test_dispatch__exceptions(self, error, status): def callback(request): raise error target = containers.ApiInterfaceBase() operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.status == status
def test_content(self): request = MockRequest() actual = helpers.create_response(request, {"foo": "bar"}) assert isinstance(actual, HttpResponse) assert actual.status == HTTPStatus.OK assert actual.headers['Content-Type'] == json_codec.CONTENT_TYPE assert json_codec.json.loads(actual.body) == {"foo": "bar"}
def test_dispatch__error_with_debug_enabled(self): def callback(request): raise ValueError() target = containers.ApiInterfaceBase(debug_enabled=True) operation = Operation(callback) with pytest.raises(ValueError): target.dispatch(operation, MockRequest())
def test_execute__invalid(self): @decorators.ResourceOperation(resource=User) def my_func(request, user): assert isinstance(user, User) assert user.name == "Stephen" request = MockRequest(body='{"id": 1, "name": "Stephen"') with pytest.raises(HttpError): my_func(request, {})
def test_dispatch__http_response(self): def callback(request): return HttpResponse("eek") target = containers.ApiInterfaceBase() operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.body == 'eek' assert actual.status == 200
def test_dispatch__encode_error_with_debug_enabled(self): def callback(request): raise api.ImmediateHttpResponse(ValueError, HTTPStatus.NOT_MODIFIED, {}) target = containers.ApiInterfaceBase(debug_enabled=True) operation = Operation(callback) with pytest.raises(TypeError): target.dispatch(operation, MockRequest())
def test_request_headers(self, cors_config, expected): api_interface = ApiInterfaceBase(mock_endpoint) cors.CORS(api_interface, **cors_config) target = api_interface.middleware[0] http_request = MockRequest(headers={'Origin': 'http://my-domain.org'}, current_operation=mock_endpoint) actual = target.request_headers(http_request) assert expected == actual
def test_no_key(self): request = MockRequest.from_uri('/foo/bar') target = signing.FixedSignedAuth(None) @Operation(path=UrlPath.parse('/foo/bar'), middleware=[target]) def callback(request): return 'ok' with pytest.raises(PermissionDenied): callback(request, {})
def test_bad_values(self, options, query, expected_errors): mock_request = MockRequest(query=query) @decorators.ListOperation(**options) def my_func(request, **kwargs): return [1, 2, 3] with pytest.raises(ValidationError) as error: my_func(mock_request, {'foo': 'bar'}) assert len(error.value.error_messages) == expected_errors
def test_error(self, url, kwargs): request = MockRequest.from_uri('/foo/bar') target = signing.FixedSignedAuth(base64.b32decode('DEADBEEF')) @Operation(path=UrlPath.parse('/foo/bar'), middleware=[target]) def callback(request): return 'ok' with pytest.raises(PermissionDenied): callback(request, {})
def test_valid_signature(self, uri): request = MockRequest.from_uri(uri) target = signing.FixedSignedAuth(base64.b32decode('DEADBEEF')) @Operation(path=UrlPath.parse('/foo/bar'), middleware=[target]) def callback(r): return 'ok' actual = callback(request, {}) assert actual == 'ok'
def test_pre_flight_headers(self, cors_config, expected): api_interface = ApiInterfaceBase(mock_endpoint) cors.CORS(api_interface, **cors_config) target = api_interface.middleware[0] http_request = MockRequest(headers={'Origin': 'http://my-domain.org'}, current_operation=mock_endpoint) actual = target.pre_flight_headers(http_request, mock_endpoint.methods) assert 'GET, HEAD' == actual.pop('Allow') assert 'no-cache, no-store' == actual.pop('Cache-Control') assert expected == actual
def test_dispatch__error_handled_by_middleware_raises_exception(self): class ErrorMiddleware(object): def handle_500(self, request, exception): assert isinstance(exception, ValueError) raise ValueError def callback(request): raise ValueError() target = containers.ApiInterfaceBase(middleware=[ErrorMiddleware()]) operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.status == 500
def test_post_request(self, origins, method, expected): api_interface = ApiInterfaceBase(mock_endpoint) cors.CORS(api_interface, origins=origins) target = api_interface.middleware[0] http_request = MockRequest(headers={'Origin': 'http://my-domain.org'}, method=method, current_operation=mock_endpoint) http_response = HttpResponse('') actual = target.post_request(http_request, http_response) assert actual is http_response assert expected == actual.headers.get('Access-Control-Allow-Origin')
def test_dispatch__error_handled_by_middleware(self): class ErrorMiddleware(object): def handle_500(self, request, exception): assert isinstance(exception, ValueError) return Error.from_status(HTTPStatus.SEE_OTHER, 0, "Quick over there...") def callback(request): raise ValueError() target = containers.ApiInterfaceBase(middleware=[ErrorMiddleware()]) operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.status == 303
def test_unbound(self): @decorators.Operation(tags=('eek', 'bar')) def target(request): """ Test target """ return 'foo' request = MockRequest() assert target.resource is None assert not target.is_bound assert target.tags == {'eek', 'bar'} actual = target(request, {}) assert actual == 'foo'
def test_cors_options(self, origins, expected): api_interface = ApiInterfaceBase(mock_endpoint) cors.CORS(api_interface, origins=origins) target = api_interface.middleware[0] http_request = MockRequest(headers={'Origin': 'http://my-domain.org'}, method=Method.OPTIONS) cors._MethodsMiddleware( (Method.GET, Method.HEAD)).pre_dispatch(http_request, None) actual = target.cors_options(http_request) assert isinstance(actual, HttpResponse) assert 'GET, HEAD' == actual.headers.pop('Allow') assert 'no-cache, no-store' == actual.headers.pop('Cache-Control') assert expected == actual.headers.get('Access-Control-Allow-Origin')
def test_dispatch__with_middleware_pre_request_response(self): """ Test scenario where pre-request hook returns a HTTP Response object """ class Middleware(object): def pre_request(self, request, path_args): return HttpResponse('eek!', status=HTTPStatus.FORBIDDEN) def callback(request, **args): assert False, "Response should have already occurred!" target = containers.ApiInterfaceBase(middleware=[Middleware()]) operation = Operation(callback) actual = target.dispatch(operation, MockRequest()) assert actual.body == 'eek!' assert actual.status == 403
def test_returning_total_count(self): mock_request = MockRequest() @decorators.ListOperation def my_func(request, foo, offset, limit): assert foo == 'bar' assert offset == 0 assert limit == 50 return [1, 2, 3], 5 result = my_func(mock_request, {'foo': 'bar'}) assert isinstance(result, HttpResponse) assert result.body == '[1, 2, 3]' assert result['X-Page-Offset'] == '0' assert result['X-Page-Limit'] == '50' assert result['X-Total-Count'] == '5'
def test_returning_total_count(self): mock_request = MockRequest() @decorators.WrappedListOperation def my_func(request, foo, offset, limit): assert foo == 'bar' assert offset == 0 assert limit == 50 return [1, 2, 3], 5 result = my_func(mock_request, {'foo': 'bar'}) assert isinstance(result, decorators.Listing) assert result.results == [1, 2, 3] assert result.offset == 0 assert result.limit == 50 assert result.total_count == 5
def test_options_handled(self, options, query, offset, limit): mock_request = MockRequest(query=query) @decorators.ListOperation(**options) def my_func(request, **kwargs): assert request is mock_request assert kwargs['offset'] == offset assert kwargs['limit'] == limit assert kwargs['foo'] == 'bar' return [1, 2, 3] result = my_func(mock_request, {'foo': 'bar'}) assert isinstance(result, HttpResponse) assert result.body == '[1, 2, 3]' assert result['X-Page-Offset'] == str(offset) assert result['X-Page-Limit'] == str(limit) assert 'X-Total-Count' not in result.headers
def test_options_handled(self, options, query, offset, limit, bare): mock_request = MockRequest(query=query) @decorators.WrappedListOperation(**options) def my_func(request, **kwargs): assert request is mock_request assert kwargs['offset'] == offset assert kwargs['limit'] == limit assert kwargs['foo'] == 'bar' return [1, 2, 3] result = my_func(mock_request, {'foo': 'bar'}) if bare: assert result == [1, 2, 3] else: assert isinstance(result, decorators.Listing) assert result.results == [1, 2, 3] assert result.offset == offset assert result.limit == limit assert result.total_count is None