from textwrap import dedent
from django.core.exceptions import ImproperlyConfigured
from django.template import Context, Template
# isort: off
from .django_test_setup import * # NOQA
from .testutils import Django30CompatibleSimpleTestCase as SimpleTestCase
# isort: on
from django_components import component
class ComponentTest(SimpleTestCase):
def test_empty_component(self):
class EmptyComponent(component.Component):
pass
with self.assertRaises(ImproperlyConfigured):
EmptyComponent("empty_component").get_template(Context({}))
def test_simple_component(self):
class SimpleComponent(component.Component):
template_name = "simple_template.html"
def get_context_data(self, variable=None):
return {
"variable": variable,
}
class Media:
css = "style.css"
js = "script.js"
comp = SimpleComponent("simple_component")
context = Context(comp.get_context_data(variable="test"))
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""
"""
).strip(),
)
self.assertHTMLEqual(
comp.render(context),
dedent(
"""
Variable: test
"""
).lstrip(),
)
def test_css_only_component(self):
class SimpleComponent(component.Component):
template_name = "simple_template.html"
class Media:
css = "style.css"
comp = SimpleComponent("simple_component")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""
"""
).strip(),
)
def test_js_only_component(self):
class SimpleComponent(component.Component):
template_name = "simple_template.html"
class Media:
js = "script.js"
comp = SimpleComponent("simple_component")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""
"""
).strip(),
)
def test_empty_media_component(self):
class SimpleComponent(component.Component):
template_name = "simple_template.html"
class Media:
pass
comp = SimpleComponent("simple_component")
self.assertHTMLEqual(comp.render_dependencies(), "")
def test_missing_media_component(self):
class SimpleComponent(component.Component):
template_name = "simple_template.html"
comp = SimpleComponent("simple_component")
self.assertHTMLEqual(comp.render_dependencies(), "")
def test_component_with_list_of_styles(self):
class MultistyleComponent(component.Component):
class Media:
css = ["style.css", "style2.css"]
js = ["script.js", "script2.js"]
comp = MultistyleComponent("multistyle_component")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""
"""
).strip(),
)
def test_component_with_filtered_template(self):
class FilteredComponent(component.Component):
template_name = "filtered_template.html"
def get_context_data(self, var1=None, var2=None):
return {
"var1": var1,
"var2": var2,
}
comp = FilteredComponent("filtered_component")
context = Context(comp.get_context_data(var1="test1", var2="test2"))
self.assertHTMLEqual(
comp.render(context),
dedent(
"""
Var1: test1
Var2 (uppercased): TEST2
"""
).lstrip(),
)
def test_component_with_dynamic_template(self):
class SvgComponent(component.Component):
def get_context_data(self, name, css_class="", title="", **attrs):
return {
"name": name,
"css_class": css_class,
"title": title,
**attrs,
}
def get_template_name(self, context):
return f"svg_{context['name']}.svg"
comp = SvgComponent("svg_component")
self.assertHTMLEqual(
comp.render(Context(comp.get_context_data(name="dynamic1"))),
dedent(
"""\
"""
),
)
self.assertHTMLEqual(
comp.render(Context(comp.get_context_data(name="dynamic2"))),
dedent(
"""\
"""
),
)
class InlineComponentTest(SimpleTestCase):
def test_inline_html_component(self):
class InlineHTMLComponent(component.Component):
template = "
Hello Inline
"
comp = InlineHTMLComponent("inline_html_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Hello Inline
",
)
def test_html_and_css_only(self):
class HTMLCSSComponent(component.Component):
template = "Content
"
css = ".html-css-only { color: blue; }"
comp = HTMLCSSComponent("html_css_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Content
",
)
self.assertHTMLEqual(
comp.render_css_dependencies(),
"",
)
def test_html_and_js_only(self):
class HTMLJSComponent(component.Component):
template = "Content
"
js = "console.log('HTML and JS only');"
comp = HTMLJSComponent("html_js_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Content
",
)
self.assertHTMLEqual(
comp.render_js_dependencies(),
"",
)
def test_html_string_with_css_js_files(self):
class HTMLStringFileCSSJSComponent(component.Component):
template = "Content
"
class Media:
css = "path/to/style.css"
js = "path/to/script.js"
comp = HTMLStringFileCSSJSComponent("html_string_file_css_js_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Content
",
)
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_html_js_string_with_css_file(self):
class HTMLStringFileCSSJSComponent(component.Component):
template = "Content
"
js = "console.log('HTML and JS only');"
class Media:
css = "path/to/style.css"
comp = HTMLStringFileCSSJSComponent("html_string_file_css_js_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Content
",
)
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_html_css_string_with_js_file(self):
class HTMLStringFileCSSJSComponent(component.Component):
template = "Content
"
css = ".html-string-file { color: blue; }"
class Media:
js = "path/to/script.js"
comp = HTMLStringFileCSSJSComponent("html_string_file_css_js_component")
self.assertHTMLEqual(
comp.render(Context({})),
"Content
",
)
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_component_with_variable_in_html(self):
class VariableHTMLComponent(component.Component):
def get_template(self, context):
return Template("{{ variable }}
")
comp = VariableHTMLComponent("variable_html_component")
context = Context({"variable": "Dynamic Content"})
self.assertHTMLEqual(
comp.render(context),
"Dynamic Content
",
)
class ComponentMediaTests(SimpleTestCase):
def test_component_media_with_strings(self):
class SimpleComponent(component.Component):
class Media:
css = "path/to/style.css"
js = "path/to/script.js"
comp = SimpleComponent("")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_component_media_with_lists(self):
class SimpleComponent(component.Component):
class Media:
css = ["path/to/style.css", "path/to/style2.css"]
js = ["path/to/script.js"]
comp = SimpleComponent("")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_component_media_with_dict_and_list(self):
class SimpleComponent(component.Component):
class Media:
css = {
"all": "path/to/style.css",
"print": ["path/to/style2.css"],
"screen": "path/to/style3.css",
}
js = ["path/to/script.js"]
comp = SimpleComponent("")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
def test_component_media_with_dict_with_list_and_list(self):
class SimpleComponent(component.Component):
class Media:
css = {"all": ["path/to/style.css"]}
js = ["path/to/script.js"]
comp = SimpleComponent("")
self.assertHTMLEqual(
comp.render_dependencies(),
dedent(
"""\
"""
),
)
class ComponentIsolationTests(SimpleTestCase):
def setUp(self):
class SlottedComponent(component.Component):
template_name = "slotted_template.html"
component.registry.register("test", SlottedComponent)
def test_instances_of_component_do_not_share_slots(self):
template = Template(
"""
{% load component_tags %}
{% component "test" %}
{% fill "header" %}Override header{% endfill %}
{% endcomponent %}
{% component "test" %}
{% fill "main" %}Override main{% endfill %}
{% endcomponent %}
{% component "test" %}
{% fill "footer" %}Override footer{% endfill %}
{% endcomponent %}
"""
)
template.render(Context({}))
rendered = template.render(Context({}))
self.assertHTMLEqual(
rendered,
"""
Default main
Override main
Default main
""",
)