def test_response_errors(self): client = Client("http://example.com", fetch_schema=False) User = client.resource_factory( "user", { "type": "object", "properties": {"$uri": {"type": "string", "readOnly": True}, "name": {"type": "string"}}, "links": [ {"rel": "self", "method": "GET", "href": "/user/{id}"}, {"rel": "makeAdmin", "method": "POST", "href": "/user/{id}/make-admin"}, ], }, ) responses.add( responses.GET, "http://example.com/user/1", status=404, json={"status": 404, "message": "Not Found"} ) responses.add( responses.POST, "http://example.com/user/2/make-admin", status=400, json={"status": 400, "message": "Forbidden"}, ) with self.assertRaises(HTTPError) as ctx: User.fetch(1) self.assertEqual(404, ctx.exception.response.status_code) with self.assertRaises(HTTPError) as ctx: User.make_admin(id=2) self.assertEqual(400, ctx.exception.response.status_code)
def test_resource_update_property(self): client = Client('http://example.com/api', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "description": "The description for 'user'.", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [] }) user = User() user.name = 'foo' self.assertEqual('foo', user.name) self.assertEqual('foo', user['name']) self.assertEqual({ "$uri": None, "name": "foo" }, user._properties) with self.assertRaises(AttributeError): user.id = 123
def test_singleton(self): client = Client('http://example.com/api', fetch_schema=False) User = client.resource_factory( 'user', { "type": "object", "description": "The description for 'user'.", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [{ "rel": "self", "href": "/api/user/{id}", "method": "GET" }] }) user_a = User('/api/user/123') user_b = User('/api/user/123') self.assertIs(user_a, user_b) user_c = User(123) self.assertIs(user_a, user_c)
def test_fetch_resource_uri_id(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "self", "method": "GET", "href": "/user/{id}", "schema": { "$ref": "#" } } ] }) # should not result in a fetch: self.assertEqual('/user/123', uri_for(User('/user/123'))) self.assertEqual(123, User('/user/123').id)
def test_resource_update_property(self): client = Client('http://example.com/api', fetch_schema=False) User = client.resource_factory( 'user', { "type": "object", "description": "The description for 'user'.", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [] }) user = User() user.name = 'foo' self.assertEqual('foo', user.name) self.assertEqual('foo', user['name']) self.assertEqual({"$uri": None, "name": "foo"}, user._properties) with self.assertRaises(AttributeError): user.id = 123
def test_decode_reference(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "self", "method": "GET", "href": "/user/{id}" }, { "rel": "instances", "method": "GET", "href": "/user" } ] }) result = json.loads(json.dumps({ "owner": {"$ref": "/user/123"} }), cls=PotionJSONDecoder, client=client) self.assertEqual({ "owner": User(123) }, result)
def test_decode_reference(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory( 'user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [{ "rel": "self", "method": "GET", "href": "/user/{id}" }, { "rel": "instances", "method": "GET", "href": "/user" }] }) result = json.loads(json.dumps({"owner": { "$ref": "/user/123" }}), cls=PotionJSONDecoder, client=client) self.assertEqual({"owner": User(123)}, result)
def test_singleton(self): client = Client('http://example.com/api', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "description": "The description for 'user'.", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "self", "href": "/api/user/{id}", "method": "GET" } ] }) user_a = User('/api/user/123') user_b = User('/api/user/123') self.assertIs(user_a, user_b) user_c = User(123) self.assertIs(user_a, user_c)
def test_fetch_resource_uri_id(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory( 'user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [{ "rel": "self", "method": "GET", "href": "/user/{id}", "schema": { "$ref": "#" } }] }) # should not result in a fetch: self.assertEqual('/user/123', uri_for(User('/user/123'))) self.assertEqual(123, User('/user/123').id)
def test_pagination(self): client = Client("http://example.com", fetch_schema=False) User = client.resource_factory( "user", { "type": "object", "properties": {"$uri": {"type": "string", "readOnly": True}, "name": {"type": "string"}}, "links": [ {"rel": "self", "href": "/user/{id}", "method": "GET"}, { "rel": "instances", "method": "GET", "href": "/user", "schema": { "type": "object", "properties": { "page": {"default": 1, "minimum": 1, "type": "integer"}, "per_page": {"default": 20, "maximum": 100, "minimum": 1, "type": "integer"}, }, }, "target_schema": {"$ref": "#"}, }, ], }, ) def request_callback(request): users = [{"$uri": "/user/{}".format(i), "name": "user-{}".format(i)} for i in range(1, 36)] params = parse_qs(urlparse(request.url).query) offset = (int(params["page"][0]) - 1) * int(params["per_page"][0]) return 200, {"X-Total-Count": "35"}, json.dumps(users[offset : offset + int(params["per_page"][0])]) responses.add_callback( responses.GET, "http://example.com/user", callback=request_callback, content_type="application/json" ) result = User.instances() # TODO test: result = User.instances(where={"foo": {"$gt": 123}}) # TODO magic: result = User.instances.where(foo__gt=123).sort(foo=DESC) self.assertIsInstance(result, PaginatedList) self.assertEqual(35, len(result)) self.assertEqual(1, len(result._pages)) self.assertEqual( [{"$uri": "/user/{}".format(i), "name": "user-{}".format(i)} for i in range(1, 36)], list(result) ) self.assertEqual(2, len(result._pages)) self.assertEqual(20, len(result._pages[1])) self.assertEqual(15, len(result._pages[2]))
def test_first(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory( 'user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [{ "rel": "instances", "method": "GET", "href": "/user", "schema": { "type": "object", "properties": { "page": { "type": "number" }, "per_page": { "type": "number" }, } } }] }) def request_callback(request): if 'missing' in request.url: return 200, {}, '[]' return 200, {}, json.dumps([{"$uri": "/user/1", "name": "foo"}]) responses.add_callback(responses.GET, 'http://example.com/user', callback=request_callback, content_type='application/json') self.assertTrue(User.instances.returns_pagination()) foo = User.first(where={"name": "foo"}) self.assertEqual("foo", foo.name) with self.assertRaises(ItemNotFound): missing = User.first(where={"name": "missing"})
def test_encode_reference(self): client = Client("http://example.com", fetch_schema=False) User = client.resource_factory( "user", { "type": "object", "properties": {"$uri": {"type": "string", "readOnly": True}, "name": {"type": "string"}}, "links": [{"rel": "instances", "method": "GET", "href": "/user"}], }, ) result = json.loads(json.dumps({"owner": User(uri="/user/123", name="foo")}, cls=PotionJSONEncoder)) self.assertEqual({"owner": {"$ref": "/user/123"}}, result)
def test_response_errors(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "self", "method": "GET", "href": "/user/{id}" }, { "rel": "makeAdmin", "method": "POST", "href": "/user/{id}/make-admin" } ] }) responses.add(responses.GET, 'http://example.com/user/1', status=404, json={ "status": 404, "message": "Not Found" }) responses.add(responses.POST, 'http://example.com/user/2/make-admin', status=400, json={ "status": 400, "message": "Forbidden" }) with self.assertRaises(HTTPError) as ctx: User.fetch(1) self.assertEqual(404, ctx.exception.response.status_code) with self.assertRaises(HTTPError) as ctx: User.make_admin(id=2) self.assertEqual(400, ctx.exception.response.status_code)
def test_first(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "instances", "method": "GET", "href": "/user", "schema": { "type": "object", "properties": { "page": {"type": "number"}, "per_page": {"type": "number"}, } } } ] }) def request_callback(request): if 'missing' in request.url: return 200, {}, '[]' return 200, {}, json.dumps([{"$uri": "/user/1", "name": "foo"}]) responses.add_callback(responses.GET, 'http://example.com/user', callback=request_callback, content_type='application/json') self.assertTrue(User.instances.returns_pagination()) foo = User.first(where={"name": "foo"}) self.assertEqual("foo", foo.name) with self.assertRaises(ItemNotFound): missing = User.first(where={"name": "missing"})
def test_subclass_resource(self): client = Client("http://example.com", fetch_schema=False) class CustomResource(Resource): def is_car(self): return self.wheels == 4 Vehicle = client.resource_factory( "vehicle", { "type": "object", "properties": { "$uri": {"type": "string", "readOnly": True}, "name": {"type": "string"}, "wheels": {"type": "number"}, }, "links": [ { "rel": "instances", "method": "GET", "href": "/vehicle", "schema": { "type": "object", "properties": {"page": {"type": "number"}, "per_page": {"type": "number"}}, }, }, {"rel": "self", "method": "GET", "href": "/vehicle/{id}", "schema": {"$ref": "#"}}, ], }, resource_cls=CustomResource, ) self.assertEqual(True, Vehicle(name="Quad", wheels=4).is_car()) self.assertEqual(False, Vehicle(name="Bike", wheels=2).is_car()) responses.add( responses.GET, "http://example.com/vehicle/2", json={"$uri": "/vehicle/2", "name": "Bus", "wheels": 6} ) responses.add( responses.GET, "http://example.com/vehicle", json=[{"$uri": "/vehicle/2", "name": "Bus", "wheels": 6}] ) self.assertEqual(6, Vehicle(2).wheels) self.assertEqual(False, Vehicle(2).is_car()) self.assertEqual([Vehicle(2)], list(Vehicle.instances()))
def test_decode_instance(self): client = Client("http://example.com", fetch_schema=False) User = client.resource_factory( "user", { "type": "object", "properties": {"$uri": {"type": "string", "readOnly": True}, "name": {"type": "string"}}, "links": [{"rel": "instances", "method": "GET", "href": "/user"}], }, ) result = json.loads(json.dumps({"$uri": "/user/123", "name": "foo"}), cls=PotionJSONDecoder, client=client) self.assertEqual(client.instance("/user/123"), result) self.assertEqual("foo", result.name) self.assertEqual(123, result.id)
def test_encode_decode_date(self): client = Client('http://example.com', fetch_schema=False) Event = client.resource_factory('event', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "start_date": { "type": "object", "additionalProperties": False, "properties": { "$date": { "type": "integer" } } } }, "links": [ { "rel": "instances", "method": "GET", "href": "/event" }, { "rel": "create", "method": "POST", "href": "/event", "schema": { "type": "object", "additionalProperties": False, "properties": { "start_date": { "type": "object", "additionalProperties": False, "properties": { "$date": { "type": "integer" } } } } } } ] }) responses.add(responses.GET, 'http://example.com/event', json=[ { "$uri": "/event/1", "start_date": { "$date": 1451060269000 } } ]) events = Event.instances() self.assertEqual(1, len(events)) self.assertEqual({ "$uri": "/event/1", "start_date": datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) }, events[0]._properties) def request_callback(request): request_data = json.loads(request.body) self.assertEqual({ "start_date": { "$date": 1451060269000 } }, request_data) return 201, {}, json.dumps({ "$uri": "/event/2", "start_date": request_data['start_date'] }) responses.add_callback(responses.POST, 'http://example.com/event', callback=request_callback, content_type='application/json') self.assertEqual(False, Event._create.schema.can_include_property('$uri')) self.assertEqual(True, Event._create.schema.can_include_property('start_date')) event = Event() event.start_date = datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) event.save() self.assertEqual(2, event.id) self.assertEqual({ "$uri": "/event/2", "start_date": datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) }, event._properties)
def test_encode_decode_date(self): client = Client('http://example.com', fetch_schema=False) Event = client.resource_factory( 'event', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "start_date": { "type": "object", "additionalProperties": False, "properties": { "$date": { "type": "integer" } } } }, "links": [{ "rel": "instances", "method": "GET", "href": "/event" }, { "rel": "create", "method": "POST", "href": "/event", "schema": { "type": "object", "additionalProperties": False, "properties": { "start_date": { "type": "object", "additionalProperties": False, "properties": { "$date": { "type": "integer" } } } } } }] }) responses.add(responses.GET, 'http://example.com/event', json=[{ "$uri": "/event/1", "start_date": { "$date": 1451060269000 } }]) events = Event.instances() self.assertEqual(1, len(events)) self.assertEqual( { "$uri": "/event/1", "start_date": datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) }, events[0]._properties) def request_callback(request): request_data = json.loads(request.body) self.assertEqual({"start_date": { "$date": 1451060269000 }}, request_data) return 201, {}, json.dumps({ "$uri": "/event/2", "start_date": request_data['start_date'] }) responses.add_callback(responses.POST, 'http://example.com/event', callback=request_callback, content_type='application/json') self.assertEqual(False, Event._create.schema.can_include_property('$uri')) self.assertEqual( True, Event._create.schema.can_include_property('start_date')) event = Event() event.start_date = datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) event.save() self.assertEqual(2, event.id) self.assertEqual( { "$uri": "/event/2", "start_date": datetime(2015, 12, 25, 16, 17, 49, tzinfo=timezone.utc) }, event._properties)
def test_pagination(self): client = Client('http://example.com', fetch_schema=False) User = client.resource_factory('user', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" } }, "links": [ { "rel": "self", "href": "/user/{id}", "method": "GET" }, { "rel": "instances", "method": "GET", "href": "/user", "schema": { "type": "object", "properties": { "page": { "default": 1, "minimum": 1, "type": "integer" }, "per_page": { "default": 20, "maximum": 100, "minimum": 1, "type": "integer" } } }, "target_schema": { "$ref": "#" } } ] }) def request_callback(request): users = [ { "$uri": "/user/{}".format(i), "name": "user-{}".format(i) } for i in range(1, 36) ] params = parse_qs(urlparse(request.url).query) offset = (int(params['page'][0]) - 1) * int(params['per_page'][0]) return 200, {'X-Total-Count': '35'}, json.dumps(users[offset:offset + int(params['per_page'][0])]) responses.add_callback(responses.GET, 'http://example.com/user', callback=request_callback, content_type='application/json') result = User.instances() # TODO test: result = User.instances(where={"foo": {"$gt": 123}}) # TODO magic: result = User.instances.where(foo__gt=123).sort(foo=DESC) self.assertIsInstance(result, PaginatedList) self.assertEqual(35, len(result)) self.assertEqual(1, len(result._pages)) self.assertEqual([ { "$uri": "/user/{}".format(i), "name": "user-{}".format(i) } for i in range(1, 36) ], list(result)) self.assertEqual(2, len(result._pages)) self.assertEqual(20, len(result._pages[1])) self.assertEqual(15, len(result._pages[2]))
def test_subclass_resource(self): client = Client('http://example.com', fetch_schema=False) class CustomResource(Resource): def is_car(self): return self.wheels == 4 Vehicle = client.resource_factory('vehicle', { "type": "object", "properties": { "$uri": { "type": "string", "readOnly": True }, "name": { "type": "string" }, "wheels": { "type": "number" } }, "links": [ { "rel": "instances", "method": "GET", "href": "/vehicle", "schema": { "type": "object", "properties": { "page": {"type": "number"}, "per_page": {"type": "number"}, } } }, { "rel": "self", "method": "GET", "href": "/vehicle/{id}", "schema": { "$ref": "#" } } ] }, resource_cls=CustomResource) self.assertEqual(True, Vehicle(name="Quad", wheels=4).is_car()) self.assertEqual(False, Vehicle(name="Bike", wheels=2).is_car()) responses.add(responses.GET, 'http://example.com/vehicle/2', json={ "$uri": "/vehicle/2", "name": "Bus", "wheels": 6 }) responses.add(responses.GET, 'http://example.com/vehicle', json=[{ "$uri": "/vehicle/2", "name": "Bus", "wheels": 6 }]) self.assertEqual(6, Vehicle(2).wheels) self.assertEqual(False, Vehicle(2).is_car()) self.assertEqual([Vehicle(2)], list(Vehicle.instances()))