From e26a7a8ef41f0d69951affb21655cdc2cf94a209 Mon Sep 17 00:00:00 2001
From: Jacob Walls
Date: Sun, 20 Sep 2020 10:14:54 -0400
Subject: [PATCH] Fixed #27906 -- Fixed test tools counting of HTML matches for
subsets of elements.
Previously examples such as '' would not match in ''.
---
django/test/html.py | 18 ++++++++++++++++++
tests/test_utils/tests.py | 21 ++++++++++++++++++++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/django/test/html.py b/django/test/html.py
index 36b44b0466..3b04217822 100644
--- a/django/test/html.py
+++ b/django/test/html.py
@@ -86,6 +86,7 @@ class Element:
if self.children == element.children:
return 1
i = 0
+ elem_child_idx = 0
for child in self.children:
# child is text content and element is also text content, then
# make a simple "text" in "text"
@@ -96,9 +97,26 @@ class Element:
elif element in child:
return 1
else:
+ # Look for element wholly within this child.
i += child._count(element, count=count)
if not count and i:
return i
+ # Also look for a sequence of element's children among self's
+ # children. self.children == element.children is tested above,
+ # but will fail if self has additional children. Ex: ''
+ # is contained in ''.
+ if isinstance(element, RootElement) and element.children:
+ elem_child = element.children[elem_child_idx]
+ # Start or continue match, advance index.
+ if elem_child == child:
+ elem_child_idx += 1
+ # Match found, reset index.
+ if elem_child_idx == len(element.children):
+ i += 1
+ elem_child_idx = 0
+ # No match, reset index.
+ else:
+ elem_child_idx = 0
return i
def __contains__(self, element):
diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py
index 87e2f56979..51e3c0548a 100644
--- a/tests/test_utils/tests.py
+++ b/tests/test_utils/tests.py
@@ -768,11 +768,30 @@ class HTMLEqualTests(SimpleTestCase):
dom2 = parse_html('foo
bar
')
self.assertEqual(dom2.count(dom1), 0)
- # html with a root element contains the same html with no root element
+ # HTML with a root element contains the same HTML with no root element.
dom1 = parse_html('foo
bar
')
dom2 = parse_html('')
self.assertEqual(dom2.count(dom1), 1)
+ # Target of search is a sequence of child elements and appears more
+ # than once.
+ dom2 = parse_html('')
+ self.assertEqual(dom2.count(dom1), 2)
+
+ # Searched HTML has additional children.
+ dom1 = parse_html('')
+ dom2 = parse_html('')
+ self.assertEqual(dom2.count(dom1), 1)
+
+ # No match found in children.
+ dom1 = parse_html('')
+ self.assertEqual(dom2.count(dom1), 0)
+
+ # Target of search found among children and grandchildren.
+ dom1 = parse_html('')
+ dom2 = parse_html('')
+ self.assertEqual(dom2.count(dom1), 2)
+
def test_parsing_errors(self):
with self.assertRaises(AssertionError):
self.assertHTMLEqual('', '')