1# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: 2# Copyright 2020-2021 Florian Bruhin (The Compiler) <mail@qutebrowser.org> 3 4# This file is part of qutebrowser. 5# 6# qutebrowser is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# qutebrowser is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>. 18 19import logging 20 21import pytest 22 23from qutebrowser.config import configdata 24from qutebrowser.utils import usertypes, version, utils 25from qutebrowser.browser.webengine import darkmode 26from qutebrowser.misc import objects 27from helpers import testutils 28 29 30@pytest.fixture(autouse=True) 31def patch_backend(monkeypatch): 32 monkeypatch.setattr(objects, 'backend', usertypes.Backend.QtWebEngine) 33 34 35@pytest.fixture 36def gentoo_versions(): 37 return version.WebEngineVersions( 38 webengine=utils.VersionNumber(5, 15, 2), 39 chromium='87.0.4280.144', 40 source='faked', 41 ) 42 43 44@pytest.mark.parametrize('value, webengine_version, expected', [ 45 # Auto 46 ("auto", "5.14", []), 47 ("auto", "5.15.0", []), 48 ("auto", "5.15.1", []), 49 ("auto", "5.15.2", [("preferredColorScheme", "2")]), # QTBUG-89753 50 ("auto", "5.15.3", []), 51 ("auto", "6.0.0", []), 52 53 # Unset 54 (None, "5.14", []), 55 (None, "5.15.0", []), 56 (None, "5.15.1", []), 57 (None, "5.15.2", [("preferredColorScheme", "2")]), # QTBUG-89753 58 (None, "5.15.3", []), 59 (None, "6.0.0", []), 60 61 # Dark 62 ("dark", "5.14", []), 63 ("dark", "5.15.0", []), 64 ("dark", "5.15.1", []), 65 ("dark", "5.15.2", [("preferredColorScheme", "1")]), 66 ("dark", "5.15.3", [("preferredColorScheme", "0")]), 67 ("dark", "6.0.0", [("preferredColorScheme", "0")]), 68 69 # Light 70 ("light", "5.14", []), 71 ("light", "5.15.0", []), 72 ("light", "5.15.1", []), 73 ("light", "5.15.2", [("preferredColorScheme", "2")]), 74 ("light", "5.15.3", [("preferredColorScheme", "1")]), 75 ("light", "6.0.0", [("preferredColorScheme", "1")]), 76]) 77@testutils.qt514 78def test_colorscheme(config_stub, value, webengine_version, expected): 79 versions = version.WebEngineVersions.from_pyqt(webengine_version) 80 if value is not None: 81 config_stub.val.colors.webpage.preferred_color_scheme = value 82 83 darkmode_settings = darkmode.settings(versions=versions, special_flags=[]) 84 assert darkmode_settings['blink-settings'] == expected 85 86 87@testutils.qt514 88def test_colorscheme_gentoo_workaround(config_stub, gentoo_versions): 89 config_stub.val.colors.webpage.preferred_color_scheme = "dark" 90 darkmode_settings = darkmode.settings(versions=gentoo_versions, special_flags=[]) 91 assert darkmode_settings['blink-settings'] == [("preferredColorScheme", "0")] 92 93 94@pytest.mark.parametrize('settings, expected', [ 95 # Disabled 96 ({}, []), 97 98 # Enabled without customization 99 ({'enabled': True}, [('darkModeEnabled', 'true')]), 100 101 # Algorithm 102 ( 103 {'enabled': True, 'algorithm': 'brightness-rgb'}, 104 [ 105 ('darkModeEnabled', 'true'), 106 ('darkModeInversionAlgorithm', '2') 107 ], 108 ), 109]) 110def test_basics(config_stub, settings, expected): 111 for k, v in settings.items(): 112 config_stub.set_obj('colors.webpage.darkmode.' + k, v) 113 114 if expected: 115 expected.append(('darkModeImagePolicy', '2')) 116 117 # Using Qt 5.15.1 because it has the least special cases. 118 versions = version.WebEngineVersions.from_pyqt('5.15.1') 119 darkmode_settings = darkmode.settings(versions=versions, special_flags=[]) 120 assert darkmode_settings['blink-settings'] == expected 121 122 123QT_514_SETTINGS = {'blink-settings': [ 124 ('darkMode', '2'), 125 ('darkModeImagePolicy', '2'), 126 ('darkModeGrayscale', 'true'), 127]} 128 129 130QT_515_0_SETTINGS = {'blink-settings': [ 131 ('darkModeEnabled', 'true'), 132 ('darkModeInversionAlgorithm', '2'), 133 ('darkModeGrayscale', 'true'), 134]} 135 136 137QT_515_1_SETTINGS = {'blink-settings': [ 138 ('darkModeEnabled', 'true'), 139 ('darkModeInversionAlgorithm', '2'), 140 ('darkModeImagePolicy', '2'), 141 ('darkModeGrayscale', 'true'), 142]} 143 144 145QT_515_2_SETTINGS = {'blink-settings': [ 146 ('preferredColorScheme', '2'), # QTBUG-89753 147 ('forceDarkModeEnabled', 'true'), 148 ('forceDarkModeInversionAlgorithm', '2'), 149 ('forceDarkModeImagePolicy', '2'), 150 ('forceDarkModeGrayscale', 'true'), 151]} 152 153 154QT_515_3_SETTINGS = { 155 'blink-settings': [('forceDarkModeEnabled', 'true')], 156 'dark-mode-settings': [ 157 ('InversionAlgorithm', '1'), 158 ('ImagePolicy', '2'), 159 ('IsGrayScale', 'true'), 160 ], 161} 162 163 164@pytest.mark.parametrize('qversion, expected', [ 165 ('5.14.0', QT_514_SETTINGS), 166 ('5.14.1', QT_514_SETTINGS), 167 ('5.14.2', QT_514_SETTINGS), 168 169 ('5.15.0', QT_515_0_SETTINGS), 170 ('5.15.1', QT_515_1_SETTINGS), 171 172 ('5.15.2', QT_515_2_SETTINGS), 173 ('5.15.3', QT_515_3_SETTINGS), 174]) 175def test_qt_version_differences(config_stub, qversion, expected): 176 settings = { 177 'enabled': True, 178 'algorithm': 'brightness-rgb', 179 'grayscale.all': True, 180 } 181 for k, v in settings.items(): 182 config_stub.set_obj('colors.webpage.darkmode.' + k, v) 183 184 versions = version.WebEngineVersions.from_pyqt(qversion) 185 darkmode_settings = darkmode.settings(versions=versions, special_flags=[]) 186 assert darkmode_settings == expected 187 188 189@testutils.qt514 190@pytest.mark.parametrize('setting, value, exp_key, exp_val', [ 191 ('contrast', -0.5, 192 'Contrast', '-0.5'), 193 ('policy.page', 'smart', 194 'PagePolicy', '1'), 195 ('policy.images', 'smart', 196 'ImagePolicy', '2'), 197 ('threshold.text', 100, 198 'TextBrightnessThreshold', '100'), 199 ('threshold.background', 100, 200 'BackgroundBrightnessThreshold', '100'), 201 ('grayscale.all', True, 202 'Grayscale', 'true'), 203 ('grayscale.images', 0.5, 204 'ImageGrayscale', '0.5'), 205]) 206def test_customization(config_stub, setting, value, exp_key, exp_val): 207 config_stub.val.colors.webpage.darkmode.enabled = True 208 config_stub.set_obj('colors.webpage.darkmode.' + setting, value) 209 210 expected = [] 211 expected.append(('darkModeEnabled', 'true')) 212 if exp_key != 'ImagePolicy': 213 expected.append(('darkModeImagePolicy', '2')) 214 expected.append(('darkMode' + exp_key, exp_val)) 215 216 versions = version.WebEngineVersions.from_pyqt('5.15.1') 217 darkmode_settings = darkmode.settings(versions=versions, special_flags=[]) 218 assert darkmode_settings['blink-settings'] == expected 219 220 221@pytest.mark.parametrize('webengine_version, expected', [ 222 ('5.13.0', darkmode.Variant.qt_511_to_513), 223 ('5.14.0', darkmode.Variant.qt_514), 224 ('5.15.0', darkmode.Variant.qt_515_0), 225 ('5.15.1', darkmode.Variant.qt_515_1), 226 ('5.15.2', darkmode.Variant.qt_515_2), 227 ('5.15.3', darkmode.Variant.qt_515_3), 228 ('6.0.0', darkmode.Variant.qt_515_3), 229]) 230def test_variant(webengine_version, expected): 231 versions = version.WebEngineVersions.from_pyqt(webengine_version) 232 assert darkmode._variant(versions) == expected 233 234 235def test_variant_gentoo_workaround(gentoo_versions): 236 assert darkmode._variant(gentoo_versions) == darkmode.Variant.qt_515_3 237 238 239@pytest.mark.parametrize('value, is_valid, expected', [ 240 ('invalid_value', False, darkmode.Variant.qt_515_0), 241 ('qt_515_2', True, darkmode.Variant.qt_515_2), 242]) 243def test_variant_override(monkeypatch, caplog, value, is_valid, expected): 244 versions = version.WebEngineVersions.from_pyqt('5.15.0') 245 monkeypatch.setenv('QUTE_DARKMODE_VARIANT', value) 246 247 with caplog.at_level(logging.WARNING): 248 assert darkmode._variant(versions) == expected 249 250 log_msg = 'Ignoring invalid QUTE_DARKMODE_VARIANT=invalid_value' 251 assert (log_msg in caplog.messages) != is_valid 252 253 254def test_broken_smart_images_policy(config_stub, caplog): 255 config_stub.val.colors.webpage.darkmode.enabled = True 256 config_stub.val.colors.webpage.darkmode.policy.images = 'smart' 257 versions = version.WebEngineVersions.from_pyqt('5.15.0') 258 259 with caplog.at_level(logging.WARNING): 260 darkmode_settings = darkmode.settings(versions=versions, special_flags=[]) 261 262 assert caplog.messages[-1] == ( 263 'Ignoring colors.webpage.darkmode.policy.images = smart because of ' 264 'Qt 5.15.0 bug') 265 266 expected = [ 267 [('darkModeEnabled', 'true')], # Qt 5.15 268 [('darkMode', '4')], # Qt 5.14 269 ] 270 assert darkmode_settings['blink-settings'] in expected 271 272 273@pytest.mark.parametrize('flag, expected', [ 274 ('--blink-settings=key=value', [('key', 'value')]), 275 ('--blink-settings=key=equal=rights', [('key', 'equal=rights')]), 276 ('--blink-settings=one=1,two=2', [('one', '1'), ('two', '2')]), 277 ('--enable-features=feat', []), 278]) 279def test_pass_through_existing_settings(config_stub, flag, expected): 280 config_stub.val.colors.webpage.darkmode.enabled = True 281 versions = version.WebEngineVersions.from_pyqt('5.15.1') 282 settings = darkmode.settings(versions=versions, special_flags=[flag]) 283 284 dark_mode_expected = [ 285 ('darkModeEnabled', 'true'), 286 ('darkModeImagePolicy', '2'), 287 ] 288 assert settings['blink-settings'] == expected + dark_mode_expected 289 290 291def test_options(configdata_init): 292 """Make sure all darkmode options have the right attributes set.""" 293 for name, opt in configdata.DATA.items(): 294 if not name.startswith('colors.webpage.darkmode.'): 295 continue 296 297 assert not opt.supports_pattern, name 298 assert opt.restart, name 299 300 if opt.backends: 301 # On older Qt versions, this is an empty list. 302 assert opt.backends == [usertypes.Backend.QtWebEngine], name 303 304 if opt.raw_backends is not None: 305 assert not opt.raw_backends['QtWebKit'], name 306 assert opt.raw_backends['QtWebEngine'] == 'Qt 5.14', name 307