"""
template = Template(template_str)
rendered = template.render(
Context(
{
"my_dict": {
"attrs:style": "height: 20px",
"class": "button",
"defaults:class": "my-class",
"defaults:style": "NONO",
},
}
),
)
self.assertHTMLEqual(
rendered,
"""
""",
)
@parametrize_context_behavior(["django", "isolated"])
def test_later_spreads_do_not_overwrite_earlier(self):
@register("test")
class SimpleComponent(Component):
def get_context_data(
self,
*args: Any,
**kwargs: Any,
):
return {
**kwargs,
}
template: types.django_html = """
{{ attrs }}
{{ items }}
{{ a }}
{{ x }}
"""
context = Context(
{
"my_dict": {
"attrs:@click": "() => {}",
"attrs:style": "height: 20px",
"items": [1, 2, 3],
},
"list": [{"a": 1, "x": "OVERWRITTEN_X"}, {"a": 2}, {"a": 3}],
}
)
# Mergingg like this will raise TypeError, because it's like
# a function receiving multiple kwargs with the same name.
template_str1: types.django_html = (
"""
{% load component_tags %}
{% component 'test'
...my_dict
attrs:style="OVERWRITTEN"
x=123
..."{{ list|first }}"
/ %}
"""
)
template1 = Template(template_str1)
with self.assertRaisesMessage(TypeError, "got multiple values for argument 'x'"):
template1.render(context)
# But, similarly to python, we can merge multiple **kwargs by instead
# merging them into a single dict, and spreading that.
template_str2: types.django_html = (
"""
{% load component_tags %}
{% component 'test'
...{
**my_dict,
"x": 123,
**"{{ list|first }}",
}
attrs:style="OVERWRITTEN"
/ %}
"""
)
template2 = Template(template_str2)
rendered2 = template2.render(context)
self.assertHTMLEqual(
rendered2,
"""
{'@click': '() => {}', 'style': 'OVERWRITTEN'}
[1, 2, 3]
1
OVERWRITTEN_X
""",
)
@parametrize_context_behavior(["django", "isolated"])
def test_raises_on_missing_value(self):
@register("test")
class SimpleComponent(Component):
pass
template_str: types.django_html = (
"""
{% load component_tags %}
{% component 'test'
var_a
...
/ %}
"""
)
with self.assertRaisesMessage(TemplateSyntaxError, "Spread syntax '...' is missing a value"):
Template(template_str)
@parametrize_context_behavior(["django", "isolated"])
def test_spread_list_and_iterables(self):
captured = None
@register("test")
class SimpleComponent(Component):
template = ""
def get_context_data(self, *args, **kwargs):
nonlocal captured
captured = args, kwargs
return {}
template_str: types.django_html = (
"""
{% load component_tags %}
{% component 'test'
...var_a
...var_b
/ %}
"""
)
template = Template(template_str)
context = Context(
{
"var_a": "abc",
"var_b": [1, 2, 3],
}
)
template.render(context)
self.assertEqual(
captured,
(
("a", "b", "c", 1, 2, 3),
{},
),
)
@parametrize_context_behavior(["django", "isolated"])
def test_raises_on_non_dict(self):
@register("test")
class SimpleComponent(Component):
pass
template_str: types.django_html = (
"""
{% load component_tags %}
{% component 'test'
...var_b
/ %}
"""
)
template = Template(template_str)
# List
with self.assertRaisesMessage(ValueError, "Cannot spread non-iterable value: '...var_b' resolved to 123"):
template.render(Context({"var_b": 123}))
class AggregateKwargsTest(BaseTestCase):
def test_aggregate_kwargs(self):
captured = None
@register("test")
class Test(Component):
template = ""
def get_context_data(self, *args, **kwargs):
nonlocal captured
captured = args, kwargs
return {}
template_str: types.django_html = """
{% load component_tags %}
{% component 'test'
attrs:@click.stop="dispatch('click_event')"
attrs:x-data="{hello: 'world'}"
attrs:class=class_var
attrs::placeholder="No text"
my_dict:one=2
three=four
/ %}
"""
template = Template(template_str)
template.render(Context({"class_var": "padding-top-8", "four": 4}))
self.assertEqual(
captured,
(
(),
{
"attrs": {
"@click.stop": "dispatch('click_event')",
"x-data": "{hello: 'world'}",
"class": "padding-top-8",
":placeholder": "No text",
},
"my_dict": {"one": 2},
"three": 4,
},
),
)
def is_aggregate_key(self):
self.assertEqual(is_aggregate_key(""), False)
self.assertEqual(is_aggregate_key(" "), False)
self.assertEqual(is_aggregate_key(" : "), False)
self.assertEqual(is_aggregate_key("attrs"), False)
self.assertEqual(is_aggregate_key(":attrs"), False)
self.assertEqual(is_aggregate_key(" :attrs "), False)
self.assertEqual(is_aggregate_key("attrs:"), False)
self.assertEqual(is_aggregate_key(":attrs:"), False)
self.assertEqual(is_aggregate_key("at:trs"), True)
self.assertEqual(is_aggregate_key(":at:trs"), False)