diff options
| author | Claude Paroz <claude@2xlibre.net> | 2022-01-22 17:21:57 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-10 08:48:27 +0100 |
| commit | 4c76ffc2d6c77c850b4bef8d9acc197d11c47937 (patch) | |
| tree | 943f449e397f362057c3f57906e7bdcc49fcbb2f /tests/forms_tests | |
| parent | cda81b79f212e0666782393c52ad19c2790c9446 (diff) | |
Fixed #29490 -- Added support for object-based Media CSS and JS paths.
Diffstat (limited to 'tests/forms_tests')
| -rw-r--r-- | tests/forms_tests/tests/test_media.py | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/tests/forms_tests/tests/test_media.py b/tests/forms_tests/tests/test_media.py index 4338321af8..171b70e508 100644 --- a/tests/forms_tests/tests/test_media.py +++ b/tests/forms_tests/tests/test_media.py @@ -1,6 +1,8 @@ from django.forms import CharField, Form, Media, MultiWidget, TextInput from django.template import Context, Template +from django.templatetags.static import static from django.test import SimpleTestCase, override_settings +from django.utils.html import format_html, html_safe @override_settings( @@ -710,3 +712,160 @@ class FormsMediaTestCase(SimpleTestCase): merged = media + empty_media self.assertEqual(merged._css_lists, [{"screen": ["a.css"]}]) self.assertEqual(merged._js_lists, [["a"]]) + + +@html_safe +class Asset: + def __init__(self, path): + self.path = path + + def __eq__(self, other): + return (self.__class__ == other.__class__ and self.path == other.path) or ( + other.__class__ == str and self.path == other + ) + + def __hash__(self): + return hash(self.path) + + def __str__(self): + return self.absolute_path(self.path) + + def absolute_path(self, path): + """ + Given a relative or absolute path to a static asset, return an absolute + path. An absolute path will be returned unchanged while a relative path + will be passed to django.templatetags.static.static(). + """ + if path.startswith(("http://", "https://", "/")): + return path + return static(path) + + def __repr__(self): + return f"{self.path!r}" + + +class CSS(Asset): + def __init__(self, path, medium): + super().__init__(path) + self.medium = medium + + def __str__(self): + path = super().__str__() + return format_html( + '<link href="{}" media="{}" rel="stylesheet">', + self.absolute_path(path), + self.medium, + ) + + +class JS(Asset): + def __init__(self, path, integrity=None): + super().__init__(path) + self.integrity = integrity or "" + + def __str__(self, integrity=None): + path = super().__str__() + template = '<script src="{}"%s></script>' % ( + ' integrity="{}"' if self.integrity else "{}" + ) + return format_html(template, self.absolute_path(path), self.integrity) + + +@override_settings( + STATIC_URL="http://media.example.com/static/", +) +class FormsMediaObjectTestCase(SimpleTestCase): + """Media handling when media are objects instead of raw strings.""" + + def test_construction(self): + m = Media( + css={"all": (CSS("path/to/css1", "all"), CSS("/path/to/css2", "all"))}, + js=( + JS("/path/to/js1"), + JS("http://media.other.com/path/to/js2"), + JS( + "https://secure.other.com/path/to/js3", + integrity="9d947b87fdeb25030d56d01f7aa75800", + ), + ), + ) + self.assertEqual( + str(m), + '<link href="http://media.example.com/static/path/to/css1" media="all" ' + 'rel="stylesheet">\n' + '<link href="/path/to/css2" media="all" rel="stylesheet">\n' + '<script src="/path/to/js1"></script>\n' + '<script src="http://media.other.com/path/to/js2"></script>\n' + '<script src="https://secure.other.com/path/to/js3" ' + 'integrity="9d947b87fdeb25030d56d01f7aa75800"></script>', + ) + self.assertEqual( + repr(m), + "Media(css={'all': ['path/to/css1', '/path/to/css2']}, " + "js=['/path/to/js1', 'http://media.other.com/path/to/js2', " + "'https://secure.other.com/path/to/js3'])", + ) + + def test_simplest_class(self): + @html_safe + class SimpleJS: + """The simplest possible asset class.""" + + def __str__(self): + return '<script src="https://example.org/asset.js" rel="stylesheet">' + + m = Media(js=(SimpleJS(),)) + self.assertEqual( + str(m), + '<script src="https://example.org/asset.js" rel="stylesheet">', + ) + + def test_combine_media(self): + class MyWidget1(TextInput): + class Media: + css = {"all": (CSS("path/to/css1", "all"), "/path/to/css2")} + js = ( + "/path/to/js1", + "http://media.other.com/path/to/js2", + "https://secure.other.com/path/to/js3", + JS("/path/to/js4", integrity="9d947b87fdeb25030d56d01f7aa75800"), + ) + + class MyWidget2(TextInput): + class Media: + css = {"all": (CSS("/path/to/css2", "all"), "/path/to/css3")} + js = (JS("/path/to/js1"), "/path/to/js4") + + w1 = MyWidget1() + w2 = MyWidget2() + self.assertEqual( + str(w1.media + w2.media), + '<link href="http://media.example.com/static/path/to/css1" media="all" ' + 'rel="stylesheet">\n' + '<link href="/path/to/css2" media="all" rel="stylesheet">\n' + '<link href="/path/to/css3" media="all" rel="stylesheet">\n' + '<script src="/path/to/js1"></script>\n' + '<script src="http://media.other.com/path/to/js2"></script>\n' + '<script src="https://secure.other.com/path/to/js3"></script>\n' + '<script src="/path/to/js4" integrity="9d947b87fdeb25030d56d01f7aa75800">' + "</script>", + ) + + def test_media_deduplication(self): + # The deduplication doesn't only happen at the point of merging two or + # more media objects. + media = Media( + css={ + "all": ( + CSS("/path/to/css1", "all"), + CSS("/path/to/css1", "all"), + "/path/to/css1", + ) + }, + js=(JS("/path/to/js1"), JS("/path/to/js1"), "/path/to/js1"), + ) + self.assertEqual( + str(media), + '<link href="/path/to/css1" media="all" rel="stylesheet">\n' + '<script src="/path/to/js1"></script>', + ) |
