Skip to content

Commit

Permalink
Merge pull request #475 from EmilStenstrom/standalone-tests
Browse files Browse the repository at this point in the history
Inline component view tests
  • Loading branch information
EmilStenstrom authored May 3, 2024
2 parents e566d8e + 3bef2ca commit d06dab6
Showing 1 changed file with 117 additions and 113 deletions.
230 changes: 117 additions & 113 deletions tests/test_component_as_view.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from typing import Any, Dict

from django.conf import settings
from django.http import HttpResponse
from django.template import Context, Template
from django.test import Client
from django.urls import include, path
from django.urls import path

# isort: off
from .django_test_setup import * # noqa
Expand All @@ -13,145 +14,123 @@

from django_components import component

#########################
# COMPONENTS
#########################


class MockComponentRequest(component.Component):
template = """
<form method="post">
{% csrf_token %}
<input type="text" name="variable" value="{{ variable }}">
<input type="submit">
</form>
"""

def post(self, request, *args, **kwargs) -> HttpResponse:
variable = request.POST.get("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]:
return {"variable": variable}


class MockComponentSlot(component.Component):
template = """
{% load component_tags %}
<div>
{% slot "first_slot" %}
Hey, I'm {{ name }}
{% endslot %}
{% slot "second_slot" %}
{% endslot %}
</div>
"""

def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"name": "Bob"}, {"second_slot": "Nice to meet you, Bob"})


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>"})


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
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)


#########################
# 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/")
@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):
response = self.client.get("/test/")
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):
response = self.client.post("/test/", {"variable": "POST"})
class MockComponentRequest(component.Component):
template = """
<form method="post">
{% csrf_token %}
<input type="text" name="variable" value="{{ variable }}">
<input type="submit">
</form>
"""

def post(self, request, *args, **kwargs) -> HttpResponse:
variable = request.POST.get("variable")
return self.render_to_response({"variable": variable})

def get_context_data(self, variable, *args, **kwargs) -> Dict[str, Any]:
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,
)

def test_replace_slot_in_view(self):
response = self.client.get("/test_slot/")
class MockComponentSlot(component.Component):
template = """
{% load component_tags %}
<div>
{% slot "first_slot" %}
Hey, I'm {{ name }}
{% endslot %}
{% slot "second_slot" %}
{% endslot %}
</div>
"""

def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response({"name": "Bob"}, {"second_slot": "Nice to meet you, Bob"})

client = CustomClient(urlpatterns=[path("test_slot/", MockComponentSlot.as_view())])
response = client.get("/test_slot/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b"Hey, I'm Bob",
Expand All @@ -163,15 +142,40 @@ def test_replace_slot_in_view(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.assertNotIn(
b"<script>",
response.content,
)

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.assertNotIn(
b"<script>",
Expand Down

0 comments on commit d06dab6

Please sign in to comment.