diff --git a/test/app/.coveragerc b/test/app/.coveragerc deleted file mode 100644 index 39ba226..0000000 --- a/test/app/.coveragerc +++ /dev/null @@ -1,9 +0,0 @@ -[run] -branch = True -source = hybridrouter - -[report] -omit = - */tests/* - */migrations/* - __init__.py \ No newline at end of file diff --git a/test/app/app/__init__.py b/test/app/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/app/app/asgi.py b/test/app/app/asgi.py deleted file mode 100644 index de17191..0000000 --- a/test/app/app/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for app project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') - -application = get_asgi_application() diff --git a/test/app/app/settings.py b/test/app/app/settings.py deleted file mode 100644 index 28b4474..0000000 --- a/test/app/app/settings.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Django settings for app project. - -Generated by 'django-admin startproject' using Django 5.0.4. - -For more information on this file, see -https://docs.djangoproject.com/en/5.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/5.0/ref/settings/ -""" - -from pathlib import Path - -# Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent.parent - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-sad(d)_+30qll2*%&tpx4car$^+!9qiz(5*a9icjezl4z*z^g)' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -SERVER_CONFIG_PATH = '/shared/ServerConfig.toml' - -SERVER_MODS_PATH = '/shared/Resources/' - -ALLOWED_HOSTS = ['*'] - - -# Application definition - -INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'rest_framework', - 'drf_spectacular', - 'hybridroutertest' -] - -REST_FRAMEWORK = { - 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', -} - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -] - -ROOT_URLCONF = 'app.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, -] - -WSGI_APPLICATION = 'app.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/5.0/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', - } -} - - -# Password validation -# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - - -# Internationalization -# https://docs.djangoproject.com/en/5.0/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_TZ = True - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/5.0/howto/static-files/ - -STATIC_URL = 'static/' - -# Default primary key field type -# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/test/app/app/urls.py b/test/app/app/urls.py deleted file mode 100644 index 95923bf..0000000 --- a/test/app/app/urls.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -URL configuration for app project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" -from django.urls import path, include -from django.urls import path -from hybridrouter import HybridRouter -from drf_spectacular.views import SpectacularSwaggerView, SpectacularAPIView -from rest_framework.routers import DefaultRouter -from hybridroutertest.views import ServerConfigView, ClientModsView, ServerModsView, ServerConfigViewSet - -router = HybridRouter(enable_intermediate_apiviews=True) -router.register_view(r'^server-config', ServerConfigView, name='server-config') -router.register_view(r'^mods/client', ClientModsView, name='mods-client') -router.register_view(r'^mods/server', ServerModsView, name='mods-server') -router.register_view(r'^coucou/client', ClientModsView, name='coucou-client') -router.register_view(r'^coucou/server', ServerModsView, name='coucou-server') -router.register_viewset(r'coucou', ServerConfigViewSet, basename='coucou') - - -urlpatterns = [ - path('', include(router.urls)), - path('api/schema/', SpectacularAPIView.as_view(), name='schema'), - path('docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), -] diff --git a/test/app/app/wsgi.py b/test/app/app/wsgi.py deleted file mode 100644 index eb514ab..0000000 --- a/test/app/app/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for app project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') - -application = get_wsgi_application() diff --git a/test/app/hybridroutertest/__init__.py b/test/app/hybridroutertest/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/app/hybridroutertest/apps.py b/test/app/hybridroutertest/apps.py deleted file mode 100644 index 775f067..0000000 --- a/test/app/hybridroutertest/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class HybridroutertestConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'hybridroutertest' diff --git a/test/app/hybridroutertest/migrations/__init__.py b/test/app/hybridroutertest/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/app/hybridroutertest/tests.py b/test/app/hybridroutertest/tests.py deleted file mode 100644 index d11c1f8..0000000 --- a/test/app/hybridroutertest/tests.py +++ /dev/null @@ -1,222 +0,0 @@ -import unittest -import sys -import importlib -import os - -from django import setup -from django.conf import settings - -if settings.configured is False: - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') - setup() - -from unittest.mock import patch -from hybridrouter import HybridRouter -from django.test import TestCase, override_settings -from rest_framework.test import APIClient -from hybridroutertest.views import ServerConfigView, ClientModsView, ServerModsView, ServerConfigViewSet -from django.urls import path, include, reverse, NoReverseMatch - -urlpatterns = [] - -class HybridRouterTests(TestCase): - - def setUp(self): - self.router.register_view(r'^server-config', ServerConfigView, name='server-config') - self.router.register_view(r'^mods/client', ClientModsView, name='mods-client') - self.router.register_view(r'^mods/server', ServerModsView, name='mods-server') - self.router.register_view(r'^coucou/client', ClientModsView, name='coucou-client') - self.router.register_view(r'^coucou/server', ServerModsView, name='coucou-server') - self.router.register_viewset(r'coucou', ServerConfigViewSet, basename='coucou') - - self.router.register_view('prefix1', ServerConfigView, 'basename1') - self.router.register_viewset('prefix2', ServerConfigViewSet, 'basename2') - self.router.register('prefix3', ServerConfigViewSet, 'basename3') - self.router.register('prefix4', ServerConfigView, 'basename4') - - - self.client = APIClient() - -class CommonHybridRouterTests: - def test_server_config_view(self): - url = reverse('server-config') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'config': 'server'}) - - def test_client_mods_view(self): - url = reverse('mods-client') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'mods': 'client'}) - - def test_server_mods_view(self): - url = reverse('mods-server') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'mods': 'server'}) - - def test_coucou_client_view(self): - url = reverse('coucou-client') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'mods': 'client'}) - - def test_coucou_server_view(self): - url = reverse('coucou-server') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'mods': 'server'}) - - def test_coucou_viewset_list(self): - url = reverse('coucou-list') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, {'a': 'b'}) - - def test_router_regsiter_view(self): - url = reverse('basename1') - repsonse = self.client.get(url) - self.assertEqual(repsonse.status_code, 200) - self.assertEqual(repsonse.data, {'config': 'server'}) - - def test_router_regsiter_viewset(self): - url = reverse('basename2-list') - repsonse = self.client.get(url) - self.assertEqual(repsonse.status_code, 200) - self.assertEqual(repsonse.data, {'a': 'b'}) - - def test_router_regsiter_a_viewset(self): - url = reverse('basename3-list') - repsonse = self.client.get(url) - self.assertEqual(repsonse.status_code, 200) - self.assertEqual(repsonse.data, {'a': 'b'}) - - - def test_router_resgister_an_api_view(self): - url = reverse('basename4') - repsonse = self.client.get(url) - self.assertEqual(repsonse.status_code, 200) - self.assertEqual(repsonse.data, {'config': 'server'}) - - def test_router_resgister_not_api_view_not_viewset(self): - class TestNotApiViewNotViewSet() : - pass - with self.assertRaises(ValueError): - self.router.register('prefix', TestNotApiViewNotViewSet, 'basename') - -@override_settings(ROOT_URLCONF='hybridroutertest.tests') -class HybridRouterTestCaseWithIntermediaryViews(CommonHybridRouterTests, HybridRouterTests): - - def setUp(self, router=None): - if not router : - self.router = HybridRouter(enable_intermediate_apiviews=True) - else : - self.router = router - - super().setUp() - - global urlpatterns - urlpatterns =[ - path('', include(self.router.urls)), - ] - - def test_view_not_overridden_by_intermediary_view(self): - url = reverse('coucou') - response = self.client.get(url) - attended_data = {'a': 'b'} - self.assertEqual(response.data, attended_data) - - def test_intermediary_view_present(self): - url = reverse('mods') - response = self.client.get(url) - attended_data = { - 'mods-client': response.wsgi_request.build_absolute_uri(reverse('mods-client')), - 'mods-server': response.wsgi_request.build_absolute_uri(reverse('mods-server')) - } - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, attended_data) - - def test_api_root_view(self): - url = reverse('api-root') - response = self.client.get(url) - attended_data = { - 'basename1': response.wsgi_request.build_absolute_uri(reverse('basename1')), - 'basename4': response.wsgi_request.build_absolute_uri(reverse('basename4')), - 'server-config': response.wsgi_request.build_absolute_uri(reverse('server-config')), - 'mods': response.wsgi_request.build_absolute_uri(reverse('mods')), - 'coucou': response.wsgi_request.build_absolute_uri(reverse('coucou')), - 'coucou-client': response.wsgi_request.build_absolute_uri(reverse('coucou-client')), - 'coucou-server': response.wsgi_request.build_absolute_uri(reverse('coucou-server')), - - 'prefix2': response.wsgi_request.build_absolute_uri(reverse('basename2-list')), - 'prefix3': response.wsgi_request.build_absolute_uri(reverse('basename3-list')), - } - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, attended_data) - -@override_settings(ROOT_URLCONF='hybridroutertest.tests') -class HybridRouterTestCaseWithoutIntermediaryViews(CommonHybridRouterTests, HybridRouterTests): - - def setUp(self, router=None): - if not router : - self.router = HybridRouter(enable_intermediate_apiviews=False) - else : - self.router = router - - super().setUp() - - global urlpatterns - urlpatterns =[ - path('', include(self.router.urls)), - ] - - def test_intermediary_view_not_present(self): - with self.assertRaises(NoReverseMatch): - reverse('mods') - - def test_api_root_view(self): - url = reverse('api-root') - response = self.client.get(url) - attended_data = { - 'basename1': response.wsgi_request.build_absolute_uri(reverse('basename1')), - 'basename4': response.wsgi_request.build_absolute_uri(reverse('basename4')), - 'mods-client': response.wsgi_request.build_absolute_uri(reverse('mods-client')), - 'mods-server': response.wsgi_request.build_absolute_uri(reverse('mods-server')), - - 'server-config': response.wsgi_request.build_absolute_uri(reverse('server-config')), - 'coucou': response.wsgi_request.build_absolute_uri(reverse('coucou-list')), - 'coucou-client': response.wsgi_request.build_absolute_uri(reverse('coucou-client')), - 'coucou-server': response.wsgi_request.build_absolute_uri(reverse('coucou-server')), - 'prefix2': response.wsgi_request.build_absolute_uri(reverse('basename2-list')), - 'prefix3': response.wsgi_request.build_absolute_uri(reverse('basename3-list')), - } - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data, attended_data) - -class TestHybridRouterWithoutSpectacular(unittest.TestCase): - - def setUp(self): - super().setUp() - modules_to_remove = [ - 'hybridrouter', 'hybridrouter.hybridrouter', 'drf_spectacular', 'drf_spectacular.utils' - ] - for module in modules_to_remove: - if module in sys.modules: - del sys.modules[module] - - @patch.dict('sys.modules', {'drf_spectacular': None}) - def test_import_error(self): - from hybridrouter import hybridrouter - importlib.reload(hybridrouter) - self.assertTrue(hasattr(hybridrouter, 'DRF_SPECTACULAR')) - self.assertFalse(getattr(hybridrouter, 'DRF_SPECTACULAR')) - -class HybridRouterTestCaseWithIntermediaryViewsWithoutSpectacular(TestHybridRouterWithoutSpectacular, HybridRouterTestCaseWithIntermediaryViews): - def setUp(cls): - super().setUp() - -class HybridRouterTestCaseWithoutIntermediaryViewsWithoutSpectacular(TestHybridRouterWithoutSpectacular, HybridRouterTestCaseWithoutIntermediaryViews): - def setUp(cls): - super().setUp() - \ No newline at end of file diff --git a/test/app/hybridroutertest/views.py b/test/app/hybridroutertest/views.py deleted file mode 100644 index d8e2f7b..0000000 --- a/test/app/hybridroutertest/views.py +++ /dev/null @@ -1,20 +0,0 @@ -from rest_framework.viewsets import ViewSet -from rest_framework.response import Response -from rest_framework.views import APIView -from rest_framework.viewsets import ViewSet - -class ServerConfigViewSet(ViewSet): - def list(self, request): - return Response({'a': 'b'}) - -class ServerConfigView(APIView): - def get(self, request): - return Response({'config': 'server'}) - -class ClientModsView(APIView): - def get(self, request): - return Response({'mods': 'client'}) - -class ServerModsView(APIView): - def get(self, request): - return Response({'mods': 'server'}) diff --git a/test/app/manage.py b/test/app/manage.py deleted file mode 100755 index 4931389..0000000 --- a/test/app/manage.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -"""Django's command-line utility for administrative tasks.""" -import os -import sys - - -def main(): - """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') - try: - from django.core.management import execute_from_command_line - except ImportError as exc: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) from exc - execute_from_command_line(sys.argv) - - -if __name__ == '__main__': - main() diff --git a/test/app/requirements.txt b/test/app/requirements.txt deleted file mode 100644 index b9756ee..0000000 --- a/test/app/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -Django==5.0.8 -djangorestframework==3.15.2 -djangorestframework-hybridrouter -drf-spectacular==0.27.2 \ No newline at end of file