diff --git a/netbox/templates/utilities/render_field.html b/netbox/templates/utilities/render_field.html
index e69296873..b383ae4d3 100644
--- a/netbox/templates/utilities/render_field.html
+++ b/netbox/templates/utilities/render_field.html
@@ -16,14 +16,6 @@
Set null
{% endif %}
- {% if field.errors %}
-
- {% for error in field.errors %}
-
{{ error }}
- {% endfor %}
-
- {% endif %}
-
{% elif field|widget_type == 'textarea' and not field.label %}
{{ field }}
@@ -35,14 +27,6 @@
{% if field.help_text %}
{{ field.help_text|safe }}
{% endif %}
- {% if field.errors %}
-
- {% for error in field.errors %}
-
{{ error }}
- {% endfor %}
-
- {% endif %}
-
{% else %}
@@ -55,13 +39,15 @@
{% if field.help_text %}
{{ field.help_text|safe }}
{% endif %}
- {% if field.errors %}
-
- {% for error in field.errors %}
-
{{ error }}
- {% endfor %}
-
- {% endif %}
-
{% endif %}
+ {% if field.errors %}
+
+ {% for error in field.errors %}
+ {# Embed an HTML comment indicating the error for extraction by tests #}
+
+
{{ error }}
+ {% endfor %}
+
+ {% endif %}
+
diff --git a/netbox/utilities/testing/utils.py b/netbox/utilities/testing/utils.py
index d763012f0..9c30002b8 100644
--- a/netbox/utilities/testing/utils.py
+++ b/netbox/utilities/testing/utils.py
@@ -1,4 +1,5 @@
import logging
+import re
from contextlib import contextmanager
from django.contrib.auth.models import Permission, User
@@ -43,6 +44,14 @@ def create_test_user(username='testuser', permissions=None):
return user
+def extract_form_failures(content):
+ """
+ Given raw HTML content from an HTTP response, return a list of form errors.
+ """
+ FORM_ERROR_REGEX = r''
+ return re.findall(FORM_ERROR_REGEX, str(content))
+
+
@contextmanager
def disable_warnings(logger_name):
"""
diff --git a/netbox/utilities/testing/views.py b/netbox/utilities/testing/views.py
index 78bd50935..afbcbc057 100644
--- a/netbox/utilities/testing/views.py
+++ b/netbox/utilities/testing/views.py
@@ -13,7 +13,7 @@ from taggit.managers import TaggableManager
from extras.models import Tag
from users.models import ObjectPermission
from utilities.permissions import resolve_permission_ct
-from .utils import disable_warnings, post_data
+from .utils import disable_warnings, extract_form_failures, post_data
__all__ = (
@@ -113,10 +113,18 @@ class TestCase(_TestCase):
"""
TestCase method. Provide more detail in the event of an unexpected HTTP response.
"""
- err_message = "Expected HTTP status {}; received {}: {}"
- self.assertEqual(response.status_code, expected_status, err_message.format(
- expected_status, response.status_code, getattr(response, 'data', response.content)
- ))
+ err_message = None
+ # Construct an error message only if we know the test is going to fail
+ if response.status_code != expected_status:
+ if hasattr(response, 'data'):
+ # REST API response; pass the response data through directly
+ err = response.data
+ else:
+ # Attempt to extract form validation errors from the response HTML
+ form_errors = extract_form_failures(response.content)
+ err = form_errors or response.content or 'No data'
+ err_message = f"Expected HTTP status {expected_status}; received {response.status_code}: {err}"
+ self.assertEqual(response.status_code, expected_status, err_message)
def assertInstanceEqual(self, instance, data, api=False):
"""