Initial commit
This commit is contained in:
0
env/lib/python3.10/site-packages/laces/tests/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/laces/tests/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/test_components.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/test_components.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/utils.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/__pycache__/utils.cpython-310.pyc
vendored
Normal file
Binary file not shown.
284
env/lib/python3.10/site-packages/laces/tests/test_components.py
vendored
Normal file
284
env/lib/python3.10/site-packages/laces/tests/test_components.py
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
import os
|
||||
import random
|
||||
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.conf import settings
|
||||
from django.forms import widgets
|
||||
from django.template import Context
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import SafeString
|
||||
|
||||
from laces.components import Component, MediaContainer
|
||||
from laces.tests.utils import MediaAssertionMixin
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from laces.typing import RenderContext
|
||||
|
||||
|
||||
class TestComponent(MediaAssertionMixin, SimpleTestCase):
|
||||
"""Directly test the Component class."""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.component = Component()
|
||||
|
||||
def test_render_html(self) -> None:
|
||||
"""Test the `render_html` method."""
|
||||
# The default Component does not specify a `template_name` attribute which is
|
||||
# required for `render_html`. So calling the method on the Component class
|
||||
# will raise an error.
|
||||
with self.assertRaises(AttributeError):
|
||||
self.component.render_html()
|
||||
|
||||
def test_get_context_data_parent_context_empty_context(self) -> None:
|
||||
"""
|
||||
Test the default get_context_data.
|
||||
|
||||
The parent context should not matter, but we use it as it is used in
|
||||
`render_html` (which passes a `Context` object).
|
||||
"""
|
||||
result = self.component.get_context_data(parent_context=Context())
|
||||
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertEqual(result, {})
|
||||
|
||||
def test_media(self) -> None:
|
||||
"""
|
||||
Test the `media` property.
|
||||
|
||||
The `media` property is added through the `metaclass=MediaDefiningClass`
|
||||
definition.
|
||||
|
||||
"""
|
||||
empty_media = widgets.Media()
|
||||
self.assertIsInstance(self.component.media, widgets.Media)
|
||||
self.assertMediaEqual(self.component.media, empty_media)
|
||||
|
||||
|
||||
class TestComponentSubclasses(MediaAssertionMixin, SimpleTestCase):
|
||||
"""
|
||||
Test the Component class through subclasses.
|
||||
|
||||
Most functionality of the Component class is only unlocked through subclassing and
|
||||
definition of certain attributes (like `template_name`) or overriding of the
|
||||
existing methods. This test class tests the functionality that is unlocked through
|
||||
subclassing.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def make_example_template_name(cls) -> str:
|
||||
return f"example-{random.randint(1000, 10000)}.html"
|
||||
|
||||
@classmethod
|
||||
def get_example_template_name(cls) -> str:
|
||||
example_template_name = cls.make_example_template_name()
|
||||
while os.path.exists(example_template_name):
|
||||
example_template_name = cls.make_example_template_name()
|
||||
return example_template_name
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.example_template_name = self.get_example_template_name()
|
||||
self.example_template = (
|
||||
Path(settings.PROJECT_DIR) / "templates" / self.example_template_name
|
||||
)
|
||||
# Write content to the template file to ensure it exists.
|
||||
self.set_example_template_content("")
|
||||
|
||||
def set_example_template_content(self, content: str) -> None:
|
||||
with open(self.example_template, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
def test_render_html_with_template_name_set(self) -> None:
|
||||
"""
|
||||
Test `render_html` method with a set `template_name` attribute.
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleComponent(Component):
|
||||
template_name = self.example_template_name
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
self.set_example_template_content("Test")
|
||||
|
||||
result = ExampleComponent().render_html()
|
||||
|
||||
self.assertIsInstance(result, str)
|
||||
self.assertIsInstance(result, SafeString)
|
||||
self.assertEqual(result, "Test")
|
||||
|
||||
def test_render_html_with_template_name_set_and_data_from_get_context_data(
|
||||
self,
|
||||
) -> None:
|
||||
"""
|
||||
Test `render_html` method with `get_context_data` providing data for the
|
||||
context.
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleComponent(Component):
|
||||
template_name = self.example_template_name
|
||||
|
||||
def get_context_data(
|
||||
self,
|
||||
parent_context: "Optional[RenderContext]",
|
||||
) -> "RenderContext":
|
||||
return {"name": "World"}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
self.set_example_template_content("Hello {{ name }}")
|
||||
|
||||
result = ExampleComponent().render_html()
|
||||
|
||||
self.assertEqual(result, "Hello World")
|
||||
|
||||
def test_render_html_when_get_context_data_returns_None(self) -> None:
|
||||
"""
|
||||
Test `render_html` method when `get_context_data` returns `None`.
|
||||
|
||||
The `render_html` method raises a `TypeError` when `None` is returned from
|
||||
`get_context_method`. This behavior was present when the class was extracted
|
||||
from Wagtail. It is not totally clear why this specific check is needed. By
|
||||
default, the `get_context_data` method provides and empty dict. If an override
|
||||
wanted to `get_context_data` return `None`, it should be expected that no
|
||||
context data is available during rendering. The underlying `template.render`
|
||||
method does not seem to be ok with `None` as the provided context.
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleComponent(Component):
|
||||
def get_context_data(
|
||||
self,
|
||||
parent_context: "Optional[Union[Context, dict[str, Any]]]",
|
||||
) -> None:
|
||||
return None
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
ExampleComponent().render_html()
|
||||
|
||||
def test_media_defined_through_nested_class(self) -> None:
|
||||
"""
|
||||
Test the `media` property when defined through a nested class.
|
||||
|
||||
The `media` property is added through the `metaclass=MediaDefiningClass`
|
||||
definition. This test ensures that the `media` property is available when
|
||||
configured through a nested class.
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleComponent(Component):
|
||||
class Media:
|
||||
css = {"all": ["example.css"]}
|
||||
js = ["example.js"]
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
result = ExampleComponent().media
|
||||
|
||||
self.assertIsInstance(result, widgets.Media)
|
||||
self.assertMediaEqual(
|
||||
result,
|
||||
widgets.Media(css={"all": ["example.css"]}, js=["example.js"]),
|
||||
)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
os.remove(path=self.example_template)
|
||||
|
||||
|
||||
class TestMediaContainer(MediaAssertionMixin, SimpleTestCase):
|
||||
"""
|
||||
Test the MediaContainer class.
|
||||
|
||||
The `MediaContainer` functionality depends on the `django.forms.widgets.Media`
|
||||
class. The `Media` class provides the logic to combine the media definitions of
|
||||
multiple objects through its `__add__` method. The `MediaContainer` relies on this
|
||||
functionality to provide a `media` property that combines the media definitions of
|
||||
its members.
|
||||
|
||||
See also:
|
||||
https://docs.djangoproject.com/en/4.2/topics/forms/media
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.media_container = MediaContainer()
|
||||
|
||||
def test_empty(self) -> None:
|
||||
result = self.media_container.media
|
||||
|
||||
self.assertIsInstance(result, widgets.Media)
|
||||
self.assertMediaEqual(result, widgets.Media())
|
||||
|
||||
def test_single_member(self) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleClass:
|
||||
media = widgets.Media(css={"all": ["example.css"]})
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
example = ExampleClass()
|
||||
self.media_container.append(example)
|
||||
|
||||
result = self.media_container.media
|
||||
|
||||
self.assertIsInstance(result, widgets.Media)
|
||||
self.assertMediaEqual(result, example.media)
|
||||
self.assertMediaEqual(result, widgets.Media(css={"all": ["example.css"]}))
|
||||
|
||||
def test_two_members_of_same_class(self) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleClass:
|
||||
media = widgets.Media(css={"all": ["example.css"]}, js=["example.js"])
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
example_1 = ExampleClass()
|
||||
example_2 = ExampleClass()
|
||||
self.media_container.append(example_1)
|
||||
self.media_container.append(example_2)
|
||||
|
||||
result = self.media_container.media
|
||||
|
||||
self.assertIsInstance(result, widgets.Media)
|
||||
self.assertMediaEqual(
|
||||
result,
|
||||
widgets.Media(css={"all": ["example.css"]}, js=["example.js"]),
|
||||
)
|
||||
|
||||
def test_two_members_of_different_classes(self) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleClass:
|
||||
media = widgets.Media(css={"all": ["shared.css"]}, js=["example.js"])
|
||||
|
||||
class OtherExampleClass:
|
||||
media = widgets.Media(
|
||||
css={
|
||||
"all": ["other.css", "shared.css"],
|
||||
"print": ["print.css"],
|
||||
},
|
||||
js=["other.js"],
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
example = ExampleClass()
|
||||
self.media_container.append(example)
|
||||
other = OtherExampleClass()
|
||||
self.media_container.append(other)
|
||||
|
||||
result = self.media_container.media
|
||||
|
||||
self.assertIsInstance(result, widgets.Media)
|
||||
self.assertMediaEqual(
|
||||
result,
|
||||
widgets.Media(
|
||||
css={
|
||||
"all": ["other.css", "shared.css"],
|
||||
"print": ["print.css"],
|
||||
},
|
||||
js=["example.js", "other.js"],
|
||||
),
|
||||
)
|
||||
0
env/lib/python3.10/site-packages/laces/tests/test_templatetags/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/laces/tests/test_templatetags/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/test_templatetags/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/laces/tests/test_templatetags/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
441
env/lib/python3.10/site-packages/laces/tests/test_templatetags/test_laces.py
vendored
Normal file
441
env/lib/python3.10/site-packages/laces/tests/test_templatetags/test_laces.py
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
import os
|
||||
import random
|
||||
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from django.conf import settings
|
||||
from django.template import Context, Template, TemplateSyntaxError
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.html import format_html
|
||||
|
||||
from laces.components import Component
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from django.utils.safestring import SafeString
|
||||
|
||||
from laces.typing import RenderContext
|
||||
|
||||
|
||||
class CopyingMock(MagicMock):
|
||||
"""
|
||||
A mock that stores copies of the call arguments.
|
||||
|
||||
The default behaviour of a mock is to store references to the call arguments. This
|
||||
means that if the call arguments are mutable, then the stored call arguments will
|
||||
change when the call arguments are changed. This is not always desirable. E.g. the
|
||||
`django.template.Context` class is mutable and the different layers are popped off
|
||||
the context during rendering. This makes it hard to inspect the context that was
|
||||
passed to a mock.
|
||||
|
||||
This variant of the mock stores copies of the call arguments. This means that the
|
||||
stored call arguments will not change when the actual call arguments are changed.
|
||||
|
||||
This override is based on the Python docs:
|
||||
https://docs.python.org/3/library/unittest.mock-examples.html#coping-with-mutable-arguments # noqa: E501
|
||||
"""
|
||||
|
||||
def __call__(self, /, *args: "List[Any]", **kwargs: "Dict[str, Any]") -> "Any":
|
||||
args = deepcopy(args)
|
||||
kwargs = deepcopy(kwargs)
|
||||
return super().__call__(*args, **kwargs)
|
||||
|
||||
|
||||
class TestComponentTag(SimpleTestCase):
|
||||
"""
|
||||
Test for the `component` template tag.
|
||||
|
||||
Extracted from Wagtail. See:
|
||||
https://github.com/wagtail/wagtail/blob/main/wagtail/admin/tests/test_templatetags.py#L225-L305 # noqa: E501
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.parent_template = Template("")
|
||||
|
||||
class ExampleComponent(Component):
|
||||
# Using a mock to be able to check if the `render_html` method is called.
|
||||
render_html = CopyingMock(return_value="Rendered HTML")
|
||||
|
||||
self.component = ExampleComponent()
|
||||
|
||||
def set_parent_template(self, template_string: str) -> None:
|
||||
template_string = "{% load laces %}" + template_string
|
||||
self.parent_template = Template(template_string)
|
||||
|
||||
def render_parent_template_with_context(
|
||||
self,
|
||||
context: "RenderContext",
|
||||
) -> "SafeString":
|
||||
"""
|
||||
Render the parent template with the given context.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
context: RenderContext
|
||||
Context to render the parent template with.
|
||||
|
||||
Returns
|
||||
-------
|
||||
SafeString
|
||||
The parent template rendered with the given context.
|
||||
"""
|
||||
return self.parent_template.render(Context(context))
|
||||
|
||||
def assertVariablesAvailableInRenderHTMLParentContext(
|
||||
self,
|
||||
expected_context_variables: "Dict[str, Any]",
|
||||
) -> None:
|
||||
"""
|
||||
Assert that the variables defined in the given dictionary are available in the
|
||||
parent context of the `render_html` method.
|
||||
|
||||
Keys and values are checked.
|
||||
"""
|
||||
actual_context = self.component.render_html.call_args.args[0]
|
||||
|
||||
for key, value in expected_context_variables.items():
|
||||
self.assertIn(key, actual_context)
|
||||
actual_value = actual_context[key]
|
||||
if not isinstance(actual_value, Component):
|
||||
# Because we are inspecting copies of the context variables, we cannot
|
||||
# easily compare the components by identity. For now, we just
|
||||
# skip components.
|
||||
self.assertEqual(actual_value, value)
|
||||
|
||||
def test_render_html_return_in_parent_template(self) -> None:
|
||||
self.assertEqual(self.component.render_html(), "Rendered HTML")
|
||||
self.set_parent_template("Before {% component my_component %} After")
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": self.component},
|
||||
)
|
||||
|
||||
# This matches the return value of the `render_html` method inserted into the
|
||||
# parent template.
|
||||
self.assertEqual(result, "Before Rendered HTML After")
|
||||
|
||||
def test_render_html_return_is_escaped(self) -> None:
|
||||
self.component.render_html.return_value = (
|
||||
"Look, I'm running with scissors! 8< 8< 8<"
|
||||
)
|
||||
self.set_parent_template("{% component my_component %}")
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": self.component},
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
"Look, I'm running with scissors! 8< 8< 8<",
|
||||
)
|
||||
|
||||
def test_render_html_return_not_escaped_when_formatted_html(self) -> None:
|
||||
self.component.render_html.return_value = format_html("<h1>My component</h1>")
|
||||
self.set_parent_template("{% component my_component %}")
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": self.component},
|
||||
)
|
||||
|
||||
self.assertEqual(result, "<h1>My component</h1>")
|
||||
|
||||
def test_render_html_return_not_escaped_when_actually_rendered_template(
|
||||
self,
|
||||
) -> None:
|
||||
example_template_name = f"example-{random.randint(1000, 10000)}.html"
|
||||
example_template = (
|
||||
Path(settings.PROJECT_DIR) / "templates" / example_template_name
|
||||
)
|
||||
with open(example_template, "w") as f:
|
||||
f.write("<h1>My component</h1>")
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
class RealExampleComponent(Component):
|
||||
template_name = example_template_name
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
component = RealExampleComponent()
|
||||
self.set_parent_template("{% component my_component %}")
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": component},
|
||||
)
|
||||
|
||||
self.assertEqual(result, "<h1>My component</h1>")
|
||||
os.remove(example_template)
|
||||
|
||||
def test_render_html_parent_context_when_only_component_in_context(self) -> None:
|
||||
self.set_parent_template("{% component my_component %}")
|
||||
|
||||
self.render_parent_template_with_context({"my_component": self.component})
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{"my_component": self.component}
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_other_variable_in_context(self) -> None:
|
||||
self.set_parent_template("{% component my_component %}")
|
||||
|
||||
self.render_parent_template_with_context(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_with_block_sets_extra_context(
|
||||
self,
|
||||
) -> None:
|
||||
self.set_parent_template(
|
||||
"{% with test='something' %}{% component my_component %}{% endwith %}"
|
||||
)
|
||||
|
||||
self.render_parent_template_with_context({"my_component": self.component})
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_with_keyword_sets_extra_context(
|
||||
self,
|
||||
) -> None:
|
||||
self.set_parent_template("{% component my_component with test='something' %}")
|
||||
|
||||
self.render_parent_template_with_context({"my_component": self.component})
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_with_only_keyword_limits_extra_context(
|
||||
self,
|
||||
) -> None:
|
||||
self.set_parent_template(
|
||||
"{% component my_component with test='nothing else' only %}"
|
||||
)
|
||||
|
||||
self.render_parent_template_with_context(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"other": "something else",
|
||||
}
|
||||
)
|
||||
|
||||
# The `my_component` and `other` variables from the parent's rendering context
|
||||
# are not included in the context that is passed to the `render_html` method.
|
||||
# The `test` variable, that was defined with the with-keyword, is present
|
||||
# though. Both of these effects come form the `only` keyword.
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext({"test": "nothing else"})
|
||||
|
||||
def test_render_html_parent_context_when_with_block_overrides_context(self) -> None:
|
||||
self.set_parent_template(
|
||||
"{% with test='something else' %}{% component my_component %}{% endwith %}"
|
||||
)
|
||||
|
||||
self.render_parent_template_with_context(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
# The `test` variable is overriden by the `with` block.
|
||||
"test": "something else",
|
||||
}
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_with_keyword_overrides_context(
|
||||
self,
|
||||
) -> None:
|
||||
self.set_parent_template(
|
||||
"{% component my_component with test='something else' %}"
|
||||
)
|
||||
|
||||
self.render_parent_template_with_context(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something",
|
||||
}
|
||||
)
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
# The `test` variable is overriden by the `with` keyword.
|
||||
"test": "something else",
|
||||
},
|
||||
)
|
||||
|
||||
def test_render_html_parent_context_when_with_keyword_overrides_with_block(
|
||||
self,
|
||||
) -> None:
|
||||
self.set_parent_template(
|
||||
"""
|
||||
{% with test='something' %}
|
||||
{% component my_component with test='something else' %}
|
||||
{% endwith %}
|
||||
"""
|
||||
)
|
||||
|
||||
self.render_parent_template_with_context({"my_component": self.component})
|
||||
|
||||
self.assertVariablesAvailableInRenderHTMLParentContext(
|
||||
{
|
||||
"my_component": self.component,
|
||||
"test": "something else",
|
||||
}
|
||||
)
|
||||
|
||||
def test_fallback_render_method_arg_true_and_object_with_render_method(
|
||||
self,
|
||||
) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleNonComponentWithRenderMethod:
|
||||
def render(self) -> str:
|
||||
return "Rendered non-component"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
non_component = ExampleNonComponentWithRenderMethod()
|
||||
self.set_parent_template(
|
||||
"{% component my_non_component fallback_render_method=True %}"
|
||||
)
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_non_component": non_component},
|
||||
)
|
||||
|
||||
self.assertEqual(result, "Rendered non-component")
|
||||
|
||||
def test_fallback_render_method_arg_true_but_object_without_render_method(
|
||||
self,
|
||||
) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleNonComponentWithoutRenderMethod:
|
||||
pass
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
non_component = ExampleNonComponentWithoutRenderMethod()
|
||||
self.set_parent_template(
|
||||
"{% component my_non_component fallback_render_method=True %}"
|
||||
)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.render_parent_template_with_context(
|
||||
{"my_non_component": non_component},
|
||||
)
|
||||
|
||||
def test_no_fallback_render_method_arg_and_object_without_render_method(
|
||||
self,
|
||||
) -> None:
|
||||
# -----------------------------------------------------------------------------
|
||||
class ExampleNonComponentWithoutRenderMethod:
|
||||
def __repr__(self) -> str:
|
||||
return "<Example repr>"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
non_component = ExampleNonComponentWithoutRenderMethod()
|
||||
self.set_parent_template("{% component my_non_component %}")
|
||||
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
self.render_parent_template_with_context(
|
||||
{"my_non_component": non_component},
|
||||
)
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Cannot render <Example repr> as a component",
|
||||
)
|
||||
|
||||
def test_as_keyword_stores_render_html_return_as_variable(self) -> None:
|
||||
self.set_parent_template(
|
||||
"{% component my_component as my_var %}The result was: {{ my_var }}"
|
||||
)
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": self.component},
|
||||
)
|
||||
|
||||
self.assertEqual(result, "The result was: Rendered HTML")
|
||||
|
||||
def test_as_keyword_without_variable_name(self) -> None:
|
||||
# The template is already parsed when the parent template is set. This is the
|
||||
# moment where the parsing error is raised.
|
||||
with self.assertRaises(TemplateSyntaxError) as cm:
|
||||
self.set_parent_template("{% component my_component as %}")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"'component' tag with 'as' must be followed by a variable name",
|
||||
)
|
||||
|
||||
def test_autoescape_off_block_can_disable_escaping_of_render_html_return(
|
||||
self,
|
||||
) -> None:
|
||||
self.component.render_html.return_value = (
|
||||
"Look, I'm running with scissors! 8< 8< 8<"
|
||||
)
|
||||
self.set_parent_template(
|
||||
"{% autoescape off %}{% component my_component %}{% endautoescape %}"
|
||||
)
|
||||
|
||||
result = self.render_parent_template_with_context(
|
||||
{"my_component": self.component},
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
"Look, I'm running with scissors! 8< 8< 8<",
|
||||
)
|
||||
|
||||
def test_parsing_no_arguments(self) -> None:
|
||||
# The template is already parsed when the parent template is set. This is the
|
||||
# moment where the parsing error is raised.
|
||||
with self.assertRaises(TemplateSyntaxError) as cm:
|
||||
self.set_parent_template("{% component %}")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"'component' tag requires at least one argument, the component object",
|
||||
)
|
||||
|
||||
def test_parsing_unknown_kwarg(self) -> None:
|
||||
# The template is already parsed when the parent template is set. This is the
|
||||
# moment where the parsing error is raised.
|
||||
with self.assertRaises(TemplateSyntaxError) as cm:
|
||||
self.set_parent_template("{% component my_component unknown_kwarg=True %}")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"'component' tag only accepts 'fallback_render_method' as a keyword argument",
|
||||
)
|
||||
|
||||
def test_parsing_unknown_bit(self) -> None:
|
||||
# The template is already parsed when the parent template is set. This is the
|
||||
# moment where the parsing error is raised.
|
||||
with self.assertRaises(TemplateSyntaxError) as cm:
|
||||
self.set_parent_template("{% component my_component unknown_bit %}")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"'component' tag received an unknown argument: 'unknown_bit'",
|
||||
)
|
||||
29
env/lib/python3.10/site-packages/laces/tests/utils.py
vendored
Normal file
29
env/lib/python3.10/site-packages/laces/tests/utils.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"""Utilities for tests in the `laces` package."""
|
||||
|
||||
from django.forms import widgets
|
||||
|
||||
|
||||
class MediaAssertionMixin:
|
||||
@staticmethod
|
||||
def assertMediaEqual(first: widgets.Media, second: widgets.Media) -> bool:
|
||||
"""
|
||||
Compare two `Media` instances.
|
||||
|
||||
The `Media` class does not implement `__eq__`, but its `__repr__` shows how to
|
||||
recreate the instance.
|
||||
We can use this to compare two `Media` instances.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
first : widgets.Media
|
||||
First `Media` instance.
|
||||
second : widgets.Media
|
||||
Second `Media` instance.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether the two `Media` instances are equal.
|
||||
|
||||
"""
|
||||
return repr(first) == repr(second)
|
||||
Reference in New Issue
Block a user