class TestDynamicListAndDetailRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_list_and_detail_route_decorators(self): routes = self.router.get_routes(DynamicListAndDetailViewSet) decorator_routes = [r for r in routes if not (r.name.endswith('-list') or r.name.endswith('-detail'))] MethodNamesMap = namedtuple('MethodNamesMap', 'method_name url_path') # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate([MethodNamesMap('list_custom_route_get', 'list_custom-route'), MethodNamesMap('list_route_get', 'list_route_get'), MethodNamesMap('list_route_post', 'list_route_post'), MethodNamesMap('detail_custom_route_get', 'detail_custom-route'), MethodNamesMap('detail_route_get', 'detail_route_get'), MethodNamesMap('detail_route_post', 'detail_route_post') ]): route = decorator_routes[i] # check url listing method_name = endpoint.method_name url_path = endpoint.url_path if method_name.startswith('list_'): self.assertEqual(route.url, '^{{prefix}}/{0}{{trailing_slash}}$'.format(url_path)) else: self.assertEqual(route.url, '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format(url_path)) # check method to function mapping if method_name.endswith('_post'): method_map = 'post' else: method_map = 'get' self.assertEqual(route.mapping[method_map], method_name)
def __new__(cls, name, bases, attrs): new_cls = super().__new__(cls, name, bases, attrs) kanaal = attrs.get("notifications_kanaal") if kanaal is None: return new_cls relevant_bases = [ base for base in bases if issubclass(base, NotificationMixin) ] resource = new_cls.queryset.model._meta.model_name # use the router to figure out which actions are available router = SimpleRouter() for route in router.get_routes(new_cls): for method, action in route.mapping.items(): if method.upper() in SAFE_METHODS: continue # check if the action is actually provided by one of the mixins if not any(hasattr(base, action) for base in relevant_bases): continue kanaal.usage[resource].append(action) return new_cls
class TestSimpleRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_link_and_action_decorator(self): routes = self.router.get_routes(BasicViewSet) decorator_routes = routes[2:] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate( ['action1', 'action2', 'action3', 'link1', 'link2']): route = decorator_routes[i] # check url listing self.assertEqual( route.url, '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format( endpoint)) # check method to function mapping if endpoint == 'action3': methods_map = ['post', 'delete'] elif endpoint.startswith('action'): methods_map = ['post'] else: methods_map = ['get'] for method in methods_map: self.assertEqual(route.mapping[method], endpoint)
class TestDynamicListAndDetailRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_list_and_detail_route_decorators(self): routes = self.router.get_routes(DynamicListAndDetailViewSet) decorator_routes = [ r for r in routes if not (r.name.endswith('-list') or r.name.endswith('-detail')) ] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate([ 'list_route_get', 'list_route_post', 'detail_route_get', 'detail_route_post' ]): route = decorator_routes[i] # check url listing if endpoint.startswith('list_'): self.assertEqual( route.url, '^{{prefix}}/{0}{{trailing_slash}}$'.format(endpoint)) else: self.assertEqual( route.url, '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format( endpoint)) # check method to function mapping if endpoint.endswith('_post'): method_map = 'post' else: method_map = 'get' self.assertEqual(route.mapping[method_map], endpoint)
class HaystackViewSetTestCase(TestCase): fixtures = ["mockperson"] def setUp(self): MockPersonIndex().reindex() self.router = SimpleRouter() class ViewSet(HaystackViewSet): serializer_class = Serializer self.view = ViewSet def tearDown(self): MockPersonIndex().clear() def test_viewset_get_queryset_no_queryset(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_queryset(self): setattr(self.view, "queryset", SearchQuerySet().all()) request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_index_models(self): setattr(self.view, "index_models", [MockPerson]) request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_obj_raise_404(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})(request, pk=100000) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_invalid_lookup_field(self): request = factory.get(path="/", data="", content_type="application/json") self.assertRaises( AttributeError, self.view.as_view(actions={"get": "retrieve"}), request, invalid_lookup=1 ) def test_viewset_get_obj_override_lookup_field(self): setattr(self.view, "lookup_field", "custom_lookup") request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})(request, custom_lookup=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_more_like_this_decorator(self): route = self.router.get_routes(self.view)[2:].pop() self.assertEqual(route.url, "^{prefix}/{lookup}/more-like-this{trailing_slash}$") self.assertEqual(route.mapping, {"get": "more_like_this"})
class TestDynamicListAndDetailRouter(TestCase): def setUp(self): self.router = SimpleRouter() def _test_list_and_detail_route_decorators(self, viewset): routes = self.router.get_routes(viewset) decorator_routes = [ r for r in routes if not (r.name.endswith('-list') or r.name.endswith('-detail')) ] MethodNamesMap = namedtuple('MethodNamesMap', 'method_name url_path') # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate([ MethodNamesMap('list_custom_route_get', 'list_custom-route'), MethodNamesMap('list_route_get', 'list_route_get'), MethodNamesMap('list_route_post', 'list_route_post'), MethodNamesMap('detail_custom_route_get', 'detail_custom-route'), MethodNamesMap('detail_route_get', 'detail_route_get'), MethodNamesMap('detail_route_post', 'detail_route_post') ]): route = decorator_routes[i] # check url listing method_name = endpoint.method_name url_path = endpoint.url_path if method_name.startswith('list_'): self.assertEqual( route.url, '^{{prefix}}/{0}{{trailing_slash}}$'.format(url_path)) else: self.assertEqual( route.url, '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format( url_path)) # check method to function mapping if method_name.endswith('_post'): method_map = 'post' else: method_map = 'get' self.assertEqual(route.mapping[method_map], method_name) def test_list_and_detail_route_decorators(self): self._test_list_and_detail_route_decorators( DynamicListAndDetailViewSet) def test_inherited_list_and_detail_route_decorators(self): self._test_list_and_detail_route_decorators( SubDynamicListAndDetailViewSet)
class TestSimpleRouter(URLPatternsTestCase, TestCase): router = SimpleRouter() router.register('basics', BasicViewSet, base_name='basic') urlpatterns = [ url(r'^api/', include(router.urls)), ] def setUp(self): self.router = SimpleRouter() def test_action_routes(self): # Get action routes (first two are list/detail) routes = self.router.get_routes(BasicViewSet)[2:] assert routes[0].url == '^{prefix}/{lookup}/action1{trailing_slash}$' assert routes[0].mapping == { 'post': 'action1', } assert routes[1].url == '^{prefix}/{lookup}/action2{trailing_slash}$' assert routes[1].mapping == { 'post': 'action2', 'delete': 'action2', } assert routes[2].url == '^{prefix}/{lookup}/action3{trailing_slash}$' assert routes[2].mapping == { 'post': 'action3', 'delete': 'action3_delete', } def test_multiple_action_handlers(self): # Standard action response = self.client.post(reverse('basic-action3', args=[1])) assert response.data == {'post': '1'} # Additional handler registered with MethodMapper response = self.client.delete(reverse('basic-action3', args=[1])) assert response.data == {'delete': '1'} def test_register_after_accessing_urls(self): self.router.register(r'notes', NoteViewSet) assert len(self.router.urls) == 2 # list and detail self.router.register(r'notes_bis', NoteViewSet) assert len(self.router.urls) == 4
class TestSimpleRouter(URLPatternsTestCase, TestCase): router = SimpleRouter() router.register('basics', BasicViewSet, basename='basic') urlpatterns = [ url(r'^api/', include(router.urls)), ] def setUp(self): self.router = SimpleRouter() def test_action_routes(self): # Get action routes (first two are list/detail) routes = self.router.get_routes(BasicViewSet)[2:] assert routes[0].url == '^{prefix}/{lookup}/action1{trailing_slash}$' assert routes[0].mapping == { 'post': 'action1', } assert routes[1].url == '^{prefix}/{lookup}/action2{trailing_slash}$' assert routes[1].mapping == { 'post': 'action2', 'delete': 'action2', } assert routes[2].url == '^{prefix}/{lookup}/action3{trailing_slash}$' assert routes[2].mapping == { 'post': 'action3', 'delete': 'action3_delete', } def test_multiple_action_handlers(self): # Standard action response = self.client.post(reverse('basic-action3', args=[1])) assert response.data == {'post': '1'} # Additional handler registered with MethodMapper response = self.client.delete(reverse('basic-action3', args=[1])) assert response.data == {'delete': '1'} def test_register_after_accessing_urls(self): self.router.register(r'notes', NoteViewSet) assert len(self.router.urls) == 2 # list and detail self.router.register(r'notes_bis', NoteViewSet) assert len(self.router.urls) == 4
class TestSimpleRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_link_and_action_decorator(self): routes = self.router.get_routes(BasicViewSet) decorator_routes = routes[2:] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate(['action1', 'action2', 'link1', 'link2']): route = decorator_routes[i] # check url listing self.assertEqual(route.url, '^{{prefix}}/{{lookup}}/{0}/$'.format(endpoint)) # check method to function mapping if endpoint.startswith('action'): method_map = 'post' else: method_map = 'get' self.assertEqual(route.mapping[method_map], endpoint)
class TestSimpleRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_link_and_action_decorator(self): routes = self.router.get_routes(BasicViewSet) decorator_routes = routes[2:] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate(["action1", "action2", "action3", "link1", "link2"]): route = decorator_routes[i] # check url listing self.assertEqual(route.url, "^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$".format(endpoint)) # check method to function mapping if endpoint == "action3": methods_map = ["post", "delete"] elif endpoint.startswith("action"): methods_map = ["post"] else: methods_map = ["get"] for method in methods_map: self.assertEqual(route.mapping[method], endpoint)
class TestDynamicListAndDetailRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_list_and_detail_route_decorators(self): routes = self.router.get_routes(DynamicListAndDetailViewSet) decorator_routes = [r for r in routes if not (r.name.endswith("-list") or r.name.endswith("-detail"))] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate(["list_route_get", "list_route_post", "detail_route_get", "detail_route_post"]): route = decorator_routes[i] # check url listing if endpoint.startswith("list_"): self.assertEqual(route.url, "^{{prefix}}/{0}{{trailing_slash}}$".format(endpoint)) else: self.assertEqual(route.url, "^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$".format(endpoint)) # check method to function mapping if endpoint.endswith("_post"): method_map = "post" else: method_map = "get" self.assertEqual(route.mapping[method_map], endpoint)
class TestSimpleRouter(TestCase): def setUp(self): self.router = SimpleRouter() def test_link_and_action_decorator(self): routes = self.router.get_routes(BasicViewSet) decorator_routes = routes[2:] # Make sure all these endpoints exist and none have been clobbered for i, endpoint in enumerate(['action1', 'action2', 'action3', 'link1', 'link2']): route = decorator_routes[i] # check url listing assert route.url == '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format(endpoint) # check method to function mapping if endpoint == 'action3': methods_map = ['post', 'delete'] elif endpoint.startswith('action'): methods_map = ['post'] else: methods_map = ['get'] for method in methods_map: assert route.mapping[method] == endpoint
class HaystackViewSetTestCase(TestCase): fixtures = ["mockperson", "mockpet"] def setUp(self): MockPersonIndex().reindex() MockPetIndex().reindex() self.router = SimpleRouter() class FacetSerializer(HaystackFacetSerializer): class Meta: fields = ["firstname", "lastname", "created"] class ViewSet1(FacetMixin, HaystackViewSet): index_models = [MockPerson] serializer_class = Serializer facet_serializer_class = FacetSerializer class ViewSet2(MoreLikeThisMixin, HaystackViewSet): index_models = [MockPerson] serializer_class = Serializer class ViewSet3(HaystackViewSet): index_models = [MockPerson, MockPet] serializer_class = Serializer self.view1 = ViewSet1 self.view2 = ViewSet2 self.view3 = ViewSet3 def tearDown(self): MockPersonIndex().clear() def test_viewset_get_queryset_no_queryset(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_queryset(self): setattr(self.view1, "queryset", SearchQuerySet().all()) request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_single_index(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_multiple_indices(self): request = factory.get(path="/", data={"model": "mockapp.mockperson"}, content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_multiple_indices_no_model_query_param(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_multiple_indices_invalid_modelname(self): request = factory.get(path="/", data={"model": "spam"}, content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_obj_raise_404(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})(request, pk=100000) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_invalid_lookup_field(self): request = factory.get(path="/", data="", content_type="application/json") self.assertRaises( AttributeError, self.view1.as_view(actions={"get": "retrieve"}), request, invalid_lookup=1 ) def test_viewset_get_obj_override_lookup_field(self): setattr(self.view1, "lookup_field", "custom_lookup") request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})(request, custom_lookup=1) setattr(self.view1, "lookup_field", "pk") self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_more_like_this_decorator(self): route = self.router.get_routes(self.view2)[2:].pop() self.assertEqual(route.url, "^{prefix}/{lookup}/more-like-this{trailing_slash}$") self.assertEqual(route.mapping, {"get": "more_like_this"}) def test_viewset_more_like_this_action_route(self): request = factory.get(path="/", data={}, content_type="application/json") response = self.view2.as_view(actions={"get": "more_like_this"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_facets_action_route(self): request = factory.get(path="/", data={}, content_type="application/json") response = self.view1.as_view(actions={"get": "facets"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK)
class HaystackViewSetTestCase(TestCase): fixtures = ["mockperson", "mockpet"] def setUp(self): MockPersonIndex().reindex() MockPetIndex().reindex() self.router = SimpleRouter() class FacetSerializer(HaystackFacetSerializer): class Meta: fields = ["firstname", "lastname", "created"] class ViewSet1(FacetMixin, HaystackViewSet): index_models = [MockPerson] serializer_class = Serializer facet_serializer_class = FacetSerializer class ViewSet2(MoreLikeThisMixin, HaystackViewSet): index_models = [MockPerson] serializer_class = Serializer class ViewSet3(HaystackViewSet): index_models = [MockPerson, MockPet] serializer_class = Serializer self.view1 = ViewSet1 self.view2 = ViewSet2 self.view3 = ViewSet3 def tearDown(self): MockPersonIndex().clear() def test_viewset_get_queryset_no_queryset(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_queryset(self): setattr(self.view1, "queryset", SearchQuerySet().all()) request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_single_index(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_multiple_indices(self): request = factory.get(path="/", data={"model": "mockapp.mockperson"}, content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object_multiple_indices_no_model_query_param(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_multiple_indices_invalid_modelname(self): request = factory.get(path="/", data={"model": "spam"}, content_type="application/json") response = self.view3.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_obj_raise_404(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})(request, pk=100000) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_invalid_lookup_field(self): request = factory.get(path="/", data="", content_type="application/json") self.assertRaises(AttributeError, self.view1.as_view(actions={"get": "retrieve"}), request, invalid_lookup=1) def test_viewset_get_obj_override_lookup_field(self): setattr(self.view1, "lookup_field", "custom_lookup") request = factory.get(path="/", data="", content_type="application/json") response = self.view1.as_view(actions={"get": "retrieve"})( request, custom_lookup=1) setattr(self.view1, "lookup_field", "pk") self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_more_like_this_decorator(self): route = self.router.get_routes(self.view2)[2:].pop() self.assertEqual(route.url, "^{prefix}/{lookup}/more-like-this{trailing_slash}$") self.assertEqual(route.mapping, {"get": "more_like_this"}) def test_viewset_more_like_this_action_route(self): request = factory.get(path="/", data={}, content_type="application/json") response = self.view2.as_view(actions={"get": "more_like_this"})( request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_facets_action_route(self): request = factory.get(path="/", data={}, content_type="application/json") response = self.view1.as_view(actions={"get": "facets"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK)
class HaystackViewSetTestCase(TestCase): fixtures = ["mockperson"] def setUp(self): MockPersonIndex().reindex() self.router = SimpleRouter() class ViewSet(HaystackViewSet): serializer_class = Serializer self.view = ViewSet def tearDown(self): MockPersonIndex().clear() def test_viewset_get_queryset_no_queryset(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_queryset(self): setattr(self.view, "queryset", SearchQuerySet().all()) request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_queryset_with_index_models(self): setattr(self.view, "index_models", [MockPerson]) request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "list"})(request) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_object(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})(request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_get_obj_raise_404(self): request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})(request, pk=100000) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_viewset_get_object_invalid_lookup_field(self): request = factory.get(path="/", data="", content_type="application/json") self.assertRaises(AttributeError, self.view.as_view(actions={"get": "retrieve"}), request, invalid_lookup=1) def test_viewset_get_obj_override_lookup_field(self): setattr(self.view, "lookup_field", "custom_lookup") request = factory.get(path="/", data="", content_type="application/json") response = self.view.as_view(actions={"get": "retrieve"})( request, custom_lookup=1) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_viewset_more_like_this_decorator(self): route = self.router.get_routes(self.view)[2:].pop() self.assertEqual(route.url, "^{prefix}/{lookup}/more-like-this{trailing_slash}$") self.assertEqual(route.mapping, {"get": "more_like_this"})