From 0b81596b8d0d4cbb1a644bdac5b2cc3606258a7e Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Thu, 23 Nov 2023 09:09:14 -0500
Subject: [PATCH] Add ability to include custom err messages in assertContent

---
 .../test_cases/integration_test_case.py       |  32 ++++-
 .../test_cases/integration_test_case.rst      |   1 +
 tests/test_cases/test_integration_case.py     | 123 ++++++++++++++++++
 3 files changed, 151 insertions(+), 5 deletions(-)

diff --git a/django_expanded_test_cases/test_cases/integration_test_case.py b/django_expanded_test_cases/test_cases/integration_test_case.py
index 815518a..ed9ea9b 100644
--- a/django_expanded_test_cases/test_cases/integration_test_case.py
+++ b/django_expanded_test_cases/test_cases/integration_test_case.py
@@ -270,16 +270,12 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
             )
 
         if expected_not_content is not None:
-            print('Asserting content is NOT present:')
-            print('{0}'.format(expected_not_content))
             self.assertNotPageContent(
                 response,
                 expected_not_content,
                 debug_output=True,
                 # debug_output=False,
             )
-        else:
-            print('No content to verify is NOT present.')
 
         # Optional hook for running custom post-builtin-test logic.
         self._assertResponse__post_builtin_tests(
@@ -747,6 +743,14 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
                 else:
                     updated_checked_content_str_addon = ''
 
+                # Handle if expected is a list or tuple.
+                additional_error_info = ''
+                if (isinstance(expected, list) or isinstance(expected, tuple)) and len(expected) == 2:
+                    # Nested array or tuple.
+                    # Assuming first value is the value to check for, and second is error message if not found.
+                    additional_error_info = expected[1]
+                    expected = expected[0]
+
                 stripped_expected = self.get_minimized_response_content(expected, strip_newlines=True)
                 if ignore_ordering:
                     # Ignoring ordering. Check as-is.
@@ -780,6 +784,7 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
                                 content_ends_before,
                                 main_err_msg,
                                 updated_checked_content_str_addon,
+                                additional_error_info=additional_error_info,
                             )
                 else:
                     # Verifying ordering.
@@ -816,6 +821,7 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
                                     content_ends_before,
                                     main_err_msg,
                                     updated_checked_content_str_addon,
+                                    additional_error_info=additional_error_info,
                                 )
 
                         # If we made it this far, then item was found in full content, but came after a previous
@@ -863,6 +869,7 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
                         content_starts_after,
                         content_ends_before,
                         main_err_msg,
+                        '',
                     )
 
         # Return page content in case user wants to run additional logic on it.
@@ -873,6 +880,7 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
         actual_content, minimized_expected, display_expected,
         strip_actual_start, strip_actual_end,
         err_msg, checked_content_str_addon,
+        additional_error_info='',
     ):
         """Internal sub-assertion for assertPageContent() function."""
         strip_err_msg = 'Expected content value was found, but occurred in "{0}" section. Expected was:\n{1}'
@@ -900,6 +908,8 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
             # Content value was physically not present at all. Raise "main" message.
             if checked_content_str_addon:
                 err_msg += checked_content_str_addon
