def test_required_together_validator(self): resource = RequiredCarTestResource(Car()) good = validate(mock_context(), 'RequiredTogether', resource, {}) self.assertEqual(good, {}) bad = validate(mock_context(), 'RequiredTogether', resource, {'make': 'Tesla'}) self.assertEqual(bad, {'RequiredTogether': [u'Make and year are required if either is provided.']}) bad = validate(mock_context(), 'RequiredTogether', resource, {'year': 2012}) self.assertEqual(bad, {'RequiredTogether': [u'Make and year are required if either is provided.']})
def test_put_with_good_sha(self): user = User() resource = AddressableUserResource(user) resource.get = lambda *args: {"age": 20, "name": "Bob"} request = self.make_request('{"age": 20, "name": "Bob"}', 'fd92376f24d6a75974c8da6edf84a834b92ee13c') response = views._process_put(mock_context(), resource, request) self.assertEqual(response.status_code, 204)
def test_put_with_bad_sha(self): user = User() resource = AddressableUserResource(user) resource.get = lambda *args: {"age": 20, "name": "Bob"} request = self.make_request('{"age": 20, "name": "Bob"}', 'OmManePadmeHumOmManePadmeHumOmManePadmeHum') response = views._process_put(mock_context(), resource, request) self.assertEqual(response.status_code, 412)
def test_get_batch(self): root_resource = self.create_root_resource_with_children( r'^api/v2/(?P<base_resource>.*)$', methods=['GET'], result={'name': 'value'}) request_data = { "data": [ self._generate_batch_partial( 'get', 'http://localhost:8081/api/v2/child/grandchild', {'business_id': 12345}) ] } response = savory_dispatch_batch(root_resource, full_host='localhost:8081', method='POST', body=json.dumps(request_data)) self.assertEqual(response.status_code, 200) response_json = json.loads(response.content) data = response_json['data'] self.assertEqual(len(data), 1) self.assertEqual(data[0]['status'], 200) self.assertEqual(data[0]['uri'], 'http://localhost:8081/api/v2/child/grandchild') self.assertEqual(data[0]['data'], {u'name': u'value'}) ctx = mock_context() ctx.formatter = JSONFormatter() self.assertEqual(data[0]['etag'], get_sha1(ctx, {u'name': u'value'}))
def test_m2m_through(self): ctx = mock_context() def resolve(*args): prefix = 'http://localhost:8000/api/' self.assertTrue(args[0].startswith(prefix)) arg = args[0][len(prefix):] if arg.startswith('group/'): n = int(arg[6:]) - 1 assert n < len(_groups), n return GroupResource(_groups[n]) elif arg.startswith('person/'): n = int(arg[7:]) - 1 assert n < len(_people), n return PersonResource(_people[n]) else: self.fail(arg) ctx.resolve_resource_uri = resolve source_dict = { 'groups': [{'resourceUri': 'http://localhost:8000/api/group/1', 'name': 'Boy Scouts'}], 'resourceUri': 'http://localhost:8000/api/person/1', 'name': 'Charlie' } resource = PersonResource(_people[0]) resource.put(ctx, source_dict) self.assertEqual('Boy Scouts', _groups[0].name) self.assertEqual(3, len(_memberships)) resource = GroupResource(_groups[0]) self.assertEqual({'resourceUri': 'uri://groups/1', 'name': 'Boy Scouts', '$hash': 'a35a8e769bb1583a840525d1e8fd6b3d02658b04'}, resource.get(ctx, {'resourceUri': 'http://localhost:8000/api/group/1'}))
def test_handle_outgoing_multi_level(self): # TODO: Need to alter savory_pie.fields.IterableField.handle_outgoing to not use manager.all() from savory_pie.tests.django import mock_orm class ORMModelMock(mock_orm.Model): pass class MockResource(ModelResource): model_class = mock_orm.Model fields = [AttributeField(attribute="bar", type=int)] field = IterableField(attribute="foo.fu", resource_class=MockResource) source_object = mock_orm.Model() related_manager = mock_orm.Manager() related_manager.all = Mock(return_value=mock_orm.QuerySet(ORMModelMock(pk=4, bar=14))) class InterimObject(object): pass source_object.foo = InterimObject() source_object.foo.fu = related_manager target_dict = {} field.handle_outgoing(mock_context(), source_object, target_dict) self.assertEqual([{"_id": "4", "bar": 14}], target_dict["foo.fu"])
def test_iterable_factory_outgoing(self): values = [Mock(name="value1", bar=1), Mock(name="value2", bar=2), Mock(name="value3", bar=3)] iterable = MagicMock(name="iterable") iterable.__iter__.return_value = iter(values) class MockResource(ModelResource): model_class = Mock() fields = [AttributeField(attribute="bar", type=int)] iterable_factory = Mock(name="iterable_factory", return_value=iterable) source_object = Mock(name="source_object") target_dict = {} field = IterableField(attribute="foo", resource_class=MockResource, iterable_factory=iterable_factory) field.handle_outgoing(mock_context(), source_object, target_dict) self.assertEqual( target_dict["foo"], [ {"bar": 1, "_id": str(values[0].pk)}, {"bar": 2, "_id": str(values[1].pk)}, {"bar": 3, "_id": str(values[2].pk)}, ], ) iterable_factory.assert_called_with(source_object.foo)
def test_simple_filter(self, haystack_qs_cls): result1 = mock.Mock(name='result1', pk=1) result2 = mock.Mock(name='result2', pk=2) haystack_qs = haystack_qs_cls.return_value haystack_qs.filter.return_value = haystack_qs haystack_qs.models.return_value = haystack_qs haystack_qs.__iter__ = lambda x: iter([result1, result2]) queryset = mock.Mock(name='queryset') queryset.model = TestModel haystack_filter = HaystackFilter() haystack_filter.filter( mock_context(), Params({'q': 'foo'}), queryset, ) queryset.assert_has_calls( [ mock.call.filter(pk__in=[1, 2]), ], any_order=True, ) haystack_qs.assert_has_calls([ mock.call.models(TestModel), mock.call.filter(content=u'foo'), ], any_order=True)
def test_simple_filter(self, haystack_qs_cls): result1 = mock.Mock(name='result1', pk=1) result2 = mock.Mock(name='result2', pk=2) haystack_qs = haystack_qs_cls.return_value haystack_qs.filter.return_value = haystack_qs haystack_qs.models.return_value = haystack_qs haystack_qs.__iter__ = lambda x: iter([result1, result2]) queryset = mock.Mock(name='queryset') queryset.model = TestModel haystack_filter = HaystackFilter() haystack_filter.filter( mock_context(), Params({'q': 'foo'}), queryset, ) queryset.assert_has_calls( [ mock.call.filter(pk__in=[1, 2]), ], any_order=True, ) haystack_qs.assert_has_calls( [ mock.call.models(TestModel), mock.call.filter(content=u'foo'), ], any_order=True )
def test_dirty_save(self): age_field = Mock() age_field.name = 'age' age_field.value_to_string.return_value = 30 name_field = Mock() name_field.name = 'name' name_field.value_to_string.return_value = 'Bob' class DirtyUser(mock_orm.Model): _fields = [age_field, name_field] pk = 3 class DirtyUserResource(resources.ModelResource): parent_resource_path = 'users' model_class = DirtyUser fields = [ fields.AttributeField(attribute='name', type=str), fields.AttributeField(attribute='age', type=int) ] dirty_user = DirtyUser() dirty_user.save = Mock() dirty_user.is_dirty = lambda: True resource = DirtyUserResource(dirty_user) resource.put(mock_context(), { 'name': 'Bob', 'age': 30, 'resourceUri': 'uri://users/1' }) self.assertTrue(dirty_user.save.called)
def test_get_batch(self): root_resource = self.create_root_resource_with_children( r'^api/v2/(?P<base_resource>.*)$', methods=['GET'], result={'name': 'value'} ) request_data = { "data": [ self._generate_batch_partial( 'get', 'http://localhost:8081/api/v2/child/grandchild', {'business_id': 12345} ) ] } response = savory_dispatch_batch( root_resource, full_host='localhost:8081', method='POST', body=json.dumps(request_data) ) self.assertEqual(response.status_code, 200) response_json = json.loads(response.content) data = response_json['data'] self.assertEqual(len(data), 1) self.assertEqual(data[0]['status'], 200) self.assertEqual(data[0]['uri'], 'http://localhost:8081/api/v2/child/grandchild') self.assertEqual(data[0]['data'], {u'name': u'value'}) ctx = mock_context() ctx.formatter = JSONFormatter() self.assertEqual(data[0]['etag'], get_sha1(ctx, {u'name': u'value'}))
def test_handle_outgoing_multi_level(self): # TODO: Need to alter savory_pie.fields.IterableField.handle_outgoing to not use manager.all() from savory_pie.tests.django import mock_orm class ORMModelMock(mock_orm.Model): pass class MockResource(ModelResource): model_class = mock_orm.Model fields = [ AttributeField(attribute='bar', type=int), ] field = IterableField(attribute='foo.fu', resource_class=MockResource) source_object = mock_orm.Model() related_manager = mock_orm.Manager() related_manager.all = Mock(return_value=mock_orm.QuerySet( ORMModelMock(pk=4, bar=14) )) class InterimObject(object): pass source_object.foo = InterimObject() source_object.foo.fu = related_manager target_dict = {} field.handle_outgoing(mock_context(), source_object, target_dict) self.assertEqual([{'_id': '4', 'bar': 14}], target_dict['foo.fu'])
def test_string_field_max_length_validator(self): ctx = mock_context() v = StringFieldMaxLengthValidator(80) field = base_fields.Field() field._attribute = 'bar' field._type = str badness = { 'foo.bar': ['This should not exceed the expected string length.'] } for (value, expected) in ( ('A', {}), (5 * 'A', {}), (10 * 'A', {}), (40 * 'A', {}), (79 * 'A', {}), (80 * 'A', {}), (81 * 'A', badness), (85 * 'A', badness), (100 * 'A', badness), (200 * 'A', badness), (500 * 'A', badness), ): error_dict = {} v.find_errors(error_dict, ctx, 'foo', None, field, value) self.assertEqual(expected, error_dict)
def test_delete(self): user = User() resource = AddressableUserResource(user) resource.delete(mock_context()) self.assertTrue(user.delete.called)
def test_semi_unaddressable_post(self): queryset_resource = SemiUnaddressableUserQuerySetResource() new_resource = queryset_resource.post(mock_context(), { 'name': 'Bob', 'age': 20 }) self.assertEqual(new_resource.resource_path, 'users/' + str(new_resource.model.pk))
def test_mutable_parameters(self): dct = {'a': 'http://one/two/three/four'} ctx = mock_context() ctx.formatter = JSONFormatter() get_sha1(ctx, dct) # Make sure that the dct that we pass in is the same dict that gets returned self.assertEqual(dct, {'a': 'http://one/two/three/four'})
def test_optional_validation(self): """ Resources and Fields should not be required to have validation """ model = User() resource = self.OptionalResource(model) errors = validate(mock_context(), 'user', resource, {}) self.assertEqual({}, errors)
def do_get(self): """ Make GET request, return response """ resource = resources.SchemaResource(DjangoUserResource) ctx = mock_context() ctx.build_resource_uri = lambda resource: 'uri://user/schema/' return resource.get(ctx)
def test_get_child_resource_fail(self): queryset_resource = AddressableUserQuerySetResource(mock_orm.QuerySet( User(pk=1, name='Alice', age=31), User(pk=2, name='Bob', age=20) )) model_resource = queryset_resource.get_child_resource(mock_context(), 999) self.assertIsNone(model_resource)
def test_fully_unaddressable_post(self): queryset_resource = FullyUnaddressableUserQuerySetResource() new_resource = queryset_resource.post(mock_context(), { 'name': 'Bob', 'age': 20 }) self.assertIsNone(new_resource.resource_path)
def test_prepare(self): related = resources.Related() queryset = self.TestResource.prepare(mock_context(), related) self.assertEqual(queryset._select, { 'group', 'domain' })
def test_query_set_get_with_valid_filter_param(self): resource = AddressableUserQuerySetResource(mock_orm.QuerySet( User(pk=1, name='Alice', age=31), User(pk=2, name='Bob', age=20) )) resource.allow_unfiltered_query = False resource.filters = [ParameterizedFilter('name', 'name')] data = resource.get(mock_context(), _ParamsImpl(QueryDict('name=Alice'))) self.assertEqual(data['objects'][0]['name'], 'Alice')
def test_put_with_missing_required_field(self): user = User() request = self.make_request('{"name": "Bob"}') # no age response = views._process_put(mock_context(), AddressableUserResource(user), request) errors = json.loads(response.content) self.assertTrue('validation_errors' in errors) self.assertEqual(errors['validation_errors'], {'missingField': 'age', 'target': 'User'})
def test_empty_queryset(self): resource = AddressableUserQuerySetResource(mock_orm.QuerySet()) data = resource.get(mock_context(), EmptyParams()) self.assertEqual(data['meta'], { 'resourceUri': 'uri://users', 'count': 0 }) self.assertEqual(data['objects'], [])
def test_prepere_after_filter(self): """ Django will reset related selects when a filter is added """ queryset = MagicMock() queryset_resource = ComplexUserResourceQuerySetResource(queryset) queryset_resource.get(mock_context(), EmptyParams()) calls = call.all().distinct().filter().select_related('manager').prefetch_related('reports').call_list() queryset.assert_has_calls(calls)
def test_get_by_source_dict(self): source_dict = { 'name': 'Bob', 'age': 15, } with patch.object(AddressableUserResource.model_class, 'objects') as objects: AddressableUserResource.get_by_source_dict(mock_context(), source_dict) objects.filter.assert_called_with(name='Bob', age=15)
def test_get_by_source_dict_filter_by_item_optional(self): source_dict = { 'name': 'Bob', 'age': 15, } with patch.object(ComplexUserResource.model_class, 'objects') as objects: ComplexUserResource.get_by_source_dict(mock_context(), source_dict) objects.filter.assert_called_with()
def test_query_set_get_disallow_unfiltered_query(self): resource = AddressableUserQuerySetResource(mock_orm.QuerySet( User(pk=1, name='Alice', age=31), User(pk=2, name='Bob', age=20) )) resource.allow_unfiltered_query = False data = None with self.assertRaises(SavoryPieError): data = resource.get(mock_context(), EmptyParams()) self.assertEqual(data, None) # we should not ever have any data as this is not allowed
def test_resource_get_returns_hash(self): user = User(pk=1, name='Bob', age=20) resource = AddressableUserResource(user) dct = resource.get(mock_context(), EmptyParams()) self.assertEqual(dct, { 'name': 'Bob', 'age': 20, 'resourceUri': 'uri://users/1' })
def test_get_by_source_dict_not_found(self): source_dict = { 'name': 'Bob', 'age': 15, } with patch.object(AddressableUserResource.model_class, 'objects') as objects: objects.filter.get.return_value = django.core.exceptions.ObjectDoesNotExist AddressableUserResource.get_by_source_dict(mock_context(), source_dict) objects.filter.assert_called_with(name='Bob', age=15)
def test_save_fields_optional(self): user = Mock(name='user') field = Mock(['handle_incoming']) class Resource(resources.ModelResource): model_class = User fields = [field] resource = Resource(user) # Tests that an attribute error is not raised resource.put(mock_context(), {'foo': 'bar'})
def test_query_set_get_with_invalid_filter_param(self): resource = AddressableUserQuerySetResource(mock_orm.QuerySet( User(pk=1, name='Alice', age=31), User(pk=2, name='Bob', age=20) )) resource.allow_unfiltered_query = False resource.filters = [ParameterizedFilter('name', 'name')] data = None with self.assertRaises(SavoryPieError): data = resource.get(mock_context(), _ParamsImpl(QueryDict('[object Object]=12345'))) self.assertEqual(data, None)
def test_get_child_resource_success(self): alice = User(pk=1, name='Alice', age=31) bob = User(pk=2, name='Bob', age=20) queryset_resource = AddressableUserQuerySetResource(mock_orm.QuerySet( alice, bob )) model_resource = queryset_resource.get_child_resource(mock_context(), 1) self.assertEqual(model_resource.model, alice)
def apply_filters(self, filters): ctx = mock_context() queryset = _users params = Params({ ctx.formatter.convert_to_public_property(name): value for name, value in filters.items() }) for filter in _filters: queryset = filter.filter(ctx, params, queryset) return queryset
def test_save_fields(self): user = Mock(name='user') field = Mock(['handle_incoming', 'save']) class Resource(resources.ModelResource): model_class = User fields = [field] resource = Resource(user) resource.put(mock_context(), {'foo': 'bar'}) self.assertTrue(field.save.called)
def test_required_together_validator(self): resource = RequiredCarTestResource(Car()) good = validate(mock_context(), 'RequiredTogether', resource, {}) self.assertEqual(good, {}) bad = validate(mock_context(), 'RequiredTogether', resource, {'make': 'Tesla'}) self.assertEqual( bad, { 'RequiredTogether': [u'Make and year are required if either is provided.'] }) bad = validate(mock_context(), 'RequiredTogether', resource, {'year': 2012}) self.assertEqual( bad, { 'RequiredTogether': [u'Make and year are required if either is provided.'] })