diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 7a7171b33..8b5b2c926 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -263,7 +263,7 @@ class ConfigCommands: values = ['false', 'true'] else: raise cmdexc.CommandError( - "set: Attempted inversion of non-boolean value.") + "set: Can't toggle non-bool setting {}".format(option)) elif not values: raise cmdexc.CommandError("set: The following arguments " "are required: value") diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index aaff1da7c..583f58cff 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -324,6 +324,35 @@ Feature: Various utility commands. - about:blank - qute://history/ (active) + # qute://settings + + Scenario: Focusing input fields in qute://settings and entering valid value + When I set ignore_case to never + And I open qute://settings + # scroll to the right - the table does not fit in the default screen + And I run :scroll-perc -x 100 + And I run :click-element id input-ignore_case + And I wait for "Entering mode KeyMode.insert *" in the log + And I press the key "" + And I press the keys "always" + And I press the key "" + # an explicit Tab to unfocus the input field seems to stabilize the tests + And I press the key "" + Then the option ignore_case should be set to always + + Scenario: Focusing input fields in qute://settings and entering invalid value + When I open qute://settings + # scroll to the right - the table does not fit in the default screen + And I run :scroll-perc -x 100 + And I run :click-element id input-ignore_case + And I wait for "Entering mode KeyMode.insert *" in the log + And I press the key "" + And I press the keys "foo" + And I press the key "" + # an explicit Tab to unfocus the input field seems to stabilize the tests + And I press the key "" + Then "Invalid value 'foo' *" should be logged + # :home Scenario: :home with single page diff --git a/tests/end2end/features/set.feature b/tests/end2end/features/set.feature deleted file mode 100644 index e9ae8a11b..000000000 --- a/tests/end2end/features/set.feature +++ /dev/null @@ -1,118 +0,0 @@ -# vim: ft=cucumber fileencoding=utf-8 sts=4 sw=4 et: - -Feature: Setting settings. - - Background: - Given I set messages.timeout to 100 - - Scenario: Using :set - When I run :set colors.statusbar.normal.bg magenta - Then the option colors.statusbar.normal.bg should be set to magenta - - Scenario: Without value - When I run :set colors.statusbar.normal.bg - Then the error "set: The following arguments are required: value" should be shown - - Scenario: Invalid option - When I run :set blub foo - Then the error "set: No option 'blub'" should be shown - - Scenario: Toggling an option - When I run :set auto_save.config false - And I run :set auto_save.config! - Then the option auto_save.config should be set to true - - Scenario: Toggling a non-bool option - When I run :set colors.statusbar.normal.bg! - Then the error "set: Attempted inversion of non-boolean value." should be shown - - Scenario: Cycling an option - When I run :set colors.statusbar.normal.bg magenta - And I run :set colors.statusbar.normal.bg green magenta blue yellow - Then the option colors.statusbar.normal.bg should be set to blue - - Scenario: Cycling an option through the end of the list - When I run :set colors.statusbar.normal.bg yellow - And I run :set colors.statusbar.normal.bg green magenta blue yellow - Then the option colors.statusbar.normal.bg should be set to green - - Scenario: Cycling an option that's not on the list - When I run :set colors.statusbar.normal.bg red - And I run :set colors.statusbar.normal.bg green magenta blue yellow - Then the option colors.statusbar.normal.bg should be set to green - - Scenario: Cycling through a single option - When I run :set colors.statusbar.normal.bg red - And I run :set colors.statusbar.normal.bg red - Then the option colors.statusbar.normal.bg should be set to red - - Scenario: Getting an option - When I run :set colors.statusbar.normal.bg magenta - And I run :set colors.statusbar.normal.bg? - Then the message "colors.statusbar.normal.bg = magenta" should be shown - - Scenario: Using -p - When I run :set -p colors.statusbar.normal.bg red - Then the message "colors.statusbar.normal.bg = red" should be shown - - Scenario: Using ! and -p - When I run :set auto_save.config false - And I run :set -p auto_save.config! - Then the message "auto_save.config = true" should be shown - - Scenario: Setting an invalid value - When I run :set auto_save.config blah - Then the error "set: Invalid value 'blah' - must be a boolean!" should be shown - - Scenario: Setting a temporary option - # We don't actually check if the option is temporary as this isn't easy - # to check. - When I run :set -t colors.statusbar.normal.bg green - Then the option colors.statusbar.normal.bg should be set to green - - # qute://settings isn't actually implemented on QtWebEngine, but this works - # (and displays a page saying it's not available) - Scenario: Opening qute://settings - When I run :set - And I wait until qute://settings is loaded - Then the following tabs should be open: - - qute://settings (active) - - Scenario: Focusing input fields in qute://settings and entering valid value - When I set ignore_case to never - And I open qute://settings - # scroll to the right - the table does not fit in the default screen - And I run :scroll-perc -x 100 - And I run :click-element id input-ignore_case - And I wait for "Entering mode KeyMode.insert *" in the log - And I press the key "" - And I press the keys "always" - And I press the key "" - # an explicit Tab to unfocus the input field seems to stabilize the tests - And I press the key "" - Then the option ignore_case should be set to always - - Scenario: Focusing input fields in qute://settings and entering invalid value - When I open qute://settings - # scroll to the right - the table does not fit in the default screen - And I run :scroll-perc -x 100 - And I run :click-element id input-ignore_case - And I wait for "Entering mode KeyMode.insert *" in the log - And I press the key "" - And I press the keys "foo" - And I press the key "" - # an explicit Tab to unfocus the input field seems to stabilize the tests - And I press the key "" - Then "Invalid value 'foo' *" should be logged - - Scenario: Empty option with ? (issue 1109) - When I run :set ? - Then the error "set: The following arguments are required: value" should be shown - - Scenario: Invalid option with ? (issue 1109) - When I run :set foo? - Then the error "set: No option 'foo'" should be shown - - Scenario: Invalid option with ! - When I run :set foo! - Then the error "set: No option 'foo'" should be shown diff --git a/tests/end2end/features/test_set_bdd.py b/tests/end2end/features/test_set_bdd.py deleted file mode 100644 index fa94de88f..000000000 --- a/tests/end2end/features/test_set_bdd.py +++ /dev/null @@ -1,21 +0,0 @@ -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# Copyright 2015-2017 Florian Bruhin (The Compiler) -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -import pytest_bdd as bdd -bdd.scenarios('set.feature') diff --git a/tests/helpers/fixtures.py b/tests/helpers/fixtures.py index c59fb233c..af080f7b8 100644 --- a/tests/helpers/fixtures.py +++ b/tests/helpers/fixtures.py @@ -206,7 +206,9 @@ def cmdline_test(request): def config_stub(stubs, monkeypatch): """Fixture which provides a fake config object.""" configdata.init() - conf = config.Config(yaml_config=None) + yaml_config = stubs.FakeYamlConfig() + + conf = config.Config(yaml_config=yaml_config) conf.read_configdata() monkeypatch.setattr(config, 'instance', conf) diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index 51a5a1058..13cd4dfe3 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -387,6 +387,12 @@ class InstaTimer(QObject): pass +class FakeYamlConfig: + + def __init__(self): + self.values = {} + + class FakeConfigType: """A stub to provide valid_values for typ attribute of a SettingValue.""" @@ -530,6 +536,9 @@ class TabbedBrowserStub(QObject): def tabopen(self, url): self.opened_url = url + def openurl(self, url, *, newtab): + self.opened_url = url + class ApplicationStub(QObject): diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index 21302df6e..9ab501e00 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -21,10 +21,12 @@ import copy import pytest -from PyQt5.QtCore import QObject +from PyQt5.QtCore import QObject, QUrl import qutebrowser.app # To register commands +from qutebrowser.commands import cmdexc from qutebrowser.config import config, configdata, configexc +from qutebrowser.utils import objreg, usertypes @pytest.fixture(autouse=True) @@ -301,3 +303,163 @@ def test_set_register_stylesheet(delete, stylesheet_param, update, qtbot, expected = 'yellow' assert obj.rendered_stylesheet == expected + + +class TestConfigCommands: + + @pytest.fixture + def commands(self, config_stub): + return config.ConfigCommands(config_stub) + + @pytest.fixture + def tabbed_browser(self, stubs, win_registry): + tb = stubs.TabbedBrowserStub() + objreg.register('tabbed-browser', tb, scope='window', window=0) + yield tb + objreg.delete('tabbed-browser', scope='window', window=0) + + def test_set_no_args(self, commands, tabbed_browser): + """:set + + Should open qute://settings.""" + commands.set(win_id=0) + assert tabbed_browser.opened_url == QUrl('qute://settings') + + def test_get(self, config_stub, commands, message_mock): + """:set url.auto_search? + + Should show the value. + """ + config_stub.val.url.auto_search = 'never' + commands.set(win_id=0, option='url.auto_search?') + msg = message_mock.getmsg(usertypes.MessageLevel.info) + assert msg.text == 'url.auto_search = never' + + @pytest.mark.parametrize('temp', [True, False]) + def test_set_simple(self, commands, config_stub, temp): + """:set [-t] url.auto_search dns + + Should set the setting accordingly. + """ + assert config_stub.val.url.auto_search == 'naive' + commands.set(0, 'url.auto_search', 'dns', temp=temp) + + assert config_stub.val.url.auto_search == 'dns' + + if temp: + assert 'url.auto_search' not in config_stub._yaml.values + else: + assert config_stub._yaml.values['url.auto_search'] == 'dns' + + @pytest.mark.parametrize('temp', [True, False]) + def test_set_temp_override(self, commands, config_stub, temp): + """Invoking :set twice. + + :set url.auto_search dns + :set -t url.auto_search never + + Should set the setting accordingly. + """ + assert config_stub.val.url.auto_search == 'naive' + commands.set(0, 'url.auto_search', 'dns') + commands.set(0, 'url.auto_search', 'never', temp=True) + + assert config_stub.val.url.auto_search == 'never' + assert config_stub._yaml.values['url.auto_search'] == 'dns' + + def test_set_print(self, config_stub, commands, message_mock): + """:set -p url.auto_search never + + Should set show the value. + """ + assert config_stub.val.url.auto_search == 'naive' + commands.set(0, 'url.auto_search', 'dns', print_=True) + + assert config_stub.val.url.auto_search == 'dns' + msg = message_mock.getmsg(usertypes.MessageLevel.info) + assert msg.text == 'url.auto_search = dns' + + def test_set_toggle(self, commands, config_stub): + """:set auto_save.config! + + Should toggle the value. + """ + assert config_stub.val.auto_save.config + commands.set(0, 'auto_save.config!') + assert not config_stub.val.auto_save.config + assert not config_stub._yaml.values['auto_save.config'] + + def test_set_toggle_nonbool(self, commands, config_stub): + """:set url.auto_search! + + Should show an error + """ + assert config_stub.val.url.auto_search == 'naive' + with pytest.raises(cmdexc.CommandError, match="set: Can't toggle " + "non-bool setting url.auto_search"): + commands.set(0, 'url.auto_search!') + assert config_stub.val.url.auto_search == 'naive' + + def test_set_toggle_print(self, commands, config_stub, message_mock): + """:set -p auto_save.config! + + Should toggle the value and show the new value. + """ + commands.set(0, 'auto_save.config!', print_=True) + msg = message_mock.getmsg(usertypes.MessageLevel.info) + assert msg.text == 'auto_save.config = false' + + def test_set_invalid_option(self, commands): + """:set foo bar + + Should show an error. + """ + with pytest.raises(cmdexc.CommandError, match="set: No option 'foo'"): + commands.set(0, 'foo', 'bar') + + def test_set_invalid_value(self, commands): + """:set auto_save.config blah + + Should show an error. + """ + with pytest.raises(cmdexc.CommandError, + match="set: Invalid value 'blah' - must be a " + "boolean!"): + commands.set(0, 'auto_save.config', 'blah') + + @pytest.mark.parametrize('option', ['?', '!', 'url.auto_search']) + def test_empty(self, commands, option): + """:set ? / :set ! / :set url.auto_search + + Should show an error. + See https://github.com/qutebrowser/qutebrowser/issues/1109 + """ + with pytest.raises(cmdexc.CommandError, + match="set: The following arguments are required: " + "value"): + commands.set(win_id=0, option=option) + + @pytest.mark.parametrize('suffix', '?!') + def test_invalid(self, commands, suffix): + """:set foo? / :set foo! + + Should show an error. + """ + with pytest.raises(cmdexc.CommandError, match="set: No option 'foo'"): + commands.set(win_id=0, option='foo' + suffix) + + @pytest.mark.parametrize('initial, expected', [ + # Normal cycling + ('magenta', 'blue'), + # Through the end of the list + ('yellow', 'green'), + # Value which is not in the list + ('red', 'green'), + ]) + def test_cycling(self, commands, config_stub, initial, expected): + """:set with multiple values.""" + opt = 'colors.statusbar.normal.bg' + config_stub.set_obj(opt, initial) + commands.set(0, opt, 'green', 'magenta', 'blue', 'yellow') + assert config_stub.get(opt) == expected + assert config_stub._yaml.values[opt] == expected