diff --git a/instances/templates/allinstances_index_grouped.html b/instances/templates/allinstances_index_grouped.html index 38fd6d2d..ad1ea64a 100644 --- a/instances/templates/allinstances_index_grouped.html +++ b/instances/templates/allinstances_index_grouped.html @@ -29,9 +29,9 @@ {% if compute.status is True %} - {% trans "Connected" %} + {% trans "Connected" %} {% else %} - {% trans "Not Connected" %} + {% trans "Not Connected" %} {% endif %} {% if app_settings.VM_DRBD_STATUS == 'True' %} @@ -76,7 +76,7 @@ {% if app_settings.VM_DRBD_STATUS == 'True' %} - {% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}{% else %}{% endif %}{{ instance.drbd }} + {% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}{% else %}{% endif %}{{ instance.drbd }} {% endif %} {{ instance.info.3 }} diff --git a/instances/templates/allinstances_index_nongrouped.html b/instances/templates/allinstances_index_nongrouped.html index 14474779..34b8f476 100644 --- a/instances/templates/allinstances_index_nongrouped.html +++ b/instances/templates/allinstances_index_nongrouped.html @@ -43,7 +43,7 @@ {% if app_settings.VM_DRBD_STATUS == 'True' %} - {% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}{% else %}{% endif %}{{ instance.drbd }} + {% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}{% else %}{% endif %}{{ instance.drbd }} {% endif %} {{ instance.info.3 }} diff --git a/interfaces/templates/interfaces.html b/interfaces/templates/interfaces.html index f5913b6b..fce57db4 100644 --- a/interfaces/templates/interfaces.html +++ b/interfaces/templates/interfaces.html @@ -54,9 +54,9 @@ {% for iface in ifaces_all %}
-
+
diff --git a/networks/templates/network.html b/networks/templates/network.html index 19135f25..04d0f84d 100644 --- a/networks/templates/network.html +++ b/networks/templates/network.html @@ -110,9 +110,9 @@
{% trans "DHCP" %}:
{% if ipv4_dhcp_range_start and ipv4_dhcp_range_end %} - {% trans "ON" %} + {% trans "ON" %} {% else %} - {% trans "OFF" %} + {% trans "OFF" %} {% endif %}
{% if ipv4_dhcp_range_start and ipv4_dhcp_range_end %} @@ -222,9 +222,9 @@
{% if ipv6_dhcp_range_start and ipv6_dhcp_range_end %} - {% trans "ON" %} + {% trans "ON" %} {% else %} - {% trans "OFF" %} + {% trans "OFF" %} {% endif %}
{% if ipv6_dhcp_range_start and ipv6_dhcp_range_end %} diff --git a/networks/templates/networks.html b/networks/templates/networks.html index 1b3f44b8..64bbf813 100644 --- a/networks/templates/networks.html +++ b/networks/templates/networks.html @@ -50,9 +50,9 @@ {% for pool in networks %}
-
+
diff --git a/storages/templates/storages.html b/storages/templates/storages.html index 0fca5a50..8c3bb373 100644 --- a/storages/templates/storages.html +++ b/storages/templates/storages.html @@ -50,9 +50,9 @@ {% for pool in storages %}
-
+
diff --git a/webvirtcloud/tests/test_status_contrast.py b/webvirtcloud/tests/test_status_contrast.py new file mode 100644 index 00000000..37763f12 --- /dev/null +++ b/webvirtcloud/tests/test_status_contrast.py @@ -0,0 +1,48 @@ +"""Status colours keep their contrast on every theme: a pool, network or +interface card's header, and a status word, is the theme's pale status +background with its dark status text, a pair that does not depend on the +page's background (dark themes keep light-mode emphasis colours).""" + +from unittest.mock import PropertyMock, patch + +import libvirt +from computes.models import Compute +from django.contrib.auth import get_user_model +from django.test import TestCase +from django.urls import reverse +from lxml import html + + +class StatusContrastTests(TestCase): + def setUp(self): + self.conn = libvirt.open("test:///default") + self.addCleanup(self.conn.close) + self.compute = Compute.objects.create(name="contrast", hostname="localhost", login="", password="", type=4) + self.client.force_login(get_user_model().objects.create_superuser("contrast", "c@example.com", "pw")) + + def page(self, name, *args, compute=True): + with patch("vrtManager.connection.connection_manager.get_connection", return_value=self.conn): + response = self.client.get(reverse(name, args=[self.compute.id, *args] if compute else args)) + self.assertEqual(response.status_code, 200) + return html.fromstring(response.content) + + def test_card_headers_are_pale_with_dark_text(self): + for name in ("storages", "networks", "interfaces"): + with self.subTest(page=name): + headers = self.page(name).xpath("//div[contains(@class, 'card-header')]") + self.assertTrue(headers) + for header in headers: + classes = header.get("class").split() + self.assertTrue({"bg-success-subtle", "bg-danger-subtle"} & set(classes), classes) + link = header.xpath(".//a")[0].get("class").split() + self.assertTrue({"text-success-emphasis", "text-danger-emphasis"} & set(link), link) + + def test_status_words_are_pale_badges_with_dark_text(self): + status = self.page("network", "default").xpath("//span[normalize-space()='ON' or normalize-space()='OFF']") + # the test driver has no node memory statistics for the host row + with patch.object(Compute, "ram_usage", new_callable=PropertyMock, return_value=1): + status += self.page("instances:index", compute=False).xpath("//span[normalize-space()='Connected']") + self.assertEqual(len(status), 3) + for span in status: + self.assertIn(span.get("class"), ("badge bg-success-subtle text-success-emphasis", + "badge bg-danger-subtle text-danger-emphasis"))