"""
Here we check that the logic around dependency rendering outputs correct HTML.
During actual rendering, the HTML is then picked up by the JS-side dependency manager.
"""
import re
from django.template import Template
from django_components import Component, registry, types
from .django_test_setup import setup_test_config
from .testutils import BaseTestCase, create_and_process_template_response
setup_test_config({"autodiscover": False})
def to_spaces(s: str):
return re.compile(r"\s+").sub(" ", s)
class SimpleComponent(Component):
template: types.django_html = """
Variable: {{ variable }}
"""
def get_context_data(self, variable, variable2="default"):
return {
"variable": variable,
"variable2": variable2,
}
class Media:
css = "style.css"
js = "script.js"
class SimpleComponentNested(Component):
template: types.django_html = """
{% load component_tags %}
{% component "inner" variable=variable / %}
{% slot "default" default / %}
"""
css: types.css = """
.my-class {
color: red;
}
"""
js: types.js = """
console.log("Hello");
"""
def get_context_data(self, variable):
return {}
class Media:
css = ["style.css", "style2.css"]
js = "script2.js"
class OtherComponent(Component):
template: types.django_html = """
XYZ: {{ variable }}
"""
css: types.css = """
.xyz {
color: red;
}
"""
js: types.js = """
console.log("xyz");
"""
def get_context_data(self, variable):
return {}
class Media:
css = "xyz1.css"
js = "xyz1.js"
class SimpleComponentWithSharedDependency(Component):
template: types.django_html = """
Variable: {{ variable }}
"""
def get_context_data(self, variable, variable2="default"):
return {}
class Media:
css = ["style.css", "style2.css"]
js = ["script.js", "script2.js"]
class MultistyleComponent(Component):
template: types.django_html = """
Variable: {{ variable }}
"""
class Media:
css = ["style.css", "style2.css"]
js = ["script.js", "script2.js"]
class DependencyRenderingTests(BaseTestCase):
def test_no_dependencies_when_no_components_used(self):
registry.register(name="test", component=SimpleComponent)
template_str: types.django_html = """
{% load component_tags %}
{% component_js_dependencies %}
{% component_css_dependencies %}
"""
template = Template(template_str)
rendered = create_and_process_template_response(template)
# Dependency manager script
self.assertInHTML('', rendered, count=1)
self.assertEqual(rendered.count("', rendered, count=1)
self.assertEqual(rendered.count("', rendered, count=1)
self.assertEqual(rendered.count(' '), 1) # Media.css
self.assertEqual(rendered.count(" ', rendered, count=1)
self.assertEqual(rendered.count(' '), 1) # Media.css
self.assertEqual(rendered.count(" ', rendered, count=0)
self.assertEqual(rendered.count(" '), 1) # Media.css
def test_single_component_js_dependencies(self):
registry.register(name="test", component=SimpleComponent)
template_str: types.django_html = """
{% load component_tags %}{% component_js_dependencies %}
{% component 'test' variable='foo' %}{% endcomponent %}
"""
template = Template(template_str)
rendered = create_and_process_template_response(template)
# Dependency manager script
self.assertInHTML('', rendered, count=1)
# CSS NOT included
self.assertEqual(rendered.count(" ', rendered, count=1)
self.assertEqual(rendered.count("
""",
rendered,
count=1,
)
# Media.js
self.assertInHTML(
"""
""",
rendered,
count=1,
)
# We expect to find this:
# ```js
# Components.manager._loadComponentScripts({
# loadedCssUrls: ["style.css", "style2.css"],
# loadedJsUrls: ["script.js", "script2.js"],
# toLoadCssTags: [],
# toLoadJsTags: [],
# });
# ```
self.assertEqual(rendered.count("loadedCssUrls: ["style.css", "style2.css"],"), 1)
self.assertEqual(rendered.count("loadedJsUrls: ["script.js", "script2.js""), 1)
self.assertEqual(rendered.count("toLoadCssTags: [],"), 1)
self.assertEqual(rendered.count("toLoadJsTags: [],"), 1)
def test_no_dependencies_with_multiple_unused_components(self):
registry.register(name="inner", component=SimpleComponent)
registry.register(name="outer", component=SimpleComponentNested)
template_str: types.django_html = """
{% load component_tags %}
{% component_js_dependencies %}
{% component_css_dependencies %}
"""
template = Template(template_str)
rendered = create_and_process_template_response(template)
# Dependency manager script
self.assertInHTML('', rendered, count=1)
self.assertEqual(rendered.count("', rendered, count=1)
self.assertEqual(rendered.count("
""",
rendered,
count=1,
)
# We expect to find this:
# ```js
# Components.manager._loadComponentScripts({
# loadedCssUrls: ["/components/cache/OtherComponent_6329ae.css/", "/components/cache/SimpleComponentNested_f02d32.css/", "style.css", "style2.css", "xyz1.css"],
# loadedJsUrls: ["/components/cache/OtherComponent_6329ae.js/", "/components/cache/SimpleComponentNested_f02d32.js/", "script.js", "script2.js", "xyz1.js"],
# toLoadCssTags: [],
# toLoadJsTags: [],
# });
# ```
self.assertEqual(
rendered.count(
"loadedJsUrls: ["/components/cache/OtherComponent_6329ae.js/", "/components/cache/SimpleComponentNested_f02d32.js/", "script.js", "script2.js", "xyz1.js"],"
),
1,
)
self.assertEqual(
rendered.count(
"loadedCssUrls: ["/components/cache/OtherComponent_6329ae.css/", "/components/cache/SimpleComponentNested_f02d32.css/", "style.css", "style2.css", "xyz1.css"],"
),
1,
)
self.assertEqual(rendered.count("toLoadJsTags: [],"), 1)
self.assertEqual(rendered.count("toLoadCssTags: [],"), 1)
def test_multiple_components_all_placeholders_removed(self):
registry.register(name="inner", component=SimpleComponent)
registry.register(name="outer", component=SimpleComponentNested)
registry.register(name="test", component=SimpleComponentWithSharedDependency)
template_str: types.django_html = """
{% load component_tags %}
{% component_js_dependencies %}
{% component_css_dependencies %}
{% component 'inner' variable='variable' / %}
{% component 'outer' variable='variable' / %}
{% component 'test' variable='variable' / %}
"""
template = Template(template_str)
rendered = create_and_process_template_response(template)
self.assertNotIn("_RENDERED", rendered)