mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-09 11:46:49 +00:00
fix(templates): status colours keep their contrast on every theme
The pool, network and interface cards had a solid green or red header with light text, and status words (Connected, ON, OFF, the DRBD state) were in the theme's green or red text colour. axe found them below the WCAG AA 4.5:1 contrast on the live theme (4.29:1, 3.52:1), on the default zephyr theme, whose green is light (2.5:1), and on dark themes (darkly 1.18:1). The card headers, and the status words as badges, are now the theme's pale status background with its dark status text (bg-*-subtle with text-*-emphasis). Bootstrap derives the pair from each theme's palette, and it does not depend on the page's background: the dark Bootswatch themes keep light-mode emphasis colours, which on their own would be dark text on a dark page. The card border keeps the status colour.
This commit is contained in:
parent
084f2e8b60
commit
b45f673da7
7 changed files with 62 additions and 14 deletions
48
webvirtcloud/tests/test_status_contrast.py
Normal file
48
webvirtcloud/tests/test_status_contrast.py
Normal file
|
|
@ -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"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue