Просмотр исходного кода

Closes #5016: assertHttpStatus() should report form validation errors

Jeremy Stretch 5 лет назад
Родитель
Сommit
3ebef04a11

+ 10 - 24
netbox/templates/utilities/render_field.html

@@ -16,14 +16,6 @@
                     <input type="checkbox" name="_nullify" value="{{ field.name }}" /> Set null
                 </label>
             {% endif %}
-            {% if field.errors %}
-                <ul>
-                    {% for error in field.errors %}
-                        <li class="text-danger">{{ error }}</li>
-                    {% endfor %}
-                </ul>
-            {% endif %}
-        </div>
     {% elif field|widget_type == 'textarea' and not field.label %}
         <div class="col-md-12">
             {{ field }}
@@ -35,14 +27,6 @@
             {% if field.help_text %}
                 <span class="help-block">{{ field.help_text|safe }}</span>
             {% endif %}
-            {% if field.errors %}
-                <ul>
-                    {% for error in field.errors %}
-                        <li class="text-danger">{{ error }}</li>
-                    {% endfor %}
-                </ul>
-            {% endif %}
-        </div>
     {% else %}
         <label class="col-md-3 control-label{% if field.field.required %} required{% endif %}" for="{{ field.id_for_label }}">{{ field.label }}</label>
         <div class="col-md-9">
@@ -55,13 +39,15 @@
             {% if field.help_text %}
                 <span class="help-block">{{ field.help_text|safe }}</span>
             {% endif %}
-            {% if field.errors %}
-                <ul>
-                    {% for error in field.errors %}
-                        <li class="text-danger">{{ error }}</li>
-                    {% endfor %}
-                </ul>
-            {% endif %}
-        </div>
     {% endif %}
+    {% if field.errors %}
+        <ul>
+            {% for error in field.errors %}
+                {# Embed an HTML comment indicating the error for extraction by tests #}
+                <!-- FORM-ERROR {{ field.name }}: {{ error }} -->
+                <li class="text-danger">{{ error }}</li>
+            {% endfor %}
+        </ul>
+    {% endif %}
+    </div>
 </div>

+ 9 - 0
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'<!-- FORM-ERROR (.*) -->'
+    return re.findall(FORM_ERROR_REGEX, str(content))
+
+
 @contextmanager
 def disable_warnings(logger_name):
     """

+ 13 - 5
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):
         """