Initial commit
This commit is contained in:
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"],
|
||||
),
|
||||
)
|
||||
Reference in New Issue
Block a user