+            if additional_error_info:
+                err_msg += '\n{0}'.format(additional_error_info)
             self.fail(err_msg.format(display_expected))
 
     def assertNotPageContent(
@@ -932,14 +942,26 @@ class IntegrationTestCase(BaseTestCase, ResponseTestCaseMixin):
         if isinstance(expected_not_content, list) or isinstance(expected_not_content, tuple):
             # Is an array of items. Verify none of them exist on page.
             for content_item in expected_not_content:
+
+                # Handle if expected is a list or tuple.
+                additional_error_info = ''
+                if (isinstance(content_item, list) or isinstance(content_item, tuple)) and len(content_item) == 2:
+                    # Nested array or tuple.
+                    # Assuming first value is the value to check for, and second is error message if not found.
+                    additional_error_info = content_item[1]
+                    content_item = content_item[0]
+
                 # Not an array of items. Assume is a single str value.
                 stripped_expected = self.get_minimized_response_content(content_item, strip_newlines=True)
                 if stripped_expected != '' and stripped_expected in trimmed_original_content:
                     # Expected value found in provided content section. Raise Error.
-                    self.fail(
+                    err_msg = (
                         'Found content in response. Expected content to not be present. Content was:\n'
                         '{0}'.format(content_item)
                     )
+                    if additional_error_info:
+                        err_msg += '\n\n{0}'.format(additional_error_info)
+                    self.fail(err_msg)
         else:
             # Not an array of items. Assume is a single str value.
             stripped_expected = self.get_minimized_response_content(expected_not_content, strip_newlines=True)
diff --git a/docs/source/test_cases/integration_test_case.rst b/docs/source/test_cases/integration_test_case.rst
index a443f50..15b39ce 100644
--- a/docs/source/test_cases/integration_test_case.rst
+++ b/docs/source/test_cases/integration_test_case.rst
@@ -96,6 +96,7 @@ of ``status_code``, which will assume a default of ``200`` if not provided.
                          `Django Messages Framework <https://docs.djangoproject.com/en/dev/ref/contrib/messages/>`_.
 :param expected_content: Expected page content that the response should contain.
                          See also ``ignore_content_ordering`` param.
+:param expected_not_content: Content that should NOT show up in the page response.
 :param auto_login: Bool indicating if user should be auto-logged-in, before
                   trying to render the response. Useful for verifying behavior
                   of views with login/permission requirements.
diff --git a/tests/test_cases/test_integration_case.py b/tests/test_cases/test_integration_case.py
index dba4ef6..420e267 100644
--- a/tests/test_cases/test_integration_case.py
+++ b/tests/test_cases/test_integration_case.py
@@ -2061,6 +2061,89 @@ class IntegrationClassTest__Base(IntegrationTestCase):
                 self.assertPageContent(response, '<h1>Testing</h1>')
             self.assertText(exception_msg_not_found.format('<h1>Testing</h1>'), str(err.exception))
 
+        with self.subTest('Minimal Response - With additional error info provided.'):
+            # First verify as standard not-found in array.
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        '<h1>Testing</h1>',
+                    ],
+                )
+            self.assertText(exception_msg_not_found.format('<h1>Testing</h1>'), str(err.exception))
+
+            # Now actually verify same thing, but with extra error info (as list).
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        ['<h1>Testing</h1>', 'Extra error stuff here!'],
+                    ],
+                )
+            self.assertText(
+                exception_msg_not_found.format('<h1>Testing</h1>\n\nExtra error stuff here!'),
+                str(err.exception),
+            )
+
+            # Now actually verify same thing, but with extra error info (as tuple).
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        ('<h1>Testing</h1>', 'Extra error stuff here!'),
+                    ],
+                )
+            self.assertText(
+                exception_msg_not_found.format('<h1>Testing</h1>\n\nExtra error stuff here!'),
+                str(err.exception),
+            )
+
+        with self.subTest('Minimal Response - With additional error info provided and ignore ordering.'):
+            # First verify as standard not-found in array.
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        '<h1>Testing</h1>',
+                    ],
+                    ignore_ordering=True,
+                )
+            self.assertText(exception_msg_not_found.format('<h1>Testing</h1>'), str(err.exception))
+
+            # Now actually verify same thing, but with extra error info (as list).
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        ['<h1>Testing</h1>', 'Extra error stuff here!'],
+                    ],
+                    ignore_ordering=True,
+                )
+            self.assertText(
+                exception_msg_not_found.format('<h1>Testing</h1>\n\nExtra error stuff here!'),
+                str(err.exception),
+            )
+
+            # Now actually verify same thing, but with extra error info (as tuple).
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertPageContent(
+                    response,
+                    [
+                        ('<h1>Testing</h1>', 'Extra error stuff here!'),
+                    ],
+                    ignore_ordering=True,
+                )
+            self.assertText(
+                exception_msg_not_found.format('<h1>Testing</h1>\n\nExtra error stuff here!'),
+                str(err.exception),
+            )
+
         with self.subTest('Standard Response - Wrong value passed'):
             with self.assertRaises(AssertionError) as err:
                 response = self._get_page_response('django_expanded_test_cases:login')
@@ -3262,6 +3345,46 @@ class IntegrationClassTest__Base(IntegrationTestCase):
                 self.assertNotPageContent(response, '<h1>Test Title</h1>')
             self.assertText(err_msg.format('<h1>Test Title</h1>'), str(err.exception))
 
+        with self.subTest('Minimal Response - With additional error info provided.'):
+            # First verify as standard not-found in array.
+            with self.assertRaises(AssertionError) as err:
+                response = HttpResponse('<h1>Test Title</h1>')
+                self.assertNotPageContent(
+                    response,
+                    [
+                        '<h1>Test Title</h1>',
+                    ],
+                )
+            self.assertText(err_msg.format('<h1>Test Title</h1>'), str(err.exception))
+
+        # Now actually verify same thing, but with extra error info (as list).
+        with self.assertRaises(AssertionError) as err:
+            response = HttpResponse('<h1>Test Title</h1>')
+            self.assertNotPageContent(
+                response,
+                [
+                    ['<h1>Test Title</h1>', 'Extra error stuff here!'],
+                ],
+            )
+        self.assertText(
+            err_msg.format('<h1>Test Title</h1>\n\nExtra error stuff here!'),
+            str(err.exception),
+        )
+
+        # Now actually verify same thing, but with extra error info (as tuple).
+        with self.assertRaises(AssertionError) as err:
+            response = HttpResponse('<h1>Test Title</h1>')
+            self.assertNotPageContent(
+                response,
+                [
+                    ('<h1>Test Title</h1>', 'Extra error stuff here!'),
+                ],
+            )
+        self.assertText(
+            err_msg.format('<h1>Test Title</h1>\n\nExtra error stuff here!'),
+            str(err.exception),
+        )
+
         with self.subTest('Standard Response - Set of items where one or more items is found (none should be found)'):
             response = self._get_page_response('django_expanded_test_cases:index')
 
-- 
GitLab