Merge pull request #475 from EmilStenstrom/standalone-tests

Inline component view tests
This commit is contained in:
Emil Stenström 2024-05-03 10:37:16 +02:00 committed by GitHub
commit d06dab6703
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,9 +1,10 @@
from typing import Any, Dict from typing import Any, Dict
from django.conf import settings
from django.http import HttpResponse from django.http import HttpResponse
from django.template import Context, Template from django.template import Context, Template
from django.test import Client from django.test import Client
from django.urls import include, path from django.urls import path
# isort: off # isort: off
from .django_test_setup import * # noqa from .django_test_setup import * # noqa
@ -13,12 +14,82 @@ from .testutils import BaseTestCase
from django_components import component from django_components import component
#########################
# COMPONENTS class CustomClient(Client):
######################### def __init__(self, urlpatterns=None, *args, **kwargs):
import types
if urlpatterns:
urls_module = types.ModuleType("urls")
urls_module.urlpatterns = urlpatterns # type: ignore
settings.ROOT_URLCONF = urls_module
else:
settings.ROOT_URLCONF = __name__
settings.SECRET_KEY = "secret" # noqa
super().__init__(*args, **kwargs)
class MockComponentRequest(component.Component): class TestComponentAsView(BaseTestCase):
def test_render_component_from_template(self):
@component.register("testcomponent")
class MockComponentRequest(component.Component):
template = """
<form method="post">
{% csrf_token %}
<input type="text" name="variable" value="{{ variable }}">
<input type="submit">
</form>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"variable": "GET"})
def get_context_data(self, variable, *args, **kwargs) -> Dict[str, Any]:
return {"variable": variable}
def render_template_view(request):
template = Template(
"""
{% load component_tags %}
{% component "testcomponent" variable="TEMPLATE" %}{% endcomponent %}
"""
)
return HttpResponse(template.render(Context({})))
client = CustomClient(urlpatterns=[path("test_template/", render_template_view)])
response = client.get("/test_template/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="TEMPLATE">',
response.content,
)
def test_get_request(self):
class MockComponentRequest(component.Component):
template = """
<form method="post">
{% csrf_token %}
<input type="text" name="variable" value="{{ variable }}">
<input type="submit">
</form>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"variable": "GET"})
def get_context_data(self, variable, *args, **kwargs) -> Dict[str, Any]:
return {"variable": variable}
client = CustomClient(urlpatterns=[path("test/", MockComponentRequest.as_view())])
response = client.get("/test/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="GET">',
response.content,
)
def test_post_request(self):
class MockComponentRequest(component.Component):
template = """ template = """
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
@ -31,14 +102,19 @@ class MockComponentRequest(component.Component):
variable = request.POST.get("variable") variable = request.POST.get("variable")
return self.render_to_response({"variable": variable}) return self.render_to_response({"variable": variable})
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"variable": "GET"})
def get_context_data(self, variable, *args, **kwargs) -> Dict[str, Any]: def get_context_data(self, variable, *args, **kwargs) -> Dict[str, Any]:
return {"variable": variable} return {"variable": variable}
client = CustomClient(urlpatterns=[path("test/", MockComponentRequest.as_view())])
response = client.post("/test/", {"variable": "POST"})
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="POST">',
response.content,
)
class MockComponentSlot(component.Component): def test_replace_slot_in_view(self):
class MockComponentSlot(component.Component):
template = """ template = """
{% load component_tags %} {% load component_tags %}
<div> <div>
@ -53,105 +129,8 @@ class MockComponentSlot(component.Component):
def get(self, request, *args, **kwargs) -> HttpResponse: def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"name": "Bob"}, {"second_slot": "Nice to meet you, Bob"}) return self.render_to_response({"name": "Bob"}, {"second_slot": "Nice to meet you, Bob"})
client = CustomClient(urlpatterns=[path("test_slot/", MockComponentSlot.as_view())])
class MockInsecureComponentContext(component.Component): response = client.get("/test_slot/")
template = """
{% load component_tags %}
<div>
{{ variable }}
</div>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"variable": "<script>alert(1);</script>"})
class MockInsecureComponentSlot(component.Component):
template = """
{% load component_tags %}
<div>
{% slot "test_slot" %}
{% endslot %}
</div>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({}, {"test_slot": "<script>alert(1);</script>"})
def render_template_view(request):
template = Template(
"""
{% load component_tags %}
{% component "testcomponent" variable="TEMPLATE" %}{% endcomponent %}
"""
)
return HttpResponse(template.render(Context({})))
components_urlpatterns = [
path("test/", MockComponentRequest.as_view()),
path("test_slot/", MockComponentSlot.as_view()),
path("test_context_insecure/", MockInsecureComponentContext.as_view()),
path("test_slot_insecure/", MockInsecureComponentSlot.as_view()),
path("test_template/", render_template_view),
]
urlpatterns = [
path("", include(components_urlpatterns)),
]
class CustomClient(Client):
def __init__(self, *args, **kwargs):
settings.ROOT_URLCONF = __name__ # noqa
settings.SECRET_KEY = "secret" # noqa
super().__init__(*args, **kwargs)
#########################
# TESTS
#########################
class TestComponentAsView(BaseTestCase):
@classmethod
def setUpClass(self):
component.registry.register("testcomponent", MockComponentRequest)
component.registry.register("testcomponent_slot", MockComponentSlot)
component.registry.register("testcomponent_context_insecure", MockInsecureComponentContext)
component.registry.register("testcomponent_slot_insecure", MockInsecureComponentSlot)
def setUp(self):
self.client = CustomClient()
def test_render_component_from_template(self):
response = self.client.get("/test_template/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="TEMPLATE">',
response.content,
)
def test_get_request(self):
response = self.client.get("/test/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="GET">',
response.content,
)
def test_post_request(self):
response = self.client.post("/test/", {"variable": "POST"})
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="POST">',
response.content,
)
def test_replace_slot_in_view(self):
response = self.client.get("/test_slot/")
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn( self.assertIn(
b"Hey, I'm Bob", b"Hey, I'm Bob",
@ -163,7 +142,20 @@ class TestComponentAsView(BaseTestCase):
) )
def test_replace_slot_in_view_with_insecure_content(self): def test_replace_slot_in_view_with_insecure_content(self):
response = self.client.get("/test_slot_insecure/") class MockInsecureComponentSlot(component.Component):
template = """
{% load component_tags %}
<div>
{% slot "test_slot" %}
{% endslot %}
</div>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({}, {"test_slot": "<script>alert(1);</script>"})
client = CustomClient(urlpatterns=[path("test_slot_insecure/", MockInsecureComponentSlot.as_view())])
response = client.get("/test_slot_insecure/")
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertNotIn( self.assertNotIn(
b"<script>", b"<script>",
@ -171,7 +163,19 @@ class TestComponentAsView(BaseTestCase):
) )
def test_replace_context_in_view_with_insecure_content(self): def test_replace_context_in_view_with_insecure_content(self):
response = self.client.get("/test_context_insecure/") class MockInsecureComponentContext(component.Component):
template = """
{% load component_tags %}
<div>
{{ variable }}
</div>
"""
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"variable": "<script>alert(1);</script>"})
client = CustomClient(urlpatterns=[path("test_context_insecure/", MockInsecureComponentContext.as_view())])
response = client.get("/test_context_insecure/")
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertNotIn( self.assertNotIn(
b"<script>", b"<script>",