From 492a92d2b81a7f0d026a3323c0eac61536d712ce Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Wed, 12 Sep 2018 21:37:38 -0700 Subject: [PATCH] Test action decorator name & suffix kwargs --- tests/test_decorators.py | 41 ++++++++++++++++++++++++++++++++++++++++ tests/test_utils.py | 26 +++++++++++++++++++++++++ tests/test_viewsets.py | 32 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 856cd9e19..77c488c34 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -212,6 +212,47 @@ class ActionDecoratorTestCase(TestCase): for name in APIView.http_method_names: assert test_action.mapping[name] == name + def test_view_name_kwargs(self): + """ + 'name' and 'suffix' are mutually exclusive kwargs used for generating + a view's display name. + """ + # by default, generate name from method + @action(detail=True) + def test_action(request): + raise NotImplementedError + + assert test_action.kwargs == { + 'description': None, + 'name': 'Test action', + } + + # name kwarg supersedes name generation + @action(detail=True, name='test name') + def test_action(request): + raise NotImplementedError + + assert test_action.kwargs == { + 'description': None, + 'name': 'test name', + } + + # suffix kwarg supersedes name generation + @action(detail=True, suffix='Suffix') + def test_action(request): + raise NotImplementedError + + assert test_action.kwargs == { + 'description': None, + 'suffix': 'Suffix', + } + + # name + suffix is a conflict. + with pytest.raises(TypeError) as excinfo: + action(detail=True, name='test name', suffix='Suffix') + + assert str(excinfo.value) == "`name` and `suffix` are mutually exclusive arguments." + def test_method_mapping(self): @action(detail=False) def test_action(request): diff --git a/tests/test_utils.py b/tests/test_utils.py index a29ae2fa6..28b06b173 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -52,6 +52,14 @@ class ResourceViewSet(ModelViewSet): def detail_action(self, request, *args, **kwargs): raise NotImplementedError + @action(detail=True, name='Custom Name') + def named_action(self, request, *args, **kwargs): + raise NotImplementedError + + @action(detail=True, suffix='Custom Suffix') + def suffixed_action(self, request, *args, **kwargs): + raise NotImplementedError + router = SimpleRouter() router.register(r'resources', ResourceViewSet) @@ -145,6 +153,24 @@ class BreadcrumbTests(TestCase): ('Detail action', '/resources/1/detail_action/'), ] + def test_modelviewset_action_name_kwarg(self): + url = '/resources/1/named_action/' + assert get_breadcrumbs(url) == [ + ('Root', '/'), + ('Resource List', '/resources/'), + ('Resource Instance', '/resources/1/'), + ('Custom Name', '/resources/1/named_action/'), + ] + + def test_modelviewset_action_suffix_kwarg(self): + url = '/resources/1/suffixed_action/' + assert get_breadcrumbs(url) == [ + ('Root', '/'), + ('Resource List', '/resources/'), + ('Resource Instance', '/resources/1/'), + ('Resource Custom Suffix', '/resources/1/suffixed_action/'), + ] + class JsonFloatTests(TestCase): """ diff --git a/tests/test_viewsets.py b/tests/test_viewsets.py index 54b691e22..eac36f095 100644 --- a/tests/test_viewsets.py +++ b/tests/test_viewsets.py @@ -63,9 +63,28 @@ class ActionViewSet(GenericViewSet): raise NotImplementedError +class ActionNamesViewSet(GenericViewSet): + + def retrieve(self, request, *args, **kwargs): + return Response() + + @action(detail=True) + def unnamed_action(self, request, *args, **kwargs): + raise NotImplementedError + + @action(detail=True, name='Custom Name') + def named_action(self, request, *args, **kwargs): + raise NotImplementedError + + @action(detail=True, suffix='Custom Suffix') + def suffixed_action(self, request, *args, **kwargs): + raise NotImplementedError + + router = SimpleRouter() router.register(r'actions', ActionViewSet) router.register(r'actions-alt', ActionViewSet, basename='actions-alt') +router.register(r'names', ActionNamesViewSet, basename='names') urlpatterns = [ @@ -172,6 +191,19 @@ class GetExtraActionUrlMapTests(TestCase): def test_uninitialized_view(self): self.assertEqual(ActionViewSet().get_extra_action_url_map(), OrderedDict()) + def test_action_names(self): + # Action 'name' and 'suffix' kwargs should be respected + response = self.client.get('/api/names/1/') + view = response.renderer_context['view'] + + expected = OrderedDict([ + ('Custom Name', 'http://testserver/api/names/1/named_action/'), + ('Action Names Custom Suffix', 'http://testserver/api/names/1/suffixed_action/'), + ('Unnamed action', 'http://testserver/api/names/1/unnamed_action/'), + ]) + + self.assertEqual(view.get_extra_action_url_map(), expected) + @override_settings(ROOT_URLCONF='tests.test_viewsets') class ReverseActionTests(TestCase):