mirror of
https://github.com/django-components/django-components.git
synced 2025-09-24 22:52:28 +00:00
tests: add inline syntax highlight, inline template files
This commit is contained in:
parent
e566d8ecbb
commit
8c4a55901c
40 changed files with 1309 additions and 1168 deletions
|
@ -3,18 +3,27 @@ from time import perf_counter
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component, types
|
||||||
from django_components.middleware import CSS_DEPENDENCY_PLACEHOLDER, JS_DEPENDENCY_PLACEHOLDER
|
from django_components.middleware import CSS_DEPENDENCY_PLACEHOLDER, JS_DEPENDENCY_PLACEHOLDER
|
||||||
from tests.django_test_setup import * # NOQA
|
from tests.django_test_setup import * # NOQA
|
||||||
from tests.testutils import BaseTestCase, create_and_process_template_response
|
from tests.testutils import BaseTestCase, create_and_process_template_response
|
||||||
|
|
||||||
|
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "slotted_template.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<custom-template>
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
</custom-template>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, variable, variable2="default"):
|
def get_context_data(self, variable, variable2="default"):
|
||||||
return {
|
return {
|
||||||
|
@ -84,8 +93,7 @@ class RenderBenchmarks(BaseTestCase):
|
||||||
return total_elapsed * 1000 / iterations
|
return total_elapsed * 1000 / iterations
|
||||||
|
|
||||||
def test_render_time_for_small_component(self):
|
def test_render_time_for_small_component(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component 'test_component' %}
|
{% component 'test_component' %}
|
||||||
{% slot "header" %}
|
{% slot "header" %}
|
||||||
|
@ -93,13 +101,12 @@ class RenderBenchmarks(BaseTestCase):
|
||||||
{% endslot %}
|
{% endslot %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
|
|
||||||
print(f"{self.timed_loop(lambda: template.render(Context({})))} ms per iteration")
|
print(f"{self.timed_loop(lambda: template.render(Context({})))} ms per iteration")
|
||||||
|
|
||||||
def test_middleware_time_with_dependency_for_small_page(self):
|
def test_middleware_time_with_dependency_for_small_page(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'test_component' %}
|
{% component 'test_component' %}
|
||||||
{% slot "header" %}
|
{% slot "header" %}
|
||||||
|
@ -107,7 +114,7 @@ class RenderBenchmarks(BaseTestCase):
|
||||||
{% endslot %}
|
{% endslot %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
# Sanity tests
|
# Sanity tests
|
||||||
response_content = create_and_process_template_response(template)
|
response_content = create_and_process_template_response(template)
|
||||||
self.assertNotIn(CSS_DEPENDENCY_PLACEHOLDER, response_content)
|
self.assertNotIn(CSS_DEPENDENCY_PLACEHOLDER, response_content)
|
||||||
|
|
|
@ -19,6 +19,9 @@ except ImportError:
|
||||||
params = (params,)
|
params = (params,)
|
||||||
return Annotated(self.type_, *params, **self.metadata[1]) # type: ignore
|
return Annotated(self.type_, *params, **self.metadata[1]) # type: ignore
|
||||||
|
|
||||||
|
def __class_getitem__(self, *params: Any) -> "Annotated": # type: ignore
|
||||||
|
return Annotated(*params) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
css = Annotated[str, "css"]
|
css = Annotated[str, "css"]
|
||||||
django_html = Annotated[str, "django_html"]
|
django_html = Annotated[str, "django_html"]
|
||||||
|
|
|
@ -2,12 +2,12 @@ from typing import Any, Dict
|
||||||
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component, types
|
||||||
|
|
||||||
|
|
||||||
@component.register("single_file_component")
|
@component.register("single_file_component")
|
||||||
class SingleFileComponent(component.Component):
|
class SingleFileComponent(component.Component):
|
||||||
template = """
|
template: types.django_html = """
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="text" name="variable" value="{{ variable }}">
|
<input type="text" name="variable" value="{{ variable }}">
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
{% if branch == 'a' %}
|
|
||||||
<p id="a">{% slot 'a' %}Default A{% endslot %}</p>
|
|
||||||
{% elif branch == 'b' %}
|
|
||||||
<p id="b">{% slot 'b' %}Default B{% endslot %}</p>
|
|
||||||
{% endif %}
|
|
Before Width: | Height: | Size: 20 B After Width: | Height: | Size: 20 B |
Before Width: | Height: | Size: 20 B After Width: | Height: | Size: 20 B |
|
@ -1,2 +0,0 @@
|
||||||
Var1: <strong>{{ var1 }}</strong>
|
|
||||||
Var2 (uppercased): <strong>{{ var2|upper }}</strong>
|
|
|
@ -1,4 +0,0 @@
|
||||||
Variable: <strong>{{ variable }}</strong>
|
|
||||||
{% if variable2 != "default" %}
|
|
||||||
Variable2: <strong>{{ variable2 }}</strong>
|
|
||||||
{% endif %}
|
|
|
@ -1,3 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<p class="incrementer">value={{ value }};calls={{ calls }}</p>
|
|
||||||
{% slot 'content' %}{% endslot %}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
{% slot 'outer' %}
|
|
||||||
<div id="outer">{% slot 'inner' %}Default{% endslot %}</div>
|
|
||||||
{% endslot %}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h1>Parent content</h1>
|
|
||||||
{% component name="variable_display" shadowing_variable='override' new_variable='unique_val' %}{% endcomponent %}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{% slot 'content' %}
|
|
||||||
<h2>Slot content</h2>
|
|
||||||
{% component name="variable_display" shadowing_variable='slot_default_override' new_variable='slot_default_unique' %}{% endcomponent %}
|
|
||||||
{% endslot %}
|
|
||||||
</div>
|
|
|
@ -1,12 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h1>Parent content</h1>
|
|
||||||
{% component name="variable_display" shadowing_variable=inner_parent_value new_variable='unique_val' %}{% endcomponent %}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{% slot 'content' %}
|
|
||||||
<h2>Slot content</h2>
|
|
||||||
{% component name="variable_display" shadowing_variable='slot_default_override' new_variable=inner_parent_value %}{% endcomponent %}
|
|
||||||
{% endslot %}
|
|
||||||
</div>
|
|
|
@ -1 +0,0 @@
|
||||||
{% extends "block_in_slot_in_component.html" %}
|
|
|
@ -1 +0,0 @@
|
||||||
{% include "block_in_slot_in_component.html" %}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div class="calendar-component">
|
|
||||||
<h1>
|
|
||||||
{% slot "header" %}Today's date is <span>{{ date }}</span>{% endslot %}
|
|
||||||
</h1>
|
|
||||||
<main>
|
|
||||||
{% slot "body" %}
|
|
||||||
You have no events today.
|
|
||||||
{% endslot %}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
|
@ -1,14 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div class="dashboard-component">
|
|
||||||
{% component "calendar" date="2020-06-06" %}
|
|
||||||
{% fill "header" %} {# fills and slots with same name relate to diff. things. #}
|
|
||||||
{% slot "header" %}Welcome to your dashboard!{% endslot %}
|
|
||||||
{% endfill %}
|
|
||||||
{% fill "body" %}Here are your to-do items for today:{% endfill %}
|
|
||||||
{% endcomponent %}
|
|
||||||
<ol>
|
|
||||||
{% for item in items %}
|
|
||||||
<li>{{ item }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
|
@ -1 +0,0 @@
|
||||||
<custom-template></custom-template>
|
|
|
@ -1,7 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<custom-template>
|
|
||||||
{{ missing_context_variable }}
|
|
||||||
<header>{% slot "header" %}Default header{% endslot %}</header>
|
|
||||||
<main>{% slot "main" %}Default main{% endslot %}</main>
|
|
||||||
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
|
||||||
</custom-template>
|
|
|
@ -1,5 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div class="header-box">
|
|
||||||
<h1>{% slot "title" required %}{% endslot %}</h1>
|
|
||||||
<h2>{% slot "subtitle" %}{% endslot %}</h2>
|
|
||||||
</div>
|
|
|
@ -1,10 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div class="frontmatter-component">
|
|
||||||
{% slot "title" %}{% endslot %}
|
|
||||||
{% slot "my_title" %}{% endslot %}
|
|
||||||
{% slot "my title 1" %}{% endslot %}
|
|
||||||
{% slot "my-title-2" %}{% endslot %}
|
|
||||||
{% slot "escape this: #$%^*()" %}{% endslot %}
|
|
||||||
|
|
||||||
{{ component_vars.is_filled }}
|
|
||||||
</div>
|
|
|
@ -1,8 +0,0 @@
|
||||||
{# Example from django-components/issues/98 #}
|
|
||||||
{% load component_tags %}
|
|
||||||
<div class="frontmatter-component">
|
|
||||||
<div class="title">{% slot "title" %}Title{% endslot %}</div>
|
|
||||||
{% if component_vars.is_filled.subtitle %}
|
|
||||||
<div class="subtitle">{% slot "subtitle" %}Optional subtitle{% endslot %}</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div>
|
|
||||||
<header>{% slot "header" %}Your Header Here{% endslot %}</header>
|
|
||||||
<main>{% slot "main" default required %}Easy to override{% endslot %}</main>
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<div>
|
|
||||||
<main>{% slot "main" default %}Easy to override{% endslot %}</main>
|
|
||||||
</div>
|
|
|
@ -1,12 +0,0 @@
|
||||||
{# Example from django-components/issues/98 #}
|
|
||||||
{% load component_tags %}
|
|
||||||
<div class="frontmatter-component">
|
|
||||||
<div class="title">{% slot "title" %}Title{% endslot %}</div>
|
|
||||||
{% if component_vars.is_filled.subtitle %}
|
|
||||||
<div class="subtitle">{% slot "subtitle" %}Optional subtitle{% endslot %}</div>
|
|
||||||
{% elif component_vars.is_filled.alt_subtitle %}
|
|
||||||
<div class="subtitle">{% slot "alt_subtitle" %}Why would you want this?{% endslot %}</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="warning">Nothing filled!</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
|
@ -1,2 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
{% include 'slotted_template.html' with context=None only %}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<header>
|
|
||||||
{% slot "header" %} Default content and {{ header.default }}{% endslot %}
|
|
||||||
</header>
|
|
|
@ -1,10 +0,0 @@
|
||||||
{# Example from django-components/issues/98 #}
|
|
||||||
{% load component_tags %}
|
|
||||||
<div class="frontmatter-component">
|
|
||||||
<div class="title">{% slot "title" %}Title{% endslot %}</div>
|
|
||||||
{% if not component_vars.is_filled.subtitle %}
|
|
||||||
<div class="warning">Subtitle not filled!</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="subtitle">{% slot "alt_subtitle" %}Why would you want this?{% endslot %}</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
<header>{% slot "header" %}Default header{% endslot %}</header>
|
|
||||||
<main>{% slot "header" %}Default main header{% endslot %}</main> {# <- whoops! slot name 'header' used twice. #}
|
|
||||||
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
|
|
@ -1,16 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
{% slot "header" %}START{% endslot %}
|
|
||||||
<div class="dashboard-component">
|
|
||||||
{% component "calendar" date="2020-06-06" %}
|
|
||||||
{% fill "header" %} {# fills and slots with same name relate to diff. things. #}
|
|
||||||
{% slot "header" %}NESTED{% endslot %}
|
|
||||||
{% endfill %}
|
|
||||||
{% fill "body" %}Here are your to-do items for today:{% endfill %}
|
|
||||||
{% endcomponent %}
|
|
||||||
<ol>
|
|
||||||
{% for item in items %}
|
|
||||||
<li>{{ item }}</li>
|
|
||||||
{% slot "header" %}LOOP {{ item }} {% endslot %}
|
|
||||||
{% endfor %}
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
|
@ -1,2 +0,0 @@
|
||||||
Provided variable: <strong>{{ variable }}</strong>
|
|
||||||
Default: <p>{{ default_param }}</p>
|
|
|
@ -1,7 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
|
|
||||||
{% for object in objects %}
|
|
||||||
{% slot 'slot_inner' %}
|
|
||||||
{{ object }} default
|
|
||||||
{% endslot %}
|
|
||||||
{% endfor %}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{% load component_tags %}
|
|
||||||
|
|
||||||
<h1>Shadowing variable = {{ shadowing_variable }}</h1>
|
|
||||||
<h1>Uniquely named variable = {{ unique_variable }}</h1>
|
|
|
@ -9,25 +9,38 @@ from django.test import override_settings
|
||||||
# isort: off
|
# isort: off
|
||||||
from .django_test_setup import * # NOQA
|
from .django_test_setup import * # NOQA
|
||||||
from .testutils import BaseTestCase, autodiscover_with_cleanup
|
from .testutils import BaseTestCase, autodiscover_with_cleanup
|
||||||
|
|
||||||
# isort: on
|
# isort: on
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component, types
|
||||||
|
|
||||||
#########################
|
|
||||||
# COMPONENTS
|
|
||||||
#########################
|
|
||||||
|
|
||||||
|
|
||||||
class ParentComponent(component.Component):
|
class ComponentTest(BaseTestCase):
|
||||||
template_name = "parent_template.html"
|
class ParentComponent(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<div>
|
||||||
|
<h1>Parent content</h1>
|
||||||
|
{% component name="variable_display" shadowing_variable='override' new_variable='unique_val' %}
|
||||||
|
{% endcomponent %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{% slot 'content' %}
|
||||||
|
<h2>Slot content</h2>
|
||||||
|
{% component name="variable_display" shadowing_variable='slot_default_override' new_variable='slot_default_unique' %}
|
||||||
|
{% endcomponent %}
|
||||||
|
{% endslot %}
|
||||||
|
</div>
|
||||||
|
""" # noqa
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
return {"shadowing_variable": "NOT SHADOWED"}
|
return {"shadowing_variable": "NOT SHADOWED"}
|
||||||
|
|
||||||
|
class VariableDisplay(component.Component):
|
||||||
class VariableDisplay(component.Component):
|
template: types.django_html = """
|
||||||
template_name = "variable_display.html"
|
{% load component_tags %}
|
||||||
|
<h1>Shadowing variable = {{ shadowing_variable }}</h1>
|
||||||
|
<h1>Uniquely named variable = {{ unique_variable }}</h1>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, shadowing_variable=None, new_variable=None):
|
def get_context_data(self, shadowing_variable=None, new_variable=None):
|
||||||
context = {}
|
context = {}
|
||||||
|
@ -37,42 +50,11 @@ class VariableDisplay(component.Component):
|
||||||
context["unique_variable"] = new_variable
|
context["unique_variable"] = new_variable
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class DuplicateSlotComponent(component.Component):
|
|
||||||
template_name = "template_with_nonunique_slots.html"
|
|
||||||
|
|
||||||
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
|
||||||
return {
|
|
||||||
"name": name,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DuplicateSlotNestedComponent(component.Component):
|
|
||||||
template_name = "template_with_nonunique_slots_nested.html"
|
|
||||||
|
|
||||||
def get_context_data(self, items: List) -> Dict[str, Any]:
|
|
||||||
return {
|
|
||||||
"items": items,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CalendarComponent(component.Component):
|
|
||||||
"""Nested in ComponentWithNestedComponent"""
|
|
||||||
|
|
||||||
template_name = "slotted_component_nesting_template_pt1_calendar.html"
|
|
||||||
|
|
||||||
|
|
||||||
#########################
|
|
||||||
# TESTS
|
|
||||||
#########################
|
|
||||||
|
|
||||||
|
|
||||||
class ComponentTest(BaseTestCase):
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
component.registry.register(name="parent_component", component=ParentComponent)
|
component.registry.register(name="parent_component", component=cls.ParentComponent)
|
||||||
component.registry.register(name="variable_display", component=VariableDisplay)
|
component.registry.register(name="variable_display", component=cls.VariableDisplay)
|
||||||
|
|
||||||
def test_empty_component(self):
|
def test_empty_component(self):
|
||||||
class EmptyComponent(component.Component):
|
class EmptyComponent(component.Component):
|
||||||
|
@ -83,7 +65,9 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_simple_component(self):
|
def test_simple_component(self):
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, variable=None):
|
def get_context_data(self, variable=None):
|
||||||
return {
|
return {
|
||||||
|
@ -114,7 +98,9 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_css_only_component(self):
|
def test_css_only_component(self):
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
css = "style.css"
|
css = "style.css"
|
||||||
|
@ -130,7 +116,9 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_js_only_component(self):
|
def test_js_only_component(self):
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
js = "script.js"
|
js = "script.js"
|
||||||
|
@ -146,7 +134,9 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_empty_media_component(self):
|
def test_empty_media_component(self):
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
pass
|
pass
|
||||||
|
@ -157,7 +147,9 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_missing_media_component(self):
|
def test_missing_media_component(self):
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
comp = SimpleComponent("simple_component")
|
comp = SimpleComponent("simple_component")
|
||||||
|
|
||||||
|
@ -183,7 +175,10 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_component_with_filtered_template(self):
|
def test_component_with_filtered_template(self):
|
||||||
class FilteredComponent(component.Component):
|
class FilteredComponent(component.Component):
|
||||||
template_name = "filtered_template.html"
|
template: types.django_html = """
|
||||||
|
Var1: <strong>{{ var1 }}</strong>
|
||||||
|
Var2 (uppercased): <strong>{{ var2|upper }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, var1=None, var2=None):
|
def get_context_data(self, var1=None, var2=None):
|
||||||
return {
|
return {
|
||||||
|
@ -213,17 +208,17 @@ class ComponentTest(BaseTestCase):
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_template_name(self, context):
|
def get_template_name(self, context):
|
||||||
return f"svg_{context['name']}.svg"
|
return f"dynamic_{context['name']}.svg"
|
||||||
|
|
||||||
comp = SvgComponent("svg_component")
|
comp = SvgComponent("svg_component")
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
comp.render(Context(comp.get_context_data(name="dynamic1"))),
|
comp.render(Context(comp.get_context_data(name="svg1"))),
|
||||||
"""
|
"""
|
||||||
<svg>Dynamic1</svg>
|
<svg>Dynamic1</svg>
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
comp.render(Context(comp.get_context_data(name="dynamic2"))),
|
comp.render(Context(comp.get_context_data(name="svg2"))),
|
||||||
"""
|
"""
|
||||||
<svg>Dynamic2</svg>
|
<svg>Dynamic2</svg>
|
||||||
""",
|
""",
|
||||||
|
@ -243,8 +238,7 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
# Fix the paths, since the "components" dir is nested
|
# Fix the paths, since the "components" dir is nested
|
||||||
with autodiscover_with_cleanup(map_import_paths=lambda p: f"tests.{p}"):
|
with autodiscover_with_cleanup(map_import_paths=lambda p: f"tests.{p}"):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_component' %}
|
{% component 'parent_component' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
|
@ -252,14 +246,21 @@ class ComponentTest(BaseTestCase):
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # NOQA
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({}))
|
rendered = template.render(Context({}))
|
||||||
self.assertIn('<input type="text" name="variable" value="hello">', rendered, rendered)
|
self.assertIn('<input type="text" name="variable" value="hello">', rendered, rendered)
|
||||||
|
|
||||||
def test_component_inside_slot(self):
|
def test_component_inside_slot(self):
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "slotted_template.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<custom-template>
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
</custom-template>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
@ -268,8 +269,7 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
component.registry.register("test", SlottedComponent)
|
component.registry.register("test", SlottedComponent)
|
||||||
|
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "test" name='Igor' %}
|
{% component "test" name='Igor' %}
|
||||||
{% fill "header" %}
|
{% fill "header" %}
|
||||||
|
@ -290,7 +290,7 @@ class ComponentTest(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
|
|
||||||
# {{ name }} should be "Jannete" everywhere
|
# {{ name }} should be "Jannete" everywhere
|
||||||
rendered = self.template.render(Context({"day": "Monday", "name": "Jannete"}))
|
rendered = self.template.render(Context({"day": "Monday", "name": "Jannete"}))
|
||||||
|
@ -313,7 +313,14 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
def test_fill_inside_fill_with_same_name(self):
|
def test_fill_inside_fill_with_same_name(self):
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "slotted_template.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<custom-template>
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
</custom-template>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
@ -322,8 +329,7 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
component.registry.register("test", SlottedComponent)
|
component.registry.register("test", SlottedComponent)
|
||||||
|
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "test" name='Igor' %}
|
{% component "test" name='Igor' %}
|
||||||
{% fill "header" %}
|
{% fill "header" %}
|
||||||
|
@ -344,7 +350,7 @@ class ComponentTest(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
|
|
||||||
# {{ name }} should be "Jannete" everywhere
|
# {{ name }} should be "Jannete" everywhere
|
||||||
rendered = self.template.render(Context({"day": "Monday", "name": "Jannete"}))
|
rendered = self.template.render(Context({"day": "Monday", "name": "Jannete"}))
|
||||||
|
@ -372,7 +378,12 @@ class ComponentTest(BaseTestCase):
|
||||||
)
|
)
|
||||||
def test_slots_of_top_level_comps_can_access_full_outer_ctx(self):
|
def test_slots_of_top_level_comps_can_access_full_outer_ctx(self):
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "template_with_default_slot.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<div>
|
||||||
|
<main>{% slot "main" default %}Easy to override{% endslot %}</main>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
@ -381,8 +392,7 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
component.registry.register("test", SlottedComponent)
|
component.registry.register("test", SlottedComponent)
|
||||||
|
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
<body>
|
<body>
|
||||||
{% component "test" %}
|
{% component "test" %}
|
||||||
|
@ -390,7 +400,7 @@ class ComponentTest(BaseTestCase):
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
</body>
|
</body>
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
|
|
||||||
nested_ctx = Context()
|
nested_ctx = Context()
|
||||||
# Check that the component can access vars across different context layers
|
# Check that the component can access vars across different context layers
|
||||||
|
@ -411,16 +421,70 @@ class ComponentTest(BaseTestCase):
|
||||||
|
|
||||||
|
|
||||||
class DuplicateSlotTest(BaseTestCase):
|
class DuplicateSlotTest(BaseTestCase):
|
||||||
|
class DuplicateSlotComponent(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
{# Slot name 'header' used twice. #}
|
||||||
|
<main>{% slot "header" %}Default main header{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
|
||||||
|
class DuplicateSlotNestedComponent(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% slot "header" %}START{% endslot %}
|
||||||
|
<div class="dashboard-component">
|
||||||
|
{% component "calendar" date="2020-06-06" %}
|
||||||
|
{% fill "header" %} {# fills and slots with same name relate to diff. things. #}
|
||||||
|
{% slot "header" %}NESTED{% endslot %}
|
||||||
|
{% endfill %}
|
||||||
|
{% fill "body" %}Here are your to-do items for today:{% endfill %}
|
||||||
|
{% endcomponent %}
|
||||||
|
<ol>
|
||||||
|
{% for item in items %}
|
||||||
|
<li>{{ item }}</li>
|
||||||
|
{% slot "header" %}LOOP {{ item }} {% endslot %}
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_context_data(self, items: List) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"items": items,
|
||||||
|
}
|
||||||
|
|
||||||
|
class CalendarComponent(component.Component):
|
||||||
|
"""Nested in ComponentWithNestedComponent"""
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<div class="calendar-component">
|
||||||
|
<h1>
|
||||||
|
{% slot "header" %}Today's date is <span>{{ date }}</span>{% endslot %}
|
||||||
|
</h1>
|
||||||
|
<main>
|
||||||
|
{% slot "body" %}
|
||||||
|
You have no events today.
|
||||||
|
{% endslot %}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
component.registry.register(name="duplicate_slot", component=DuplicateSlotComponent)
|
component.registry.register(name="duplicate_slot", component=cls.DuplicateSlotComponent)
|
||||||
component.registry.register(name="duplicate_slot_nested", component=DuplicateSlotNestedComponent)
|
component.registry.register(name="duplicate_slot_nested", component=cls.DuplicateSlotNestedComponent)
|
||||||
component.registry.register(name="calendar", component=CalendarComponent)
|
component.registry.register(name="calendar", component=cls.CalendarComponent)
|
||||||
|
|
||||||
def test_duplicate_slots(self):
|
def test_duplicate_slots(self):
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "duplicate_slot" %}
|
{% component "duplicate_slot" %}
|
||||||
{% fill "header" %}
|
{% fill "header" %}
|
||||||
|
@ -431,7 +495,7 @@ class DuplicateSlotTest(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
|
|
||||||
rendered = self.template.render(Context({"name": "Jannete"}))
|
rendered = self.template.render(Context({"name": "Jannete"}))
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
|
@ -444,13 +508,12 @@ class DuplicateSlotTest(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_duplicate_slots_fallback(self):
|
def test_duplicate_slots_fallback(self):
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "duplicate_slot" %}
|
{% component "duplicate_slot" %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
rendered = self.template.render(Context({}))
|
rendered = self.template.render(Context({}))
|
||||||
|
|
||||||
# NOTE: Slots should have different fallbacks even though they use the same name
|
# NOTE: Slots should have different fallbacks even though they use the same name
|
||||||
|
@ -464,8 +527,7 @@ class DuplicateSlotTest(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_duplicate_slots_nested(self):
|
def test_duplicate_slots_nested(self):
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "duplicate_slot_nested" items=items %}
|
{% component "duplicate_slot_nested" items=items %}
|
||||||
{% fill "header" %}
|
{% fill "header" %}
|
||||||
|
@ -473,7 +535,7 @@ class DuplicateSlotTest(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
rendered = self.template.render(Context({"items": [1, 2, 3]}))
|
rendered = self.template.render(Context({"items": [1, 2, 3]}))
|
||||||
|
|
||||||
# NOTE: Slots should have different fallbacks even though they use the same name
|
# NOTE: Slots should have different fallbacks even though they use the same name
|
||||||
|
@ -504,13 +566,12 @@ class DuplicateSlotTest(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_duplicate_slots_nested_fallback(self):
|
def test_duplicate_slots_nested_fallback(self):
|
||||||
self.template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "duplicate_slot_nested" items=items %}
|
{% component "duplicate_slot_nested" items=items %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
self.template = Template(template_str)
|
||||||
rendered = self.template.render(Context({"items": [1, 2, 3]}))
|
rendered = self.template.render(Context({"items": [1, 2, 3]}))
|
||||||
|
|
||||||
# NOTE: Slots should have different fallbacks even though they use the same name
|
# NOTE: Slots should have different fallbacks even though they use the same name
|
||||||
|
@ -735,13 +796,12 @@ class ComponentMediaTests(BaseTestCase):
|
||||||
def test_component_media_with_dict_with_relative_paths(self):
|
def test_component_media_with_dict_with_relative_paths(self):
|
||||||
# Fix the paths, since the "components" dir is nested
|
# Fix the paths, since the "components" dir is nested
|
||||||
with autodiscover_with_cleanup(map_import_paths=lambda p: f"tests.{p}"):
|
with autodiscover_with_cleanup(map_import_paths=lambda p: f"tests.{p}"):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component name='relative_file_component' variable=variable %}
|
{% component name='relative_file_component' variable=variable %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # NOQA
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "test"}))
|
rendered = template.render(Context({"variable": "test"}))
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -759,13 +819,19 @@ class ComponentMediaTests(BaseTestCase):
|
||||||
class ComponentIsolationTests(BaseTestCase):
|
class ComponentIsolationTests(BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "slotted_template.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<custom-template>
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
</custom-template>
|
||||||
|
"""
|
||||||
|
|
||||||
component.registry.register("test", SlottedComponent)
|
component.registry.register("test", SlottedComponent)
|
||||||
|
|
||||||
def test_instances_of_component_do_not_share_slots(self):
|
def test_instances_of_component_do_not_share_slots(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "test" %}
|
{% component "test" %}
|
||||||
{% fill "header" %}Override header{% endfill %}
|
{% fill "header" %}Override header{% endfill %}
|
||||||
|
@ -777,7 +843,7 @@ class ComponentIsolationTests(BaseTestCase):
|
||||||
{% fill "footer" %}Override footer{% endfill %}
|
{% fill "footer" %}Override footer{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
|
|
||||||
template.render(Context({}))
|
template.render(Context({}))
|
||||||
rendered = template.render(Context({}))
|
rendered = template.render(Context({}))
|
||||||
|
@ -809,7 +875,14 @@ class SlotBehaviorTests(BaseTestCase):
|
||||||
# Django settings per test with `@override_settings`
|
# Django settings per test with `@override_settings`
|
||||||
def make_template(self) -> Template:
|
def make_template(self) -> Template:
|
||||||
class SlottedComponent(component.Component):
|
class SlottedComponent(component.Component):
|
||||||
template_name = "slotted_template.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<custom-template>
|
||||||
|
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||||
|
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||||
|
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||||
|
</custom-template>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
def get_context_data(self, name: Optional[str] = None) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
@ -818,8 +891,7 @@ class SlotBehaviorTests(BaseTestCase):
|
||||||
|
|
||||||
component.registry.register("test", SlottedComponent)
|
component.registry.register("test", SlottedComponent)
|
||||||
|
|
||||||
return Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "test" name='Igor' %}
|
{% component "test" name='Igor' %}
|
||||||
{% fill "header" %}
|
{% fill "header" %}
|
||||||
|
@ -840,7 +912,7 @@ class SlotBehaviorTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
return Template(template_str)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
COMPONENTS={"context_behavior": "django"},
|
COMPONENTS={"context_behavior": "django"},
|
||||||
|
|
|
@ -11,7 +11,7 @@ from .testutils import BaseTestCase
|
||||||
|
|
||||||
# isort: on
|
# isort: on
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component, types
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# COMPONENTS
|
# COMPONENTS
|
||||||
|
@ -19,7 +19,7 @@ from django_components import component
|
||||||
|
|
||||||
|
|
||||||
class MockComponentRequest(component.Component):
|
class MockComponentRequest(component.Component):
|
||||||
template = """
|
template: types.django_html = """
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="text" name="variable" value="{{ variable }}">
|
<input type="text" name="variable" value="{{ variable }}">
|
||||||
|
@ -39,7 +39,7 @@ class MockComponentRequest(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class MockComponentSlot(component.Component):
|
class MockComponentSlot(component.Component):
|
||||||
template = """
|
template: types.django_html = """
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
<div>
|
<div>
|
||||||
{% slot "first_slot" %}
|
{% slot "first_slot" %}
|
||||||
|
@ -55,7 +55,7 @@ class MockComponentSlot(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class MockInsecureComponentContext(component.Component):
|
class MockInsecureComponentContext(component.Component):
|
||||||
template = """
|
template: types.django_html = """
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
<div>
|
<div>
|
||||||
{{ variable }}
|
{{ variable }}
|
||||||
|
@ -67,7 +67,7 @@ class MockInsecureComponentContext(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class MockInsecureComponentSlot(component.Component):
|
class MockInsecureComponentSlot(component.Component):
|
||||||
template = """
|
template: types.django_html = """
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
<div>
|
<div>
|
||||||
{% slot "test_slot" %}
|
{% slot "test_slot" %}
|
||||||
|
@ -80,12 +80,11 @@ class MockInsecureComponentSlot(component.Component):
|
||||||
|
|
||||||
|
|
||||||
def render_template_view(request):
|
def render_template_view(request):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}
|
{% load component_tags %}
|
||||||
{% component "testcomponent" variable="TEMPLATE" %}{% endcomponent %}
|
{% component "testcomponent" variable="TEMPLATE" %}{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
return HttpResponse(template.render(Context({})))
|
return HttpResponse(template.render(Context({})))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.template import Context, Template
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component
|
||||||
|
from django_components import types
|
||||||
|
|
||||||
from .django_test_setup import * # NOQA
|
from .django_test_setup import * # NOQA
|
||||||
from .testutils import BaseTestCase
|
from .testutils import BaseTestCase
|
||||||
|
@ -14,7 +15,9 @@ from .testutils import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
class SimpleComponent(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, variable=None):
|
def get_context_data(self, variable=None):
|
||||||
return {"variable": variable} if variable is not None else {}
|
return {"variable": variable} if variable is not None else {}
|
||||||
|
@ -24,22 +27,12 @@ class SimpleComponent(component.Component):
|
||||||
return "Variable: < strong > {} < / strong >".format(variable_value)
|
return "Variable: < strong > {} < / strong >".format(variable_value)
|
||||||
|
|
||||||
|
|
||||||
class ParentComponent(component.Component):
|
|
||||||
template_name = "parent_template.html"
|
|
||||||
|
|
||||||
def get_context_data(self):
|
|
||||||
return {"shadowing_variable": "NOT SHADOWED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ParentComponentWithArgs(component.Component):
|
|
||||||
template_name = "parent_with_args_template.html"
|
|
||||||
|
|
||||||
def get_context_data(self, parent_value):
|
|
||||||
return {"inner_parent_value": parent_value}
|
|
||||||
|
|
||||||
|
|
||||||
class VariableDisplay(component.Component):
|
class VariableDisplay(component.Component):
|
||||||
template_name = "variable_display.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<h1>Shadowing variable = {{ shadowing_variable }}</h1>
|
||||||
|
<h1>Uniquely named variable = {{ unique_variable }}</h1>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, shadowing_variable=None, new_variable=None):
|
def get_context_data(self, shadowing_variable=None, new_variable=None):
|
||||||
context = {}
|
context = {}
|
||||||
|
@ -51,7 +44,11 @@ class VariableDisplay(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class IncrementerComponent(component.Component):
|
class IncrementerComponent(component.Component):
|
||||||
template_name = "incrementer.html"
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<p class="incrementer">value={{ value }};calls={{ calls }}</p>
|
||||||
|
{% slot 'content' %}{% endslot %}
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -66,32 +63,46 @@ class IncrementerComponent(component.Component):
|
||||||
return {"value": value + 1, "calls": self.call_count}
|
return {"value": value + 1, "calls": self.call_count}
|
||||||
|
|
||||||
|
|
||||||
class OuterContextComponent(component.Component):
|
|
||||||
template_name = "simple_template.html"
|
|
||||||
|
|
||||||
def get_context_data(self):
|
|
||||||
return self.outer_context.flatten()
|
|
||||||
|
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# TESTS
|
# TESTS
|
||||||
#########################
|
#########################
|
||||||
|
|
||||||
|
|
||||||
class ContextTests(BaseTestCase):
|
class ContextTests(BaseTestCase):
|
||||||
|
class ParentComponent(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<div>
|
||||||
|
<h1>Parent content</h1>
|
||||||
|
{% component name="variable_display" shadowing_variable='override' new_variable='unique_val' %}
|
||||||
|
{% endcomponent %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{% slot 'content' %}
|
||||||
|
<h2>Slot content</h2>
|
||||||
|
{% component name="variable_display" shadowing_variable='slot_default_override' new_variable='slot_default_unique' %}
|
||||||
|
{% endcomponent %}
|
||||||
|
{% endslot %}
|
||||||
|
</div>
|
||||||
|
""" # noqa
|
||||||
|
|
||||||
|
def get_context_data(self):
|
||||||
|
return {"shadowing_variable": "NOT SHADOWED"}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
component.registry.register(name="variable_display", component=VariableDisplay)
|
component.registry.register(name="variable_display", component=VariableDisplay)
|
||||||
component.registry.register(name="parent_component", component=ParentComponent)
|
component.registry.register(name="parent_component", component=cls.ParentComponent)
|
||||||
|
|
||||||
def test_nested_component_context_shadows_parent_with_unfilled_slots_and_component_tag(
|
def test_nested_component_context_shadows_parent_with_unfilled_slots_and_component_tag(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'parent_component' %}{% endcomponent %}"
|
{% component 'parent_component' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
|
|
||||||
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
||||||
|
@ -105,10 +116,12 @@ class ContextTests(BaseTestCase):
|
||||||
def test_nested_component_instances_have_unique_context_with_unfilled_slots_and_component_tag(
|
def test_nested_component_instances_have_unique_context_with_unfilled_slots_and_component_tag(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}
|
||||||
"{% component name='parent_component' %}{% endcomponent %}"
|
{% component_dependencies %}
|
||||||
)
|
{% component name='parent_component' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
|
|
||||||
self.assertIn("<h1>Uniquely named variable = unique_val</h1>", rendered, rendered)
|
self.assertIn("<h1>Uniquely named variable = unique_val</h1>", rendered, rendered)
|
||||||
|
@ -119,8 +132,7 @@ class ContextTests(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_nested_component_context_shadows_parent_with_filled_slots(self):
|
def test_nested_component_context_shadows_parent_with_filled_slots(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_component' %}
|
{% component 'parent_component' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
|
@ -129,7 +141,7 @@ class ContextTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # NOQA
|
""" # NOQA
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
|
|
||||||
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
||||||
|
@ -140,12 +152,10 @@ class ContextTests(BaseTestCase):
|
||||||
)
|
)
|
||||||
self.assertNotIn("<h1>Shadowing variable = NOT SHADOWED</h1>", rendered, rendered)
|
self.assertNotIn("<h1>Shadowing variable = NOT SHADOWED</h1>", rendered, rendered)
|
||||||
|
|
||||||
def test_nested_component_instances_have_unique_context_with_filled_slots(
|
def test_nested_component_instances_have_unique_context_with_filled_slots(self):
|
||||||
self,
|
template_str: types.django_html = """
|
||||||
):
|
{% load component_tags %}
|
||||||
template = Template(
|
{% component_dependencies %}
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
|
||||||
{% component 'parent_component' %}
|
{% component 'parent_component' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
{% component name='variable_display' shadowing_variable='shadow_from_slot' new_variable='unique_from_slot' %}
|
{% component name='variable_display' shadowing_variable='shadow_from_slot' new_variable='unique_from_slot' %}
|
||||||
|
@ -153,7 +163,7 @@ class ContextTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # NOQA
|
""" # NOQA
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
|
|
||||||
self.assertIn("<h1>Uniquely named variable = unique_val</h1>", rendered, rendered)
|
self.assertIn("<h1>Uniquely named variable = unique_val</h1>", rendered, rendered)
|
||||||
|
@ -166,10 +176,12 @@ class ContextTests(BaseTestCase):
|
||||||
def test_nested_component_context_shadows_outer_context_with_unfilled_slots_and_component_tag(
|
def test_nested_component_context_shadows_outer_context_with_unfilled_slots_and_component_tag(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}
|
||||||
"{% component name='parent_component' %}{% endcomponent %}"
|
{% component_dependencies %}
|
||||||
)
|
{% component name='parent_component' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"shadowing_variable": "NOT SHADOWED"}))
|
rendered = template.render(Context({"shadowing_variable": "NOT SHADOWED"}))
|
||||||
|
|
||||||
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
||||||
|
@ -183,8 +195,7 @@ class ContextTests(BaseTestCase):
|
||||||
def test_nested_component_context_shadows_outer_context_with_filled_slots(
|
def test_nested_component_context_shadows_outer_context_with_filled_slots(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_component' %}
|
{% component 'parent_component' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
|
@ -193,7 +204,7 @@ class ContextTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # NOQA
|
""" # NOQA
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"shadowing_variable": "NOT SHADOWED"}))
|
rendered = template.render(Context({"shadowing_variable": "NOT SHADOWED"}))
|
||||||
|
|
||||||
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
self.assertIn("<h1>Shadowing variable = override</h1>", rendered, rendered)
|
||||||
|
@ -206,11 +217,31 @@ class ContextTests(BaseTestCase):
|
||||||
|
|
||||||
|
|
||||||
class ParentArgsTests(BaseTestCase):
|
class ParentArgsTests(BaseTestCase):
|
||||||
|
class ParentComponentWithArgs(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
<div>
|
||||||
|
<h1>Parent content</h1>
|
||||||
|
{% component name="variable_display" shadowing_variable=inner_parent_value new_variable='unique_val' %}
|
||||||
|
{% endcomponent %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{% slot 'content' %}
|
||||||
|
<h2>Slot content</h2>
|
||||||
|
{% component name="variable_display" shadowing_variable='slot_default_override' new_variable=inner_parent_value %}
|
||||||
|
{% endcomponent %}
|
||||||
|
{% endslot %}
|
||||||
|
</div>
|
||||||
|
""" # noqa
|
||||||
|
|
||||||
|
def get_context_data(self, parent_value):
|
||||||
|
return {"inner_parent_value": parent_value}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
component.registry.register(name="incrementer", component=IncrementerComponent)
|
component.registry.register(name="incrementer", component=IncrementerComponent)
|
||||||
component.registry.register(name="parent_with_args", component=ParentComponentWithArgs)
|
component.registry.register(name="parent_with_args", component=cls.ParentComponentWithArgs)
|
||||||
component.registry.register(name="variable_display", component=VariableDisplay)
|
component.registry.register(name="variable_display", component=VariableDisplay)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
|
@ -219,13 +250,12 @@ class ParentArgsTests(BaseTestCase):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def test_parent_args_can_be_drawn_from_context__django(self):
|
def test_parent_args_can_be_drawn_from_context__django(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_with_args' parent_value=parent_value %}
|
{% component 'parent_with_args' parent_value=parent_value %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"parent_value": "passed_in"}))
|
rendered = template.render(Context({"parent_value": "passed_in"}))
|
||||||
|
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
|
@ -250,13 +280,12 @@ class ParentArgsTests(BaseTestCase):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def test_parent_args_can_be_drawn_from_context__isolated(self):
|
def test_parent_args_can_be_drawn_from_context__isolated(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_with_args' parent_value=parent_value %}
|
{% component 'parent_with_args' parent_value=parent_value %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"parent_value": "passed_in"}))
|
rendered = template.render(Context({"parent_value": "passed_in"}))
|
||||||
|
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
|
@ -276,10 +305,11 @@ class ParentArgsTests(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_parent_args_available_outside_slots(self):
|
def test_parent_args_available_outside_slots(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'parent_with_args' parent_value='passed_in' %}{%endcomponent %}"
|
{% component 'parent_with_args' parent_value='passed_in' %}{%endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
|
|
||||||
self.assertIn("<h1>Shadowing variable = passed_in</h1>", rendered, rendered)
|
self.assertIn("<h1>Shadowing variable = passed_in</h1>", rendered, rendered)
|
||||||
|
@ -292,8 +322,7 @@ class ParentArgsTests(BaseTestCase):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def test_parent_args_available_in_slots__django(self):
|
def test_parent_args_available_in_slots__django(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_with_args' parent_value='passed_in' %}
|
{% component 'parent_with_args' parent_value='passed_in' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
|
@ -302,7 +331,7 @@ class ParentArgsTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # noqa: E501
|
""" # noqa: E501
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -325,8 +354,7 @@ class ParentArgsTests(BaseTestCase):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def test_parent_args_not_available_in_slots__isolated(self):
|
def test_parent_args_not_available_in_slots__isolated(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'parent_with_args' parent_value='passed_in' %}
|
{% component 'parent_with_args' parent_value='passed_in' %}
|
||||||
{% fill 'content' %}
|
{% fill 'content' %}
|
||||||
|
@ -335,7 +363,7 @@ class ParentArgsTests(BaseTestCase):
|
||||||
{% endfill %}
|
{% endfill %}
|
||||||
{% endcomponent %}
|
{% endcomponent %}
|
||||||
""" # noqa: E501
|
""" # noqa: E501
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = template.render(Context())
|
rendered = template.render(Context())
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -360,10 +388,11 @@ class ContextCalledOnceTests(BaseTestCase):
|
||||||
component.registry.register(name="incrementer", component=IncrementerComponent)
|
component.registry.register(name="incrementer", component=IncrementerComponent)
|
||||||
|
|
||||||
def test_one_context_call_with_simple_component(self):
|
def test_one_context_call_with_simple_component(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component name='incrementer' %}{% endcomponent %}"
|
{% component name='incrementer' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip().replace("\n", "")
|
rendered = template.render(Context()).strip().replace("\n", "")
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -371,46 +400,66 @@ class ContextCalledOnceTests(BaseTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_one_context_call_with_simple_component_and_arg(self):
|
def test_one_context_call_with_simple_component_and_arg(self):
|
||||||
template = Template("{% load component_tags %}{% component name='incrementer' value='2' %}{% endcomponent %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% component name='incrementer' value='2' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip()
|
rendered = template.render(Context()).strip()
|
||||||
|
|
||||||
self.assertEqual(rendered, '<p class="incrementer">value=3;calls=1</p>', rendered)
|
self.assertHTMLEqual(rendered, '<p class="incrementer">value=3;calls=1</p>', rendered)
|
||||||
|
|
||||||
def test_one_context_call_with_component(self):
|
def test_one_context_call_with_component(self):
|
||||||
template = Template("{% load component_tags %}" "{% component 'incrementer' %}{% endcomponent %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% component 'incrementer' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip()
|
rendered = template.render(Context()).strip()
|
||||||
|
|
||||||
self.assertEqual(rendered, '<p class="incrementer">value=1;calls=1</p>', rendered)
|
self.assertHTMLEqual(rendered, '<p class="incrementer">value=1;calls=1</p>', rendered)
|
||||||
|
|
||||||
def test_one_context_call_with_component_and_arg(self):
|
def test_one_context_call_with_component_and_arg(self):
|
||||||
template = Template("{% load component_tags %}" "{% component 'incrementer' value='3' %}{% endcomponent %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% component 'incrementer' value='3' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip()
|
rendered = template.render(Context()).strip()
|
||||||
|
|
||||||
self.assertEqual(rendered, '<p class="incrementer">value=4;calls=1</p>', rendered)
|
self.assertHTMLEqual(rendered, '<p class="incrementer">value=4;calls=1</p>', rendered)
|
||||||
|
|
||||||
def test_one_context_call_with_slot(self):
|
def test_one_context_call_with_slot(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}"
|
{% load component_tags %}
|
||||||
"{% component 'incrementer' %}{% fill 'content' %}"
|
{% component 'incrementer' %}
|
||||||
"<p>slot</p>{% endfill %}{% endcomponent %}"
|
{% fill 'content' %}
|
||||||
)
|
<p>slot</p>
|
||||||
|
{% endfill %}
|
||||||
|
{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip()
|
rendered = template.render(Context()).strip()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
'<p class="incrementer">value=1;calls=1</p>\n<p>slot</p>',
|
'<p class="incrementer">value=1;calls=1</p>\n<p>slot</p>',
|
||||||
rendered,
|
rendered,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_one_context_call_with_slot_and_arg(self):
|
def test_one_context_call_with_slot_and_arg(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}"
|
{% load component_tags %}
|
||||||
"{% component 'incrementer' value='3' %}{% fill 'content' %}"
|
{% component 'incrementer' value='3' %}
|
||||||
"<p>slot</p>{% endfill %}{% endcomponent %}"
|
{% fill 'content' %}
|
||||||
)
|
<p>slot</p>
|
||||||
|
{% endfill %}
|
||||||
|
{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context()).strip()
|
rendered = template.render(Context()).strip()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
'<p class="incrementer">value=4;calls=1</p>\n<p>slot</p>',
|
'<p class="incrementer">value=4;calls=1</p>\n<p>slot</p>',
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -427,10 +476,11 @@ class ComponentsCanAccessOuterContext(BaseTestCase):
|
||||||
COMPONENTS={"context_behavior": "django"},
|
COMPONENTS={"context_behavior": "django"},
|
||||||
)
|
)
|
||||||
def test_simple_component_can_use_outer_context__django(self):
|
def test_simple_component_can_use_outer_context__django(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' %}{% endcomponent %}"
|
{% component 'simple_component' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -443,10 +493,11 @@ class ComponentsCanAccessOuterContext(BaseTestCase):
|
||||||
COMPONENTS={"context_behavior": "isolated"},
|
COMPONENTS={"context_behavior": "isolated"},
|
||||||
)
|
)
|
||||||
def test_simple_component_cannot_use_outer_context__isolated(self):
|
def test_simple_component_cannot_use_outer_context__isolated(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' %}{% endcomponent %}"
|
{% component 'simple_component' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
@ -463,18 +514,20 @@ class IsolatedContextTests(BaseTestCase):
|
||||||
component.registry.register(name="simple_component", component=SimpleComponent)
|
component.registry.register(name="simple_component", component=SimpleComponent)
|
||||||
|
|
||||||
def test_simple_component_can_pass_outer_context_in_args(self):
|
def test_simple_component_can_pass_outer_context_in_args(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' variable only %}{% endcomponent %}"
|
{% component 'simple_component' variable only %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
||||||
self.assertIn("outer_value", rendered, rendered)
|
self.assertIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
def test_simple_component_cannot_use_outer_context(self):
|
def test_simple_component_cannot_use_outer_context(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' only %}{% endcomponent %}"
|
{% component 'simple_component' only %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
||||||
self.assertNotIn("outer_value", rendered, rendered)
|
self.assertNotIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
|
@ -499,60 +552,73 @@ class IsolatedContextSettingTests(BaseTestCase):
|
||||||
def test_component_tag_includes_variable_with_isolated_context_from_settings(
|
def test_component_tag_includes_variable_with_isolated_context_from_settings(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' variable %}{% endcomponent %}"
|
{% component 'simple_component' variable %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertIn("outer_value", rendered, rendered)
|
self.assertIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
def test_component_tag_excludes_variable_with_isolated_context_from_settings(
|
def test_component_tag_excludes_variable_with_isolated_context_from_settings(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' %}{% endcomponent %}"
|
{% component 'simple_component' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertNotIn("outer_value", rendered, rendered)
|
self.assertNotIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
def test_component_includes_variable_with_isolated_context_from_settings(
|
def test_component_includes_variable_with_isolated_context_from_settings(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' variable %}"
|
{% component 'simple_component' variable %}
|
||||||
"{% endcomponent %}"
|
{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertIn("outer_value", rendered, rendered)
|
self.assertIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
def test_component_excludes_variable_with_isolated_context_from_settings(
|
def test_component_excludes_variable_with_isolated_context_from_settings(
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'simple_component' %}"
|
{% component 'simple_component' %}
|
||||||
"{% endcomponent %}"
|
{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"}))
|
rendered = template.render(Context({"variable": "outer_value"}))
|
||||||
self.assertNotIn("outer_value", rendered, rendered)
|
self.assertNotIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
|
|
||||||
class OuterContextPropertyTests(BaseTestCase):
|
class OuterContextPropertyTests(BaseTestCase):
|
||||||
|
class OuterContextComponent(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_context_data(self):
|
||||||
|
return self.outer_context.flatten()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
component.registry.register(name="outer_context_component", component=OuterContextComponent)
|
component.registry.register(name="outer_context_component", component=cls.OuterContextComponent)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
COMPONENTS={"context_behavior": "django"},
|
COMPONENTS={"context_behavior": "django"},
|
||||||
)
|
)
|
||||||
def test_outer_context_property_with_component__django(self):
|
def test_outer_context_property_with_component__django(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'outer_context_component' only %}{% endcomponent %}"
|
{% component 'outer_context_component' only %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
||||||
self.assertIn("outer_value", rendered, rendered)
|
self.assertIn("outer_value", rendered, rendered)
|
||||||
|
|
||||||
|
@ -560,9 +626,10 @@ class OuterContextPropertyTests(BaseTestCase):
|
||||||
COMPONENTS={"context_behavior": "isolated"},
|
COMPONENTS={"context_behavior": "isolated"},
|
||||||
)
|
)
|
||||||
def test_outer_context_property_with_component__isolated(self):
|
def test_outer_context_property_with_component__isolated(self):
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'outer_context_component' only %}{% endcomponent %}"
|
{% component 'outer_context_component' only %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
rendered = template.render(Context({"variable": "outer_value"})).strip()
|
||||||
self.assertIn("outer_value", rendered, rendered)
|
self.assertIn("outer_value", rendered, rendered)
|
||||||
|
|
|
@ -4,17 +4,32 @@ from django.http import HttpResponseNotModified
|
||||||
from django.template import Template
|
from django.template import Template
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
from django_components import component
|
from django_components import component, types
|
||||||
from django_components.middleware import ComponentDependencyMiddleware
|
from django_components.middleware import ComponentDependencyMiddleware
|
||||||
|
|
||||||
from .django_test_setup import * # NOQA
|
from .django_test_setup import * # NOQA
|
||||||
from .test_templatetags import SimpleComponent
|
|
||||||
from .testutils import BaseTestCase, create_and_process_template_response
|
from .testutils import BaseTestCase, create_and_process_template_response
|
||||||
|
|
||||||
|
|
||||||
class SimpleComponentAlternate(component.Component):
|
class SimpleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template_name = "simple_template.html"
|
||||||
|
|
||||||
|
def get_context_data(self, variable, variable2="default"):
|
||||||
|
return {
|
||||||
|
"variable": variable,
|
||||||
|
"variable2": variable2,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Media:
|
||||||
|
css = "style.css"
|
||||||
|
js = "script.js"
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleComponentAlternate(component.Component):
|
||||||
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, variable):
|
def get_context_data(self, variable):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
@ -24,7 +39,9 @@ class SimpleComponentAlternate(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class SimpleComponentWithSharedDependency(component.Component):
|
class SimpleComponentWithSharedDependency(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
def get_context_data(self, variable, variable2="default"):
|
def get_context_data(self, variable, variable2="default"):
|
||||||
return {}
|
return {}
|
||||||
|
@ -35,7 +52,9 @@ class SimpleComponentWithSharedDependency(component.Component):
|
||||||
|
|
||||||
|
|
||||||
class MultistyleComponent(component.Component):
|
class MultistyleComponent(component.Component):
|
||||||
template_name = "simple_template.html"
|
template: types.django_html = """
|
||||||
|
Variable: <strong>{{ variable }}</strong>
|
||||||
|
"""
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
css = ["style.css", "style2.css"]
|
css = ["style.css", "style2.css"]
|
||||||
|
@ -51,7 +70,10 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_no_dependencies_when_no_components_used(self):
|
def test_no_dependencies_when_no_components_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_dependencies %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_dependencies %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
|
@ -63,14 +85,20 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_no_js_dependencies_when_no_components_used(self):
|
def test_no_js_dependencies_when_no_components_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_js_dependencies %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_js_dependencies %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||||
|
|
||||||
def test_no_css_dependencies_when_no_components_used(self):
|
def test_no_css_dependencies_when_no_components_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_css_dependencies %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_css_dependencies %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -81,7 +109,10 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_preload_dependencies_render_when_no_components_used(self):
|
def test_preload_dependencies_render_when_no_components_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_dependencies preload='test' %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_dependencies preload='test' %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
|
@ -93,7 +124,10 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_preload_css_dependencies_render_when_no_components_used(self):
|
def test_preload_css_dependencies_render_when_no_components_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_css_dependencies preload='test' %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_css_dependencies preload='test' %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -104,10 +138,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_single_component_dependencies_render_when_used(self):
|
def test_single_component_dependencies_render_when_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -119,10 +154,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_single_component_with_dash_or_slash_in_name(self):
|
def test_single_component_with_dash_or_slash_in_name(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -134,10 +170,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_preload_dependencies_render_once_when_used(self):
|
def test_preload_dependencies_render_once_when_used(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies preload='test' %}"
|
{% load component_tags %}{% component_dependencies preload='test' %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -149,27 +186,32 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_placeholder_removed_when_single_component_rendered(self):
|
def test_placeholder_removed_when_single_component_rendered(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertNotIn("_RENDERED", rendered)
|
self.assertNotIn("_RENDERED", rendered)
|
||||||
|
|
||||||
def test_placeholder_removed_when_preload_rendered(self):
|
def test_placeholder_removed_when_preload_rendered(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_dependencies preload='test' %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_dependencies preload='test' %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertNotIn("_RENDERED", rendered)
|
self.assertNotIn("_RENDERED", rendered)
|
||||||
|
|
||||||
def test_single_component_css_dependencies(self):
|
def test_single_component_css_dependencies(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_css_dependencies %}"
|
{% load component_tags %}{% component_css_dependencies %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -180,10 +222,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
def test_single_component_js_dependencies(self):
|
def test_single_component_js_dependencies(self):
|
||||||
component.registry.register(name="test", component=SimpleComponent)
|
component.registry.register(name="test", component=SimpleComponent)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_js_dependencies %}"
|
{% load component_tags %}{% component_js_dependencies %}
|
||||||
"{% component 'test' variable='foo' %}{% endcomponent %}"
|
{% component 'test' variable='foo' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
|
|
||||||
|
@ -191,9 +234,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
component.registry.register(name="test", component=MultistyleComponent)
|
component.registry.register(name="test", component=MultistyleComponent)
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}{% component 'test' %}{% endcomponent %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
)
|
{% component 'test' %}{% endcomponent %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
||||||
|
@ -212,12 +257,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
component.registry.register(name="test", component=MultistyleComponent)
|
component.registry.register(name="test", component=MultistyleComponent)
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_js_dependencies %}
|
{% load component_tags %}{% component_js_dependencies %}
|
||||||
{% component 'test' %}{% endcomponent %}
|
{% component 'test' %}{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
||||||
|
@ -236,12 +280,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
self,
|
self,
|
||||||
):
|
):
|
||||||
component.registry.register(name="test", component=MultistyleComponent)
|
component.registry.register(name="test", component=MultistyleComponent)
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_css_dependencies %}
|
{% load component_tags %}{% component_css_dependencies %}
|
||||||
{% component 'test' %}{% endcomponent %}
|
{% component 'test' %}{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
||||||
|
@ -260,7 +303,10 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test1", component=SimpleComponent)
|
component.registry.register(name="test1", component=SimpleComponent)
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
|
|
||||||
template = Template("{% load component_tags %}{% component_dependencies %}")
|
template_str: types.django_html = """
|
||||||
|
{% load component_tags %}{% component_dependencies %}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
||||||
|
@ -279,10 +325,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test1", component=SimpleComponent)
|
component.registry.register(name="test1", component=SimpleComponent)
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_css_dependencies %}"
|
{% load component_tags %}{% component_css_dependencies %}
|
||||||
"{% component 'test1' 'variable' %}{% endcomponent %}"
|
{% component 'test1' 'variable' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
'<link href="style.css" media="all" rel="stylesheet"/>',
|
'<link href="style.css" media="all" rel="stylesheet"/>',
|
||||||
|
@ -299,10 +346,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test1", component=SimpleComponent)
|
component.registry.register(name="test1", component=SimpleComponent)
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_js_dependencies %}"
|
{% load component_tags %}{% component_js_dependencies %}
|
||||||
"{% component 'test1' 'variable' %}{% endcomponent %}"
|
{% component 'test1' 'variable' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
self.assertInHTML('<script src="script2.js">', rendered, count=0)
|
||||||
|
@ -311,10 +359,11 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test1", component=SimpleComponent)
|
component.registry.register(name="test1", component=SimpleComponent)
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"{% load component_tags %}{% component_dependencies %}"
|
{% load component_tags %}{% component_dependencies %}
|
||||||
"{% component 'test2' variable='variable' %}{% endcomponent %}"
|
{% component 'test2' variable='variable' %}{% endcomponent %}
|
||||||
)
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
||||||
|
@ -334,14 +383,13 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
component.registry.register(name="test3", component=SimpleComponentWithSharedDependency)
|
component.registry.register(name="test3", component=SimpleComponentWithSharedDependency)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'test1' variable='variable' %}{% endcomponent %}
|
{% component 'test1' variable='variable' %}{% endcomponent %}
|
||||||
{% component 'test2' variable='variable' %}{% endcomponent %}
|
{% component 'test2' variable='variable' %}{% endcomponent %}
|
||||||
{% component 'test1' variable='variable' %}{% endcomponent %}
|
{% component 'test1' variable='variable' %}{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||||
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
self.assertInHTML('<script src="script2.js">', rendered, count=1)
|
||||||
|
@ -361,14 +409,13 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
component.registry.register(name="test2", component=SimpleComponentAlternate)
|
||||||
component.registry.register(name="test3", component=SimpleComponentWithSharedDependency)
|
component.registry.register(name="test3", component=SimpleComponentWithSharedDependency)
|
||||||
|
|
||||||
template = Template(
|
template_str: types.django_html = """
|
||||||
"""
|
|
||||||
{% load component_tags %}{% component_dependencies %}
|
{% load component_tags %}{% component_dependencies %}
|
||||||
{% component 'test1' variable='variable' %}{% endcomponent %}
|
{% component 'test1' variable='variable' %}{% endcomponent %}
|
||||||
{% component 'test2' variable='variable' %}{% endcomponent %}
|
{% component 'test2' variable='variable' %}{% endcomponent %}
|
||||||
{% component 'test1' variable='variable' %}{% endcomponent %}
|
{% component 'test1' variable='variable' %}{% endcomponent %}
|
||||||
"""
|
"""
|
||||||
)
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertNotIn("_RENDERED", rendered)
|
self.assertNotIn("_RENDERED", rendered)
|
||||||
|
|
||||||
|
@ -388,12 +435,14 @@ class ComponentMediaRenderingTests(BaseTestCase):
|
||||||
]
|
]
|
||||||
for component_name in component_names:
|
for component_name in component_names:
|
||||||
component.registry.register(name=component_name, component=SimpleComponent)
|
component.registry.register(name=component_name, component=SimpleComponent)
|
||||||
template = Template(
|
template_str: types.django_html = f"""
|
||||||
"{% load component_tags %}"
|
{{% load component_tags %}}
|
||||||
"{% component_js_dependencies %}"
|
{{% component_js_dependencies %}}
|
||||||
"{% component_css_dependencies %}"
|
{{% component_css_dependencies %}}
|
||||||
f"{{% component '{component_name}' variable='value' %}}{{% endcomponent %}}"
|
{{% component '{component_name}' variable='value' %}}
|
||||||
)
|
{{% endcomponent %}}
|
||||||
|
"""
|
||||||
|
template = Template(template_str)
|
||||||
rendered = create_and_process_template_response(template)
|
rendered = create_and_process_template_response(template)
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
rendered,
|
rendered,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue