chore: Push dev to master to release v0.110 (#767)

* feat: skeleton of dependency manager backend (#688)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: selectolax update and tests cleanup (#702)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: move release notes to own file (#704)

* chore: merge changes from master (#705)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Yassin Rakha <yaso2go@gmail.com>
Co-authored-by: Emil Stenström <emil@emilstenstrom.se>
fix for nested slots (#698) (#699)

* refactor: remove joint {% component_dependencies %} tag (#706)

Co-authored-by: Emil Stenström <emil@emilstenstrom.se>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: split up utils file and move utils to util dir (#707)

* docs: Move docs inside src/ to allow imports in python scripts (#708)

* refactor: Docs prep 1 (#715)

* refactor: Document template tags (#716)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: pass slot fills in template via slots param (#719)

* chore: Merge master to dev (#729)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Yassin Rakha <yaso2go@gmail.com>
Co-authored-by: Emil Stenström <emil@emilstenstrom.se>
Co-authored-by: Tom Larsen <larsent@gmail.com>
fix for nested slots (#698) (#699)

* fix: Do not raise error if multiple slots with same name are flagged as default (#727)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: tag formatter - allow fwd slash in end tag (#730)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* refactor: Use lowercase names for registry settings (#731)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* docs: add docstrings (#732)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* feat: define settings as a data class for type hints, intellisense, and docs (#733)

* refactor: fix reload-on-change logic, expose autodiscover's dirs-getting logic, rename settings (#734)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* docs: document settings (#743)

* docs: document settings

* refactor: fix linter errors

* feat: passthrough slots and more (#758)

* feat: passthrough slots and more

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* refactor: remove ComponentSlotContext.slots

* refactor: update comment

* docs: update changelog

* refactor: update docstrings

* refactor: document and test-cover more changes

* refactor: revert fill without name

* docs: update README

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* fix: apostrophes in tags (#765)

* refactor: fix merge error - duplicate code

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Emil Stenström <emil@emilstenstrom.se>
This commit is contained in:
Juro Oravec 2024-11-25 09:41:57 +01:00 committed by GitHub
parent 9f891453d5
commit 5fd45ab424
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
97 changed files with 8727 additions and 3011 deletions

338
tests/test_loader.py Normal file
View file

@ -0,0 +1,338 @@
import os
import re
from pathlib import Path
from unittest.mock import MagicMock, patch
from django.conf import settings
from django.test import override_settings
from django_components.util.loader import _filepath_to_python_module, get_component_dirs, get_component_files
from .django_test_setup import setup_test_config
from .testutils import BaseTestCase
setup_test_config({"autodiscover": False})
class ComponentDirsTest(BaseTestCase):
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
)
def test_get_dirs__base_dir(self):
dirs = sorted(get_component_dirs())
apps_dirs = [dirs[0], dirs[2]]
own_dirs = [dirs[1], *dirs[3:]]
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 2)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/django_components\/components$"))
self.assertRegex(str(apps_dirs[1]), re.compile(r"\/tests\/test_app\/components$"))
@override_settings(
BASE_DIR=Path(__file__).parent.resolve() / "test_structures" / "test_structure_1", # noqa
)
def test_get_dirs__base_dir__complex(self):
dirs = sorted(get_component_dirs())
apps_dirs = dirs[:2]
own_dirs = dirs[2:]
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 2)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/django_components\/components$"))
self.assertRegex(str(apps_dirs[1]), re.compile(r"\/tests\/test_app\/components$"))
expected = [
Path(__file__).parent.resolve() / "test_structures" / "test_structure_1" / "components",
]
self.assertEqual(own_dirs, expected)
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
STATICFILES_DIRS=[
Path(__file__).parent.resolve() / "components",
("with_alias", Path(__file__).parent.resolve() / "components"),
("too_many", Path(__file__).parent.resolve() / "components", Path(__file__).parent.resolve()),
("with_not_str_alias", 3),
], # noqa
)
@patch("django_components.util.loader.logger.warning")
def test_get_dirs__components_dirs(self, mock_warning: MagicMock):
mock_warning.reset_mock()
dirs = sorted(get_component_dirs())
apps_dirs = [dirs[0], dirs[2]]
own_dirs = [dirs[1], *dirs[3:]]
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 2)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/django_components\/components$"))
self.assertRegex(str(apps_dirs[1]), re.compile(r"\/tests\/test_app\/components$"))
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
warn_inputs = [warn.args[0] for warn in mock_warning.call_args_list]
assert "Got <class 'int'> : 3" in warn_inputs[0]
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"dirs": [],
},
)
def test_get_dirs__components_dirs__empty(self):
dirs = sorted(get_component_dirs())
apps_dirs = dirs
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 2)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/django_components\/components$"))
self.assertRegex(str(apps_dirs[1]), re.compile(r"\/tests\/test_app\/components$"))
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"dirs": ["components"],
},
)
def test_get_dirs__componenents_dirs__raises_on_relative_path_1(self):
with self.assertRaisesMessage(ValueError, "COMPONENTS.dirs must contain absolute paths"):
get_component_dirs()
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"dirs": [("with_alias", "components")],
},
)
def test_get_dirs__component_dirs__raises_on_relative_path_2(self):
with self.assertRaisesMessage(ValueError, "COMPONENTS.dirs must contain absolute paths"):
get_component_dirs()
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"app_dirs": ["custom_comps_dir"],
},
)
def test_get_dirs__app_dirs(self):
dirs = sorted(get_component_dirs())
apps_dirs = dirs[1:]
own_dirs = dirs[:1]
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 1)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/tests\/test_app\/custom_comps_dir$"))
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"app_dirs": [],
},
)
def test_get_dirs__app_dirs_empty(self):
dirs = sorted(get_component_dirs())
own_dirs = dirs
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
COMPONENTS={
"app_dirs": ["this_dir_does_not_exist"],
},
)
def test_get_dirs__app_dirs_not_found(self):
dirs = sorted(get_component_dirs())
own_dirs = dirs
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
INSTALLED_APPS=("django_components", "tests.test_app_nested.app"),
)
def test_get_dirs__nested_apps(self):
dirs = sorted(get_component_dirs())
apps_dirs = [dirs[0], *dirs[2:]]
own_dirs = [dirs[1]]
# Apps with a `components` dir
self.assertEqual(len(apps_dirs), 2)
self.assertRegex(str(apps_dirs[0]), re.compile(r"\/django_components\/components$"))
self.assertRegex(str(apps_dirs[1]), re.compile(r"\/tests\/test_app_nested\/app\/components$"))
self.assertEqual(
own_dirs,
[
# Top-level /components dir
Path(__file__).parent.resolve()
/ "components",
],
)
class ComponentFilesTest(BaseTestCase):
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
)
def test_get_files__py(self):
files = sorted(get_component_files(".py"))
dot_paths = [f.dot_path for f in files]
file_paths = [str(f.filepath) for f in files]
self.assertEqual(
dot_paths,
[
"components",
"components.multi_file.multi_file",
"components.relative_file.relative_file",
"components.relative_file_pathobj.relative_file_pathobj",
"components.single_file",
"components.staticfiles.staticfiles",
"components.urls",
"django_components.components",
"django_components.components.dynamic",
"tests.test_app.components.app_lvl_comp.app_lvl_comp",
],
)
self.assertEqual(
[
file_paths[0].endswith("tests/components/__init__.py"),
file_paths[1].endswith("tests/components/multi_file/multi_file.py"),
file_paths[2].endswith("tests/components/relative_file/relative_file.py"),
file_paths[3].endswith("tests/components/relative_file_pathobj/relative_file_pathobj.py"),
file_paths[4].endswith("tests/components/single_file.py"),
file_paths[5].endswith("tests/components/staticfiles/staticfiles.py"),
file_paths[6].endswith("tests/components/urls.py"),
file_paths[7].endswith("django_components/components/__init__.py"),
file_paths[8].endswith("django_components/components/dynamic.py"),
file_paths[9].endswith("tests/test_app/components/app_lvl_comp/app_lvl_comp.py"),
],
[True for _ in range(len(file_paths))],
)
@override_settings(
BASE_DIR=Path(__file__).parent.resolve(),
)
def test_get_files__js(self):
files = sorted(get_component_files(".js"))
dot_paths = [f.dot_path for f in files]
file_paths = [str(f.filepath) for f in files]
print(file_paths)
self.assertEqual(
dot_paths,
[
"components.relative_file.relative_file",
"components.relative_file_pathobj.relative_file_pathobj",
"components.staticfiles.staticfiles",
"tests.test_app.components.app_lvl_comp.app_lvl_comp",
],
)
self.assertEqual(
[
file_paths[0].endswith("tests/components/relative_file/relative_file.js"),
file_paths[1].endswith("tests/components/relative_file_pathobj/relative_file_pathobj.js"),
file_paths[2].endswith("tests/components/staticfiles/staticfiles.js"),
file_paths[3].endswith("tests/test_app/components/app_lvl_comp/app_lvl_comp.js"),
],
[True for _ in range(len(file_paths))],
)
class TestFilepathToPythonModule(BaseTestCase):
def test_prepares_path(self):
base_path = str(settings.BASE_DIR)
the_path = os.path.join(base_path, "tests.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests",
)
the_path = os.path.join(base_path, "tests/components/relative_file/relative_file.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests.components.relative_file.relative_file",
)
def test_handles_nonlinux_paths(self):
base_path = str(settings.BASE_DIR).replace("/", "//")
with patch("os.path.sep", new="//"):
the_path = os.path.join(base_path, "tests.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests",
)
the_path = os.path.join(base_path, "tests//components//relative_file//relative_file.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests.components.relative_file.relative_file",
)
base_path = str(settings.BASE_DIR).replace("//", "\\")
with patch("os.path.sep", new="\\"):
the_path = os.path.join(base_path, "tests.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests",
)
the_path = os.path.join(base_path, "tests\\components\\relative_file\\relative_file.py")
self.assertEqual(
_filepath_to_python_module(the_path, base_path, None),
"tests.components.relative_file.relative_file",
)