""" 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(".my-class { color: red; } """, rendered, count=1, ) # Components' Media.css # Order: # - "style.css", "style2.css" (from SimpleComponentNested) # - "style.css" (from SimpleComponent inside SimpleComponentNested) # - "xyz1.css" (from OtherComponent inserted into SimpleComponentNested) self.assertInHTML( """ """, rendered, count=1, ) # Components' Media.js followed by inlined JS # Order: # - "script2.js" (from SimpleComponentNested) # - "script.js" (from SimpleComponent inside SimpleComponentNested) # - "xyz1.js" (from OtherComponent inserted into SimpleComponentNested) self.assertInHTML( """ """, 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)