""" 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("'), 1) # Media.css self.assertEqual(rendered.count(''), 1) self.assertEqual(rendered.count("const loadedJsScripts = [];"), 1) self.assertEqual( rendered.count("const loadedCssScripts = ["style.css", "style2.css"];"), 1 ) self.assertEqual( rendered.count( r"const toLoadJsScripts = [Components.unescapeJs(\`<script src="script.js"></script>\`), Components.unescapeJs(\`<script src="script2.js"></script>\`)];" ), 1, ) self.assertEqual( rendered.count( r"const toLoadCssScripts = [Components.unescapeJs(\`<link href="style.css" media="all" rel="stylesheet">\`), Components.unescapeJs(\`<link href="style2.css" media="all" rel="stylesheet">\`)];" ), 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(".xyz { color: red; }", rendered, count=1) self.assertInHTML("", rendered, count=1) # Components' Media.css # NOTE: Each of these should be present only ONCE! self.assertInHTML('', rendered, count=1) self.assertInHTML('', rendered, count=1) self.assertInHTML('', rendered, count=1) self.assertEqual( rendered.count( "const loadedJsScripts = ["/components/cache/OtherComponent_6329ae.js/", "/components/cache/SimpleComponentNested_f02d32.js/"];" ), 1, ) self.assertEqual( rendered.count( "const loadedCssScripts = ["/components/cache/OtherComponent_6329ae.css/", "/components/cache/SimpleComponentNested_f02d32.css/", "style.css", "style2.css", "xyz1.css"];" ), 1, ) self.assertEqual( rendered.count( r"const toLoadJsScripts = [Components.unescapeJs(\`<script src="script.js"></script>\`), Components.unescapeJs(\`<script src="script2.js"></script>\`), Components.unescapeJs(\`<script src="xyz1.js"></script>\`)];" ), 1, ) self.assertEqual( rendered.count( r"const toLoadCssScripts = [Components.unescapeJs(\`<link href="style.css" media="all" rel="stylesheet">\`), Components.unescapeJs(\`<link href="style2.css" media="all" rel="stylesheet">\`), Components.unescapeJs(\`<link href="xyz1.css" media="all" rel="stylesheet">\`)];" ), 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)