from django.contrib.auth.models import User from django.conf import settings from . import patterns from django.conf.urls import include from django.conf.urls import url from django.test import TestCase from importlib import import_module from rest_framework.routers import DefaultRouter from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet from py2swagger.plugins.drf.urlparser import UrlParser from testapp.serializers import CommentSerializer from testapp.urlparser import MockApiView, NonApiView from testapp.custom_urlconf import urlpatterns as custom_urlpatterns class UrlParserTest(TestCase): def setUp(self): self.url_patterns = patterns( '', url(r'a-view/$', MockApiView.as_view(), name='a test view'), url(r'b-view$', MockApiView.as_view(), name='a test view'), url(r'c-view/$', MockApiView.as_view(), name='a test view'), url(r'a-view/child/?$', MockApiView.as_view()), url(r'a-view/child2/?$', MockApiView.as_view()), url(r'another-view/?$', MockApiView.as_view(), name='another test view'), url(r'view-with-param/(:?<ID>\d+)/?$', MockApiView.as_view(), name='another test view'), url(r'a-view-honky/?$', MockApiView.as_view(), name='a test view'), ) self.urlparser = UrlParser() def test_get_apis(self): urls = import_module(settings.ROOT_URLCONF) # Overwrite settings with test patterns urls.urlpatterns = self.url_patterns apis = self.urlparser.get_apis() self.assertEqual(self.url_patterns[0], apis[0]['pattern']) self.assertEqual('/a-view/', apis[0]['path']) self.assertEqual(self.url_patterns[1], apis[1]['pattern']) self.assertEqual('/b-view', apis[1]['path']) self.assertEqual(self.url_patterns[2], apis[2]['pattern']) self.assertEqual('/c-view/', apis[2]['path']) self.assertEqual(self.url_patterns[3], apis[3]['pattern']) self.assertEqual('/a-view/child/', apis[3]['path']) self.assertEqual(self.url_patterns[4], apis[4]['pattern']) self.assertEqual('/a-view/child2/', apis[4]['path']) self.assertEqual(self.url_patterns[5], apis[5]['pattern']) self.assertEqual('/another-view/', apis[5]['path']) self.assertEqual(self.url_patterns[6], apis[6]['pattern']) self.assertEqual('/view-with-param/{var}/', apis[6]['path']) def test_get_apis_urlconf_path(self): apis = self.urlparser.get_apis(urlconf='testapp.custom_urlconf') self.assertEqual(custom_urlpatterns[0], apis[0]['pattern']) self.assertEqual('/a-view/', apis[0]['path']) self.assertEqual(custom_urlpatterns[1], apis[1]['pattern']) self.assertEqual('/b-view', apis[1]['path']) self.assertEqual(custom_urlpatterns[2], apis[2]['pattern']) self.assertEqual('/c-view/', apis[2]['path']) self.assertEqual(custom_urlpatterns[3], apis[3]['pattern']) self.assertEqual('/a-view/child/', apis[3]['path']) self.assertEqual(custom_urlpatterns[4], apis[4]['pattern']) self.assertEqual('/a-view/child2/', apis[4]['path']) self.assertEqual(custom_urlpatterns[5], apis[5]['pattern']) self.assertEqual('/another-view/', apis[5]['path']) self.assertEqual(custom_urlpatterns[6], apis[6]['pattern']) self.assertEqual('/view-with-param/{var}/', apis[6]['path']) def test_get_apis_urlconf(self): urls = import_module(settings.ROOT_URLCONF) # Overwrite settings with test patterns urls.urlpatterns = self.url_patterns apis = self.urlparser.get_apis(urlconf=urls) self.assertEqual(self.url_patterns[0], apis[0]['pattern']) self.assertEqual('/a-view/', apis[0]['path']) self.assertEqual(self.url_patterns[1], apis[1]['pattern']) self.assertEqual('/b-view', apis[1]['path']) self.assertEqual(self.url_patterns[2], apis[2]['pattern']) self.assertEqual('/c-view/', apis[2]['path']) self.assertEqual(self.url_patterns[3], apis[3]['pattern']) self.assertEqual('/a-view/child/', apis[3]['path']) self.assertEqual(self.url_patterns[4], apis[4]['pattern']) self.assertEqual('/a-view/child2/', apis[4]['path']) self.assertEqual(self.url_patterns[5], apis[5]['pattern']) self.assertEqual('/another-view/', apis[5]['path']) self.assertEqual(self.url_patterns[6], apis[6]['pattern']) self.assertEqual('/view-with-param/{var}/', apis[6]['path']) def test_format_api_patterns(self): apis = self.urlparser.get_apis(self.url_patterns) self.assertEqual(len(self.url_patterns), len(apis)) def test_format_api_patterns_url_import(self): urls = patterns('', url(r'api/base/path/', include(self.url_patterns))) apis = self.urlparser.get_apis(urls) self.assertEqual(len(self.url_patterns), len(apis)) def test_format_api_patterns_with_filter(self): apis = self.urlparser.get_apis(self.url_patterns, filter_path="a-view") paths = [api['path'] for api in apis] self.assertIn("/a-view/", paths) self.assertIn("/a-view/child/", paths) self.assertIn("/a-view/child2/", paths) self.assertIn("/a-view-honky/", paths) self.assertEqual(4, len(apis)) def test_format_api_patterns_excluded_namesapce(self): urls = patterns( '', url(r'api/base/path/', include(self.url_patterns, namespace='exclude')) ) apis = self.urlparser.format_api_patterns( url_patterns=urls, exclude_namespaces='exclude') self.assertEqual([], apis) def test_format_api_patterns_url_import_with_routers(self): class MockApiViewSet(ModelViewSet): serializer_class = CommentSerializer model = User queryset = User.objects.all() class AnotherMockApiViewSet(ModelViewSet): serializer_class = CommentSerializer model = User queryset = User.objects.all() router = DefaultRouter() router.register(r'other_views', MockApiViewSet, base_name='test_base_name') router.register(r'more_views', AnotherMockApiViewSet, base_name='test_base_name') urls_app = patterns('', url(r'^', include(router.urls))) urls = patterns( '', url(r'api/', include(urls_app)), url(r'test/', include(urls_app)) ) apis = self.urlparser.get_apis(urls) self.assertEqual( 4, sum(api['path'].find('api') != -1 for api in apis)) self.assertEqual( 4, sum(api['path'].find('test') != -1 for api in apis)) def test_get_api_callback(self): callback = self.urlparser.filter_api_view_callbacks(self.url_patterns[0]) self.assertTrue(issubclass(callback, MockApiView)) def test_get_api_callback_not_rest_view(self): non_api = patterns( '', url(r'something', NonApiView.as_view()) ) callback = self.urlparser.filter_api_view_callbacks(non_api[0]) self.assertIsNone(callback) def test_assemble_endpoint_data(self): """ Tests that the endpoint data is correctly packaged """ urlparser = UrlParser() pattern = self.url_patterns[0] data = urlparser.gather_endpoint_data(pattern) self.assertEqual(data['path'], '/a-view/') self.assertEqual(data['callback'], MockApiView) self.assertEqual(data['pattern'], pattern) def test_assemble_data_with_non_api_callback(self): bad_pattern = patterns('', url(r'^some_view/', NonApiView.as_view())) data = self.urlparser.gather_endpoint_data(bad_pattern) self.assertIsNone(data) def test_exclude_router_api_root(self): class MyViewSet(ModelViewSet): serializer_class = CommentSerializer queryset = User.objects.all() model = User router = DefaultRouter() router.register('test', MyViewSet, base_name='test_base_name') urls_created = len(router.urls) apis = self.urlparser.get_apis(router.urls) self.assertEqual(4, urls_created - len(apis)) class NestedUrlParserTest(TestCase): def setUp(self): class FuzzyApiView(APIView): def get(self, request): pass class ShinyApiView(APIView): def get(self, request): pass api_fuzzy_url_patterns = patterns( '', url(r'^item/$', FuzzyApiView.as_view(), name='find_me')) api_shiny_url_patterns = patterns( '', url(r'^item/$', ShinyApiView.as_view(), name='hide_me')) fuzzy_app_urls = patterns( '', url(r'^api/', include(api_fuzzy_url_patterns, namespace='api_fuzzy_app'))) shiny_app_urls = patterns( '', url(r'^api/', include(api_shiny_url_patterns, namespace='api_shiny_app'))) self.project_urls = patterns( '', url('my_fuzzy_app/', include(fuzzy_app_urls)), url('my_shiny_app/', include(shiny_app_urls)), ) def test_exclude_nested_urls(self): url_parser = UrlParser() # Overwrite settings with test patterns urlpatterns = self.project_urls apis = url_parser.get_apis(urlpatterns, exclude_namespaces=['api_shiny_app']) self.assertEqual(len(apis), 1) self.assertEqual(apis[0]['pattern'].name, 'find_me')