Skip to content

Commit 83e8e61

Browse files
Refactor components, add tests for edge cases, and boost coverage % (#173)
1 parent 55921f8 commit 83e8e61

File tree

6 files changed

+114
-60
lines changed

6 files changed

+114
-60
lines changed

src/django_bird/components.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,8 @@ def path(self):
7474
def source(self):
7575
return self.template.template.source
7676

77-
@property
78-
def used_in(self):
79-
return components.get_template_usage(self.name)
80-
8177
@classmethod
82-
def from_abs_path(cls, path: Path, root: Path) -> Component | None:
78+
def from_abs_path(cls, path: Path, root: Path) -> Component:
8379
name = str(path.relative_to(root).with_suffix("")).replace("/", ".")
8480
return cls.from_name(name)
8581

@@ -174,11 +170,6 @@ def fill_slots(self, context: Context):
174170
**slot_nodes,
175171
}
176172

177-
if context.get("slots"):
178-
for name, content in context["slots"].items():
179-
if name not in slots or not slots.get(name):
180-
slots[name] = TextNode(str(content))
181-
182173
if not slots[DEFAULT_SLOT] and "slot" in context:
183174
slots[DEFAULT_SLOT] = TextNode(context["slot"])
184175

@@ -203,8 +194,6 @@ def discover_components(self) -> None:
203194
continue
204195

205196
component = Component.from_abs_path(component_abs_path, root_abs_path)
206-
if component is None:
207-
continue
208197

