Skip to content

Commit a082a96

Browse files
committed
Skip script tags for root element. Only write window stub for parent elements.
1 parent de50acf commit a082a96

File tree

3 files changed

+28
-18
lines changed

3 files changed

+28
-18
lines changed

src/django_unicorn/components/unicorn_template_response.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def get_root_element(content: str) -> html.HtmlElement:
7979
else:
8080
# lxml.html.fragments_fromstring returns a list of elements/strings
8181
fragments = html.fragments_fromstring(content)
82-
elements = [f for f in fragments if isinstance(f, html.HtmlElement)]
82+
elements = [f for f in fragments if isinstance(f, html.HtmlElement) and f.tag != "script"]
8383

8484
if not elements:
8585
raise MissingComponentElementError("No root element for the component was found")
@@ -117,7 +117,7 @@ def assert_has_single_wrapper_element(content: str, component_name: str) -> None
117117
elements = [content]
118118
else:
119119
fragments = html.fragments_fromstring(content)
120-
elements = [f for f in fragments if isinstance(f, html.HtmlElement)]
120+
elements = [f for f in fragments if isinstance(f, html.HtmlElement) and (f.tag != "script" or f.attrib)]
121121
except Exception:
122122
# Should have been caught by get_root_element usually
123123
return

src/django_unicorn/templatetags/unicorn.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,6 @@ def __init__(
8585
self.parent = None
8686

8787
def render(self, context):
88-
# Ensure that window.Unicorn exists before any component is rendered
89-
# so that inline scripts can attach functions to it without errors
90-
unicorn_stub = ""
91-
92-
if not context.get("unicorn_stub_rendered"):
93-
unicorn_stub = mark_safe("<script>window.Unicorn = window.Unicorn || {};</script>\n")
94-
context["unicorn_stub_rendered"] = True
95-
9688
request = None
9789

9890
if hasattr(context, "request"):
@@ -152,6 +144,14 @@ def render(self, context):
152144
except template.VariableDoesNotExist:
153145
pass # no implicit parent present
154146

147+
# Ensure that window.Unicorn exists before any component is rendered
148+
# so that inline scripts can attach functions to it without errors
149+
unicorn_stub = ""
150+
151+
if not self.parent and not context.get("unicorn_stub_rendered"):
152+
unicorn_stub = mark_safe("<script>window.Unicorn = window.Unicorn || {};</script>\n")
153+
context["unicorn_stub_rendered"] = True
154+
155155
component_id = None
156156

157157
try:

tests/templatetags/test_unicorn_render.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,21 @@ def test_unicorn_template_renders(client):
100100

101101
assert response.wsgi_request.path == "/test"
102102
assert "WSGIRequest" in content
103-
assert content.startswith("<div unicorn:id")
104-
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentKwargs"' in content
103+
root_element = get_root_element(content)
104+
assert root_element.tag == "div"
105+
assert "unicorn:id" in root_element.attrib
106+
assert root_element.attrib.get("unicorn:name") == "tests.templatetags.test_unicorn_render.FakeComponentKwargs"
105107

106108

107109
def test_unicorn_template_renders_with_parent_and_child(client):
108110
response = client.get("/test-parent")
109111
content = response.content.decode().strip()
110112

111113
assert response.wsgi_request.path == "/test-parent"
112-
assert content.startswith("<div unicorn:id")
113-
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentParent"' in content
114+
root_element = get_root_element(content)
115+
assert root_element.tag == "div"
116+
assert "unicorn:id" in root_element.attrib
117+
assert root_element.attrib.get("unicorn:name") == "tests.templatetags.test_unicorn_render.FakeComponentParent"
114118
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentChild"' in content
115119
assert "--parent--" in content
116120
assert "==child==" in content
@@ -121,8 +125,10 @@ def test_unicorn_template_renders_with_parent_and_child_with_templateview(client
121125
content = response.content.decode().strip()
122126

123127
assert response.wsgi_request.path == "/test-parent-template"
124-
assert content.startswith("<div unicorn:id")
125-
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentParent"' in content
128+
root_element = get_root_element(content)
129+
assert root_element.tag == "div"
130+
assert "unicorn:id" in root_element.attrib
131+
assert root_element.attrib.get("unicorn:name") == "tests.templatetags.test_unicorn_render.FakeComponentParent"
126132
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentChild"' in content
127133
assert "--parent--" in content
128134
assert "==child==" in content
@@ -133,8 +139,12 @@ def test_unicorn_template_renders_with_implicit_parent_and_child(client):
133139
content = response.content.decode().strip()
134140

135141
assert response.wsgi_request.path == "/test-parent-implicit"
136-
assert content.startswith("<div unicorn:id")
137-
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentParentImplicit"' in content
142+
root_element = get_root_element(content)
143+
assert root_element.tag == "div"
144+
assert "unicorn:id" in root_element.attrib
145+
assert (
146+
root_element.attrib.get("unicorn:name") == "tests.templatetags.test_unicorn_render.FakeComponentParentImplicit"
147+
)
138148
assert 'unicorn:name="tests.templatetags.test_unicorn_render.FakeComponentChildImplicit"' in content
139149
assert "--parent--" in content
140150
assert "==child==" in content

0 commit comments

Comments
 (0)