Skip to content

Commit 76b2939

Browse files
create unique id per component based on name and whitespace normalized source (#123)
1 parent da0ee5e commit 76b2939

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

src/django_bird/components.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,20 @@ def get_asset(self, asset_filename: str) -> Asset | None:
3535
def render(self, context: dict[str, Any]):
3636
return self.template.render(context)
3737

38+
@property
39+
def id(self):
40+
whitespace_normalized_source = "".join(self.source.split())
41+
hashed = hash((self.name, whitespace_normalized_source))
42+
return f"{hashed & 0xFFFFFFF:07x}"
43+
3844
@property
3945
def nodelist(self):
4046
return self.template.template.nodelist
4147

48+
@property
49+
def source(self):
50+
return self.template.template.source
51+
4252
@classmethod
4353
def from_name(cls, name: str):
4454
template_names = get_template_names(name)

tests/test_components.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,63 @@ def test_from_name_custom_component_dir(self, templates_dir, override_app_settin
105105
assert isinstance(comp.template, Template)
106106
assert comp.render({}) == "<button>Click me</button>"
107107

108+
def test_id_is_consistent(self, templates_dir):
109+
button = TestComponent(
110+
name="button", content="<button>Click me</button>"
111+
).create(templates_dir)
112+
113+
comp1 = Component.from_name(button.name)
114+
comp2 = Component.from_name(button.name)
115+
116+
assert comp1.id == comp2.id
117+
118+
def test_id_content_changes(self, templates_dir):
119+
button = TestComponent(
120+
name="button", content="<button>Click me</button>"
121+
).create(templates_dir)
122+
123+
comp1 = Component.from_name(button.name)
124+
125+
button.file.write_text("<button>Don't click me</button>")
126+
comp2 = Component.from_name(button.name)
127+
128+
assert comp1.id != comp2.id
129+
130+
def test_id_whitespace_changes(self, templates_dir):
131+
button = TestComponent(
132+
name="button", content="<button>Click me</button>"
133+
).create(templates_dir)
134+
135+
comp1 = Component.from_name(button.name)
136+
137+
button.file.write_text("<button>\n Click me\n</button>")
138+
comp2 = Component.from_name(button.name)
139+
140+
assert comp1.id == comp2.id
141+
142+
def test_id_name_changes(self, templates_dir):
143+
button1 = TestComponent(
144+
name="button1", content="<button>Click me</button>"
145+
).create(templates_dir)
146+
button2 = TestComponent(
147+
name="button2", content="<button>Click me</button>"
148+
).create(templates_dir)
149+
150+
comp1 = Component.from_name(button1.name)
151+
comp2 = Component.from_name(button2.name)
152+
153+
assert comp1.id != comp2.id
154+
155+
def test_id_formatting(self, templates_dir):
156+
button = TestComponent(
157+
name="button", content="<button>Click me</button>"
158+
).create(templates_dir)
159+
160+
comp = Component.from_name(button.name)
161+
162+
assert len(comp.id) == 7
163+
assert all(c in "0123456789abcdef" for c in comp.id)
164+
108165

109166
class TestComponentRegistryProject:
110167
def test_discover_components(self, templates_dir):

0 commit comments

Comments
 (0)