import pathlib import tempfile import unittest import unittest.mock import generator.theme class ThemeTests(unittest.TestCase): def test_foregrounds_remain_readable_on_dark_surfaces(self): def luminance(color): channels = [value / 255 for value in color] linear = [value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 for value in channels] return sum(value * weight for value, weight in zip(linear, (0.2126, 0.7152, 0.0722))) for surface in ('background', 'panel', 'selection'): background = luminance(generator.theme.rgb(surface)) self.assertLess(background, 0.06) for name in ('ink', 'muted', 'accent', 'connecting', 'retrying', 'connected', 'danger'): contrast = (luminance(generator.theme.rgb(name)) + 0.05) / (background + 0.05) self.assertGreaterEqual(contrast, 4.5, (name, surface)) def test_cpp_colors_match_the_renderer_palette_without_rewriting(self): with tempfile.TemporaryDirectory() as temporary: header = pathlib.Path(temporary) / 'palette.hpp' generator.theme.generate_header(header) stamp = header.stat().st_mtime_ns for name in generator.theme.COLORS: red, green, blue = generator.theme.rgb(name) self.assertIn(f'{name} = vamp_style::color{{{red}, {green}, {blue}, 255}};', header.read_text()) generator.theme.generate_header(header) self.assertEqual(stamp, header.stat().st_mtime_ns) def test_invalid_colors_fail_before_writing(self): with unittest.mock.patch.dict(generator.theme.COLORS, {'background': '#xyz'}): with self.assertRaisesRegex(ValueError, 'background'): generator.theme.rgb('background')