Skip to content

Commit f696987

Browse files
committed
test: add tests for add_heading_anchors template filter
10 test cases covering: h2/h3/h4 processing, h1/h5 exclusion, duplicate-slug deduplication, existing-id passthrough, nested HTML stripping, non-heading passthrough, empty string, empty text, and anchor placement inside the heading element.
1 parent 47b1dca commit f696987

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""Tests for apps/pages/templatetags/page_tags.py."""
2+
3+
from django.test import SimpleTestCase
4+
5+
from apps.pages.templatetags.page_tags import add_heading_anchors
6+
7+
8+
class AddHeadingAnchorsFilterTests(SimpleTestCase):
9+
"""Tests for the ``add_heading_anchors`` template filter."""
10+
11+
def test_h2_gets_id_and_anchor_link(self):
12+
"""An h2 heading receives an id attribute and a pilcrow anchor link."""
13+
html = "<h2>2023</h2>"
14+
result = add_heading_anchors(html)
15+
self.assertIn('id="2023"', result)
16+
self.assertIn('href="#2023"', result)
17+
self.assertIn("¶", result)
18+
19+
def test_h3_and_h4_also_processed(self):
20+
"""h3 and h4 headings are also processed."""
21+
for tag in ("h3", "h4"):
22+
html = f"<{tag}>Section Title</{tag}>"
23+
result = add_heading_anchors(html)
24+
self.assertIn('id="section-title"', result)
25+
self.assertIn('href="#section-title"', result)
26+
27+
def test_h1_and_h5_are_not_changed(self):
28+
"""h1 and h5 headings are left untouched."""
29+
for tag in ("h1", "h5"):
30+
html = f"<{tag}>Title</{tag}>"
31+
result = add_heading_anchors(html)
32+
self.assertNotIn("id=", result)
33+
self.assertNotIn("href=", result)
34+
35+
def test_duplicate_headings_get_unique_ids(self):
36+
"""Duplicate heading text produces unique, numbered ids."""
37+
html = "<h2>Board Resolution</h2><h2>Board Resolution</h2>"
38+
result = add_heading_anchors(html)
39+
self.assertIn('id="board-resolution"', result)
40+
self.assertIn('id="board-resolution-2"', result)
41+
42+
def test_heading_with_existing_id_is_unchanged(self):
43+
"""A heading that already has an id attribute is left as-is."""
44+
html = '<h2 id="custom-id">My Section</h2>'
45+
result = add_heading_anchors(html)
46+
self.assertIn('id="custom-id"', result)
47+
# No extra anchor link should be injected.
48+
self.assertNotIn("headerlink", result)
49+
50+
def test_heading_with_nested_html_tags(self):
51+
"""Plain text is extracted from headings that contain nested tags."""
52+
html = "<h2><em>Nested</em> Heading</h2>"
53+
result = add_heading_anchors(html)
54+
self.assertIn('id="nested-heading"', result)
55+
56+
def test_non_heading_html_is_unchanged(self):
57+
"""Non-heading elements are passed through unmodified."""
58+
html = "<p>Some paragraph</p><ul><li>Item</li></ul>"
59+
result = add_heading_anchors(html)
60+
self.assertEqual(str(result), html)
61+
62+
def test_empty_string_returns_empty_string(self):
63+
"""Passing an empty string returns an empty string."""
64+
self.assertEqual(str(add_heading_anchors("")), "")
65+
66+
def test_heading_with_empty_text_is_unchanged(self):
67+
"""A heading whose text slugifies to an empty string is left alone."""
68+
html = "<h2> </h2>"
69+
result = add_heading_anchors(html)
70+
self.assertNotIn("id=", result)
71+
72+
def test_anchor_link_is_inside_heading(self):
73+
"""The pilcrow anchor link appears inside the heading element."""
74+
html = "<h2>Resolutions 2022</h2>"
75+
result = str(add_heading_anchors(html))
76+
# The closing </h2> must come after the anchor link.
77+
self.assertIn("¶</a></h2>", result)

0 commit comments

Comments
 (0)