mirror of
https://github.com/wrabit/django-cotton.git
synced 2025-08-05 15:48:06 +00:00
132 lines
4.2 KiB
Python
132 lines
4.2 KiB
Python
import os
|
|
import sys
|
|
import shutil
|
|
import tempfile
|
|
|
|
from django.urls import path
|
|
from django.conf import settings
|
|
from django.test import TestCase
|
|
from django.test import override_settings
|
|
from django.template import Context, Template
|
|
from django.views.generic import TemplateView
|
|
from django_cotton.cotton_loader import Loader as CottonLoader
|
|
|
|
|
|
class DynamicURLModule:
|
|
def __init__(self):
|
|
self.urlpatterns = []
|
|
|
|
def __call__(self):
|
|
return self.urlpatterns
|
|
|
|
|
|
class FileAlreadyExistsError(Exception):
|
|
pass
|
|
|
|
|
|
class CottonTestCase(TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
# Set tmp dir and register a url module for our tmp files
|
|
cls.temp_dir = tempfile.mkdtemp()
|
|
cls.url_module = DynamicURLModule()
|
|
cls.url_module_name = f"dynamic_urls_{cls.__name__}"
|
|
sys.modules[cls.url_module_name] = cls.url_module
|
|
|
|
# Register our temp directory as a TEMPLATES path
|
|
cls.new_templates_setting = settings.TEMPLATES.copy()
|
|
cls.new_templates_setting[0]["DIRS"] = [cls.temp_dir] + cls.new_templates_setting[0]["DIRS"]
|
|
|
|
# Apply the setting
|
|
cls.templates_override = override_settings(TEMPLATES=cls.new_templates_setting)
|
|
cls.templates_override.enable()
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
"""Remove temporary directory and clean up modules"""
|
|
cls.templates_override.disable()
|
|
shutil.rmtree(cls.temp_dir, ignore_errors=True)
|
|
del sys.modules[cls.url_module_name]
|
|
super().tearDownClass()
|
|
|
|
def tearDown(self):
|
|
"""Clear state between tests so that we can use the same file names"""
|
|
self.clean_temp_dir()
|
|
super().tearDown()
|
|
|
|
def clean_temp_dir(self):
|
|
"""Remove all files in the temporary directory"""
|
|
for filename in os.listdir(self.temp_dir):
|
|
file_path = os.path.join(self.temp_dir, filename)
|
|
try:
|
|
if os.path.isfile(file_path) or os.path.islink(file_path):
|
|
os.unlink(file_path)
|
|
elif os.path.isdir(file_path):
|
|
shutil.rmtree(file_path)
|
|
except Exception as e:
|
|
print(f"Failed to delete {file_path}. Reason: {e}")
|
|
|
|
def create_template(self, name, content, url=None, context={}):
|
|
"""Create a template file in the temporary directory and return the path"""
|
|
|
|
# To test the non-default of allowing non-snake-cased names
|
|
snake_cased_names = getattr(settings, "COTTON_SNAKE_CASED_NAMES", True)
|
|
if not snake_cased_names:
|
|
name = name.replace("_", "-")
|
|
|
|
path = os.path.join(self.temp_dir, name)
|
|
|
|
if os.path.exists(path):
|
|
raise FileAlreadyExistsError(
|
|
f"A file named '{name}' already exists in the temporary directory."
|
|
)
|
|
|
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
with open(path, "w") as f:
|
|
f.write(content)
|
|
|
|
if url:
|
|
# Create a dynamic class-based view
|
|
class DynamicTemplateView(TemplateView):
|
|
template_name = name
|
|
|
|
def get_context_data(self, **kwargs):
|
|
dynamic_context = super().get_context_data(**kwargs)
|
|
dynamic_context.update(context)
|
|
return dynamic_context
|
|
|
|
self.register_path(url, DynamicTemplateView.as_view(template_name=name))
|
|
|
|
return path
|
|
|
|
def make_view(self, template_name):
|
|
"""Make a view that renders the given template"""
|
|
return TemplateView.as_view(template_name=template_name)
|
|
|
|
def register_path(self, url, view):
|
|
"""Register a URL pattern and returns path"""
|
|
url_pattern = path(url, view)
|
|
self.url_module.urlpatterns.append(url_pattern)
|
|
return url_pattern
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.url_module.urlpatterns = []
|
|
|
|
def url_conf(self):
|
|
return self.url_module_name
|
|
|
|
|
|
def get_compiled(template_string):
|
|
return CottonLoader(engine=None).cotton_compiler.process(template_string)
|
|
|
|
|
|
def get_rendered(template_string, context: dict = None):
|
|
if context is None:
|
|
context = {}
|
|
|
|
compiled_string = get_compiled(template_string)
|
|
|
|
return Template(compiled_string).render(Context(context))
|