Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32507 closed Cleanup/optimization (fixed)

assertInHTML('<a>', '<a><b/></a>') fails when tag implicitly closed

Reported by: Jacob Walls Owned by: Jacob Walls
Component: Documentation Version: dev
Severity: Normal Keywords:
Cc: Antoine Humbert Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

If the needle ('<a>') is an open tag without children, and the haystack is a closed tag with children ('<a><b/></a>'), no match is found.
Spotted by Antoine Humbert in the patch for #31867.

Something like this appears to work:

diff --git a/django/test/html.py b/django/test/html.py
index 486a0d358d..4443540a70 100644
--- a/django/test/html.py
+++ b/django/test/html.py
@@ -82,6 +82,9 @@ class Element:
             return 1
         i = 0
         elem_child_idx = 0
+        # Begin search against a childless copy, e.g. '<a>' in '<a><b/></a>'.
+        if Element(self.name, self.attributes) == element:
+            i = 1
         for child in self.children:
             # child is text content and element is also text content, then
             # make a simple "text" in "text"

But it breaks the fourth assertion here from the original commit 844a24bbb97af663ebf8dbeab4499acafe105943:

    def test_contains_html(self):
        response = HttpResponse('''<body>
        This is a form: <form method="get">
            <input type="text" name="Hello" />
        </form></body>''')

        self.assertNotContains(response, "<input name='Hello' type='text'>")
        self.assertContains(response, '<form method="get">')

        self.assertContains(response, "<input name='Hello' type='text'>", html=True)
        self.assertNotContains(response, '<form method="get">', html=True)

I'm having trouble seeing why the fourth assertion is correct. I see from the docs for assertHTMLEqual that "All open tags are closed implicitly, e.g. when a surrounding tag is closed or the HTML document ends.", which is fine to insist on for equality, but for contains, I would expect the test case for this ticket to pass.

Or, if we decide not to support it, we should explain in the docs for assertInHTML that an implicit closing tag is being added.

Change History (6)

comment:1 by Jacob Walls, 3 years ago

This probably verges on new feature territory, because my suggested approach will be unexpected for someone who does pass a complete tag and expects '<a></a>' in '<a><b/></a>' to fail.

So, I suppose my proposal is to either:

  • document the current implicit closing on assertInHTML, or
  • add an allow_additional_children=False kwarg that can be set to True (or strict=True that can be set to False, etc.) to satisfy this use case.

comment:2 by Chris Jerdonek, 3 years ago

The documentation for assertContains(), which is similar, refers the reader to assertHTMLEqual() for more details. So maybe this can be addressed simply by adding that same wording to assertInHTML().

comment:3 by Mariusz Felisiak, 3 years ago

Component: Testing frameworkDocumentation
Easy pickings: set
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

I agree with Chris. Adding "See assertHTMLEqual() for more details." should be enough.

comment:4 by Jacob Walls, 3 years ago

Has patch: set

comment:5 by GitHub <noreply@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In 286fb73:

Fixed #32507 -- Added link to assertHTMLEqual() in assertInHTML() docs.

comment:6 by Mariusz Felisiak <felisiak.mariusz@…>, 3 years ago

In 3fd83c48:

[3.2.x] Fixed #32507 -- Added link to assertHTMLEqual() in assertInHTML() docs.

Backport of 286fb73b6962d197ed0cf041755fb724cfe08600 from master

Note: See TracTickets for help on using tickets.
Back to Top