209198
if component.name not in self._components:
210199
self._components[component.name] = component
@@ -249,9 +238,5 @@ def get_component_usage(
249238
for component_name in self._template_usage.get(path, set()):
250239
yield Component.from_name(component_name)
251240

252-
def get_template_usage(self, component: str | Component) -> frozenset[Path]:
253-
name = component.name if isinstance(component, Component) else component
254-
return frozenset(self._component_usage.get(name, set()))
255-
256241

257242
components = ComponentRegistry()

src/django_bird/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def configure_templates(self) -> None:
7272
self.configure_builtins(options)
7373

7474
# Force re-evaluation of settings.TEMPLATES because EngineHandler caches it.
75-
with suppress(AttributeError):
75+
with suppress(AttributeError): # pragma: no cover
7676
del django.template.engines.templates
7777
django.template.engines._engines = {} # type: ignore[attr-defined]
7878

tests/templatetags/test_prop.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import pytest
4+
from django import template
45
from django.template.base import Parser
56
from django.template.base import Token
67
from django.template.base import TokenType
@@ -25,3 +26,10 @@ def test_do_prop(contents, expected):
2526
assert node.name == expected.name
2627
assert node.default == expected.default
2728
assert node.attrs == expected.attrs
29+
30+
31+
def test_do_prop_no_args():
32+
start_token = Token(TokenType.BLOCK, TAG)
33+
34+
with pytest.raises(template.TemplateSyntaxError):
35+
do_prop(Parser([]), start_token)

tests/templatetags/test_var.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
11
from __future__ import annotations
22

33
import pytest
4+
from django import template
45
from django.template import Context
56
from django.template import Template
7+
from django.template.base import Parser
8+
from django.template.base import Token
9+
from django.template.base import TokenType
610
from django.template.exceptions import TemplateSyntaxError
711

12+
from django_bird.templatetags.tags.var import END_TAG
13+
from django_bird.templatetags.tags.var import TAG
14+
from django_bird.templatetags.tags.var import do_end_var
15+
from django_bird.templatetags.tags.var import do_var
816
from tests.utils import TestComponent
917

1018

19+
def test_do_var_no_args():
20+
start_token = Token(TokenType.BLOCK, TAG)
21+
22+
with pytest.raises(template.TemplateSyntaxError):
23+
do_var(Parser([]), start_token)
24+
25+
26+
def test_do_end_var_no_args():
27+
start_token = Token(TokenType.BLOCK, END_TAG)
28+
29+
with pytest.raises(template.TemplateSyntaxError):
30+
do_end_var(Parser([]), start_token)
31+
32+
1133
def test_basic_assignment():
1234
template = Template("""
1335
{% load django_bird %}

tests/test_components.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@
2727

2828

2929
class TestComponentClass:
30+
def test_get_asset(self, templates_dir):
31+
button = TestComponent(
32+
name="button", content="<button>Click me</button>"
33+
).create(templates_dir)
34+
button_css = TestAsset(
35+
component=button,
36+
content=".button { color: blue; }",
37+
asset_type=AssetType.CSS,
38+
).create()
39+
40+
component = Component.from_name(button.name)
41+
42+
assert component.get_asset(button_css.file.name)
43+
44+
def test_get_asset_no_asset(self, templates_dir):
45+
button = TestComponent(
46+
name="button", content="<button>Click me</button>"
47+
).create(templates_dir)
48+
49+
component = Component.from_name(button.name)
50+
51+
assert component.get_asset("button.css") is None
52+
assert component.get_asset("button.js") is None
53+
3054
def test_from_abs_path_basic(self, templates_dir):
3155
test_component = TestComponent(
3256
name="button", content="<button>Click me</button>"

tests/test_conf.py

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,76 +9,91 @@
99

1010
from django_bird.conf import DJANGO_BIRD_BUILTINS
1111
from django_bird.conf import DJANGO_BIRD_FINDER
12-
from django_bird.conf import AppSettings
1312
from django_bird.conf import AutoConfigurator
1413
from django_bird.conf import app_settings
1514

1615

16+
@pytest.fixture(autouse=True)
17+
def reset_settings():
18+
template_options = settings.TEMPLATES[0]["OPTIONS"]
19+
20+
assert DJANGO_BIRD_BUILTINS in template_options["builtins"]
21+
assert DJANGO_BIRD_FINDER in settings.STATICFILES_FINDERS
22+
23+
with override_settings(
24+
STATICFILES_FINDERS=[
25+
finder
26+
for finder in settings.STATICFILES_FINDERS
27+
if finder != DJANGO_BIRD_FINDER
28+
],
29+
TEMPLATES=[
30+
settings.TEMPLATES[0]
31+
| {
32+
**settings.TEMPLATES[0],
33+
"OPTIONS": {
34+
"builtins": [
35+
builtin
36+
for builtin in template_options["builtins"]
37+
if builtin != DJANGO_BIRD_BUILTINS
38+
],
39+
},
40+
}
41+
],
42+
):
43+
options = settings.TEMPLATES[0]["OPTIONS"]
44+
45+
assert DJANGO_BIRD_BUILTINS not in options["builtins"]
46+
assert DJANGO_BIRD_FINDER not in settings.STATICFILES_FINDERS
47+
48+
yield
49+
50+
1751
@pytest.mark.default_app_settings
1852
def test_app_settings():
1953
assert app_settings.COMPONENT_DIRS == []
2054
assert app_settings.ENABLE_AUTO_CONFIG is True
2155

2256

57+
def test_autoconfigure_disabled():
58+
template_options = settings.TEMPLATES[0]["OPTIONS"]
59+
60+
with override_settings(
61+
DJANGO_BIRD={
62+
"ENABLE_AUTO_CONFIG": False,
63+
}
64+
):
65+
app_settings.autoconfigure()
66+
67+
assert DJANGO_BIRD_BUILTINS not in template_options["builtins"]
68+
assert DJANGO_BIRD_FINDER not in settings.STATICFILES_FINDERS
69+
70+
2371
class TestAutoConfigurator:
2472
@pytest.fixture
2573
def configurator(self):
2674
return AutoConfigurator(app_settings)
2775

28-
@pytest.fixture(autouse=True)
29-
def reset_settings(self):
76+
def test_autoconfigure(self, configurator):
3077
template_options = settings.TEMPLATES[0]["OPTIONS"]
3178

79+
configurator.autoconfigure()
80+
3281
assert DJANGO_BIRD_BUILTINS in template_options["builtins"]
3382
assert DJANGO_BIRD_FINDER in settings.STATICFILES_FINDERS
3483

84+
def test_non_django_template_engine(self, configurator):
85+
template_options = settings.TEMPLATES[0]["OPTIONS"]
86+
3587
with override_settings(
36-
STATICFILES_FINDERS=[
37-
finder
38-
for finder in settings.STATICFILES_FINDERS
39-
if finder != DJANGO_BIRD_FINDER
40-
],
4188
TEMPLATES=[
42-
settings.TEMPLATES[0]
43-
| {
44-
**settings.TEMPLATES[0],
45-
"OPTIONS": {
46-
"builtins": [
47-
builtin
48-
for builtin in template_options["builtins"]
49-
if builtin != DJANGO_BIRD_BUILTINS
50-
],
51-
},
89+
{
90+
"BACKEND": "django.template.backends.jinja2.Jinja2",
5291
}
5392
],
5493
):
55-
options = settings.TEMPLATES[0]["OPTIONS"]
56-
57-
assert DJANGO_BIRD_BUILTINS not in options["builtins"]
58-
assert DJANGO_BIRD_FINDER not in settings.STATICFILES_FINDERS
59-
60-
yield
61-
62-
def test_autoconfigure(self, configurator):
63-
template_options = settings.TEMPLATES[0]["OPTIONS"]
64-
65-
configurator.autoconfigure()
66-
67-
assert DJANGO_BIRD_BUILTINS in template_options["builtins"]
68-
assert DJANGO_BIRD_FINDER in settings.STATICFILES_FINDERS
69-
70-
@override_settings(
71-
DJANGO_BIRD={
72-
"ENABLE_AUTO_CONFIG": False,
73-
}
74-
)
75-
def test_autoconfigure_disabled(self):
76-
app_settings = AppSettings()
77-
template_options = settings.TEMPLATES[0]["OPTIONS"]
94+
configurator.configure_templates()
7895

79-
assert app_settings.ENABLE_AUTO_CONFIG is False
8096
assert DJANGO_BIRD_BUILTINS not in template_options["builtins"]
81-
assert DJANGO_BIRD_FINDER not in settings.STATICFILES_FINDERS
8297

8398
def test_configure_builtins(self, configurator):
8499
template_options = settings.TEMPLATES[0]["OPTIONS"]

0 commit comments

Comments
 (0)