diff --git a/.travis.yml b/.travis.yml index 663c4c6f9..dfa566671 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,16 +68,3 @@ after_success: after_failure: - bash scripts/dev/ci/travis_backtrace.sh - -notifications: - webhooks: - - https://buildtimetrend.herokuapp.com/travis - irc: - channels: - - "chat.freenode.net#qutebrowser-dev" - on_success: always - on_failure: always - skip_join: true - template: - - "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}" - - "%{compare_url} - %{build_url}" diff --git a/MANIFEST.in b/MANIFEST.in index cd9e50cf9..a0e61c30e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -13,7 +13,7 @@ include qutebrowser/utils/testfile include qutebrowser/git-commit-id include LICENSE doc/* README.asciidoc include misc/qutebrowser.desktop -include misc/qutebrowser.appdata.xml +include misc/org.qutebrowser.qutebrowser.appdata.xml include misc/Makefile include requirements.txt include tox.ini diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 514261953..d5d76b181 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -25,6 +25,7 @@ Added opened from a page should stack on each other or not. - New `completion.open_categories` setting which allows to configure which categories are shown in the `:open` completion, and how they are ordered. +- New `tabs.pinned.frozen` setting to allow/deny navigating in pinned tabs. - New config manipulation commands: * `:config-dict-add` and `:config-list-add` to a new element to a dict/list setting. @@ -53,6 +54,11 @@ Changed - Various small performance improvements for hints and the completion. - The Wayland check for QtWebEngine is now disabled on Qt >= 5.11.2, as those versions should work without any issues. +- The JavaScript `console` object is now available in PAC files. +- The metainfo file `qutebrowser.appdata.xml` is now renamed to + `org.qutebrowser.qutebrowser.appdata.xml`. +- The `qute-pass` userscript now understands domains in gpg filenames + in addition to directory names. Fixed ~~~~~ @@ -67,9 +73,13 @@ Fixed `content.cookies.accept = no-3rdparty` from working properly on some pages like GMail. However, the default for `content.cookies.accept` is still `all` to be in line with what other browsers do. -- `:navigate` not incrementing in anchors or queries or anchors. +- `:navigate` not incrementing in anchors or queries. - Crash when trying to use a proxy requiring authentication with QtWebKit. - Slashes in search terms are now percent-escaped. +- When `scrolling.bar = True` was set in versions before v1.5.0, this now + correctly gets migrated to `always` instead of `when-searching`. +- Completion highlighting now works again on Qt 5.11.3 and 5.12.1. +- The outdated header `X-Do-Not-Track` is no longer sent. v1.5.2 ------ diff --git a/doc/faq.asciidoc b/doc/faq.asciidoc index 113a11f09..10661cb9e 100644 --- a/doc/faq.asciidoc +++ b/doc/faq.asciidoc @@ -211,9 +211,10 @@ Why does J move to the next (right) tab, and K to the previous (left) one?:: What's the difference between insert and passthrough mode?:: They are quite similar, but insert mode has some bindings (like `Ctrl-e` to - open an editor) while passthrough mode only has escape bound. It might also - be useful to rebind escape to something else in passthrough mode only, to be - able to send an escape keypress to the website. + open an editor) while passthrough mode only has shift+escape bound. This is + because shift+escape is unlikely to be a useful binding to be passed to a + webpage. However, any other keys may be assigned to leaving passthrough mode + instead of shift+escape should this be desired. Why does it take longer to open a URL in qutebrowser than in chromium?:: When opening a URL in an existing instance, the normal qutebrowser diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc index 33711b755..b04c9e9df 100644 --- a/doc/help/configuring.asciidoc +++ b/doc/help/configuring.asciidoc @@ -396,6 +396,7 @@ Pre-built colorschemes - A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager]. - Two implementations of the https://github.com/arcticicestudio/nord[Nord] colorscheme for qutebrowser exist: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon] - https://github.com/evannagle/qutebrowser-dracula-theme[Dracula] +- https://github.com/jjzmajic/qutewal[Pywal theme] Avoiding flake8 errors ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 7da6e543e..eb3907cce 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -261,6 +261,7 @@ |<>|Stack related tabs on top of each other when opened consecutively. |<>|Position of new tabs which are not opened from another tab. |<>|Padding (in pixels) around text for tabs. +|<>|Force pinned tabs to stay at fixed URL. |<>|Shrink pinned tabs down to their contents. |<>|Position of the tab bar. |<>|Which tab to select when the focused tab is removed. @@ -3307,6 +3308,14 @@ Default: - +pass:[right]+: +pass:[5]+ - +pass:[top]+: +pass:[0]+ +[[tabs.pinned.frozen]] +=== tabs.pinned.frozen +Force pinned tabs to stay at fixed URL. + +Type: <> + +Default: +pass:[true]+ + [[tabs.pinned.shrink]] === tabs.pinned.shrink Shrink pinned tabs down to their contents. diff --git a/doc/install.asciidoc b/doc/install.asciidoc index 37f6ebb12..c9ae54cd2 100644 --- a/doc/install.asciidoc +++ b/doc/install.asciidoc @@ -102,18 +102,12 @@ $ python3 scripts/asciidoc2html.py On Fedora --------- -NOTE: Fedora's packages used to be outdated for a long time, but are -now (November 2017) maintained and up-to-date again. - qutebrowser is available in the official repositories: ----- # dnf install qutebrowser ----- -However, note that Fedora 25/26 won't be updated to qutebrowser v1.0, so you -might want to <> instead there. - Additional hints ~~~~~~~~~~~~~~~~ diff --git a/misc/Makefile b/misc/Makefile index 4625b288e..526f7adce 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -17,8 +17,8 @@ doc/qutebrowser.1.html: install: doc/qutebrowser.1.html $(PYTHON) setup.py install --prefix="$(PREFIX)" --optimize=1 $(SETUPTOOLSOPTS) - install -Dm644 misc/qutebrowser.appdata.xml \ - "$(DESTDIR)$(DATADIR)/metainfo/qutebrowser.appdata.xml" + install -Dm644 misc/org.qutebrowser.qutebrowser.appdata.xml \ + "$(DESTDIR)$(DATADIR)/metainfo/org.qutebrowser.qutebrowser.appdata.xml" install -Dm644 doc/qutebrowser.1 \ "$(DESTDIR)$(MANDIR)/man1/qutebrowser.1" install -Dm644 misc/qutebrowser.desktop \ diff --git a/misc/qutebrowser.appdata.xml b/misc/org.qutebrowser.qutebrowser.appdata.xml similarity index 100% rename from misc/qutebrowser.appdata.xml rename to misc/org.qutebrowser.qutebrowser.appdata.xml diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt index 20a66cd5f..42255f825 100644 --- a/misc/requirements/requirements-flake8.txt +++ b/misc/requirements/requirements-flake8.txt @@ -11,7 +11,7 @@ flake8-deprecated==1.3 flake8-docstrings==1.3.0 flake8-future-import==0.4.5 flake8-mock==0.3 -flake8-per-file-ignores==0.6 +flake8-per-file-ignores==0.7 flake8-polyfill==1.0.2 flake8-string-format==0.2.3 flake8-tidy-imports==1.1.0 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 6f106798b..c089895d1 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -16,6 +16,6 @@ pytz==2018.7 requests==2.21.0 six==1.12.0 snowballstemmer==1.2.1 -Sphinx==1.8.2 +Sphinx==1.8.3 sphinxcontrib-websupport==1.1.0 urllib3==1.24.1 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index 28c26d891..228045f8c 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -3,8 +3,8 @@ atomicwrites==1.2.1 attrs==18.2.0 backports.functools-lru-cache==1.5 -beautifulsoup4==4.6.3 -cheroot==6.5.2 +beautifulsoup4==4.7.0 +cheroot==6.5.3 Click==7.0 # colorama==0.4.1 coverage==4.5.2 @@ -12,12 +12,12 @@ EasyProcess==0.2.5 Flask==1.0.2 glob2==0.6 hunter==2.1.0 -hypothesis==3.84.5 +hypothesis==3.85.2 itsdangerous==1.1.0 # Jinja2==2.10 Mako==1.0.7 # MarkupSafe==1.1.0 -more-itertools==4.3.0 +more-itertools==5.0.0 parse==1.9.0 parse-type==0.4.2 pluggy==0.8.0 diff --git a/misc/userscripts/password_fill b/misc/userscripts/password_fill index 2e4f01b66..7d4be0467 100755 --- a/misc/userscripts/password_fill +++ b/misc/userscripts/password_fill @@ -64,6 +64,7 @@ die() { javascript_escape() { # print the first argument in an escaped way, such that it can safely # be used within javascripts double quotes + # shellcheck disable=SC2001 sed "s,[\\\\'\"],\\\\&,g" <<< "$1" } @@ -111,6 +112,7 @@ simplify_url() { # are found: no_entries_found() { while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do + # shellcheck disable=SC2001 shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url") if [ "$shorter_simple_url" = "$simple_url" ] ; then # if no dot, then even remove the top level domain diff --git a/misc/userscripts/qute-pass b/misc/userscripts/qute-pass index ca9c4d4ca..bfc2cbeb9 100755 --- a/misc/userscripts/qute-pass +++ b/misc/userscripts/qute-pass @@ -97,13 +97,19 @@ def qute_command(command): def find_pass_candidates(domain, password_store_path): candidates = [] for path, directories, file_names in os.walk(password_store_path, followlinks=True): - if directories or domain not in path.split(os.path.sep): + secrets = fnmatch.filter(file_names, '*.gpg') + if not secrets: continue # Strip password store path prefix to get the relative pass path pass_path = path[len(password_store_path) + 1:] - secrets = fnmatch.filter(file_names, '*.gpg') - candidates.extend(os.path.join(pass_path, os.path.splitext(secret)[0]) for secret in secrets) + split_path = pass_path.split(os.path.sep) + for secret in secrets: + secret_base = os.path.splitext(secret)[0] + if domain not in (split_path + [secret_base]): + continue + + candidates.append(os.path.join(pass_path, secret_base)) return candidates diff --git a/misc/userscripts/qutedmenu b/misc/userscripts/qutedmenu index de1b8d641..cc5a44413 100755 --- a/misc/userscripts/qutedmenu +++ b/misc/userscripts/qutedmenu @@ -37,7 +37,7 @@ get_selection() { # https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font [[ -s $confdir/dmenu/font ]] && read -r font < "$confdir"/dmenu/font -[[ $font ]] && opts+=(-fn "$font") +[[ -n $font ]] && opts+=(-fn "$font") # shellcheck source=/dev/null [[ -s $optsfile ]] && source "$optsfile" @@ -46,7 +46,7 @@ url=$(get_selection) url=${url/*http/http} # If no selection is made, exit (escape pressed, e.g.) -[[ ! $url ]] && exit 0 +[[ -z $url ]] && exit 0 case $1 in open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;; diff --git a/pytest.ini b/pytest.ini index c907173e0..c278b0591 100644 --- a/pytest.ini +++ b/pytest.ini @@ -64,6 +64,7 @@ qt_log_ignore = ^QSettings::value: Empty key passed ^Icon theme ".*" not found ^Error receiving trust for a CA certificate + ^QBackingStore::endPaint\(\) called with active painter on backingstore paint device xfail_strict = true filterwarnings = error diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 029394657..55ab89a20 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -943,6 +943,10 @@ class AbstractTab(QWidget): evt.posted = True QApplication.postEvent(recipient, evt) + def navigation_blocked(self) -> bool: + """Test if navigation is allowed on the current tab.""" + return self.data.pinned and config.val.tabs.pinned.frozen + @pyqtSlot(QUrl) def _on_before_load_started(self, url: QUrl) -> None: """Adjust the title if we are going to visit a URL soon.""" diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 571e06d8b..6ae47f9d9 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -316,7 +316,7 @@ class CommandDispatcher: else: # Explicit count with a tab that doesn't exist. return - elif curtab.data.pinned: + elif curtab.navigation_blocked(): message.info("Tab is pinned!") else: curtab.load_url(cur_url) diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py index 1c6075945..bd060820b 100644 --- a/qutebrowser/browser/network/pac.py +++ b/qutebrowser/browser/network/pac.py @@ -180,6 +180,8 @@ class PACResolver: """ self._engine = QJSEngine() + self._engine.installExtensions(QJSEngine.ConsoleExtension) + self._ctx = _PACContext(self._engine) self._engine.globalObject().setProperty( "PAC", self._engine.newQObject(self._ctx)) diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index 0bf3301f9..92130be65 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -42,7 +42,6 @@ def custom_headers(url): if dnt_config is not None: dnt = b'1' if dnt_config else b'0' headers[b'DNT'] = dnt - headers[b'X-Do-Not-Track'] = dnt conf_headers = config.instance.get('content.headers.custom', url=url) for header, value in conf_headers.items(): diff --git a/qutebrowser/browser/webengine/webenginequtescheme.py b/qutebrowser/browser/webengine/webenginequtescheme.py index 68ffa019d..816589514 100644 --- a/qutebrowser/browser/webengine/webenginequtescheme.py +++ b/qutebrowser/browser/webengine/webenginequtescheme.py @@ -22,6 +22,11 @@ from PyQt5.QtCore import QBuffer, QIODevice, QUrl from PyQt5.QtWebEngineCore import (QWebEngineUrlSchemeHandler, QWebEngineUrlRequestJob) +try: + from PyQt5.QtWebEngineCore import QWebEngineUrlScheme # type: ignore +except ImportError: + # Added in Qt 5.12 + QWebEngineUrlScheme = None from qutebrowser.browser import qutescheme from qutebrowser.utils import log, qtutils @@ -33,8 +38,12 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler): def install(self, profile): """Install the handler for qute:// URLs on the given profile.""" + if QWebEngineUrlScheme is not None: + assert QWebEngineUrlScheme.schemeByName(b'qute') is not None + profile.installUrlSchemeHandler(b'qute', self) - if qtutils.version_check('5.11', compiled=False): + if (qtutils.version_check('5.11', compiled=False) and + not qtutils.version_check('5.12', compiled=False)): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378 profile.installUrlSchemeHandler(b'chrome-error', self) profile.installUrlSchemeHandler(b'chrome-extension', self) @@ -130,3 +139,16 @@ class QuteSchemeHandler(QWebEngineUrlSchemeHandler): buf.seek(0) buf.close() job.reply(mimetype.encode('ascii'), buf) + + +def init(): + """Register the qute:// scheme. + + Note this needs to be called early, before constructing any QtWebEngine + classes. + """ + if QWebEngineUrlScheme is not None: + scheme = QWebEngineUrlScheme(b'qute') + scheme.setFlags(QWebEngineUrlScheme.LocalScheme | + QWebEngineUrlScheme.LocalAccessAllowed) + QWebEngineUrlScheme.registerScheme(scheme) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index da569eef6..10c4d4e6b 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -30,7 +30,7 @@ from PyQt5.QtGui import QFont from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile, QWebEnginePage) -from qutebrowser.browser.webengine import spell +from qutebrowser.browser.webengine import spell, webenginequtescheme from qutebrowser.config import config, websettings from qutebrowser.config.websettings import AttributeInfo as Attr from qutebrowser.utils import utils, standarddir, qtutils, message, log @@ -298,6 +298,7 @@ def init(args): not hasattr(QWebEnginePage, 'setInspectedPage')): # only Qt < 5.11 os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port()) + webenginequtescheme.init() spell.init() _init_profiles() diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py index 3ed5f0a64..b58f36372 100644 --- a/qutebrowser/completion/completiondelegate.py +++ b/qutebrowser/completion/completiondelegate.py @@ -212,11 +212,11 @@ class CompletionItemDelegate(QStyledItemDelegate): view = self.parent() pattern = view.pattern columns_to_filter = index.model().columns_to_filter(index) - self._doc.setPlainText(self._opt.text) if index.column() in columns_to_filter and pattern: pat = re.escape(pattern).replace(r'\ ', r'|') _Highlighter(self._doc, pat, config.val.colors.completion.match.fg) + self._doc.setPlainText(self._opt.text) else: self._doc.setHtml( '{}'.format( diff --git a/qutebrowser/components/misccommands.py b/qutebrowser/components/misccommands.py index eaf45f40d..a65bdd235 100644 --- a/qutebrowser/components/misccommands.py +++ b/qutebrowser/components/misccommands.py @@ -118,7 +118,7 @@ def printpage(tab: apitypes.Tab, @cmdutils.argument('tab', value=cmdutils.Value.cur_tab) def home(tab: apitypes.Tab) -> None: """Open main startpage in current tab.""" - if tab.data.pinned: + if tab.navigation_blocked(): message.info("Tab is pinned!") else: tab.load_url(config.val.url.start_pages[0]) diff --git a/qutebrowser/config/configcache.py b/qutebrowser/config/configcache.py index a421ba85c..15f343478 100644 --- a/qutebrowser/config/configcache.py +++ b/qutebrowser/config/configcache.py @@ -46,7 +46,9 @@ class ConfigCache: self._cache[attr] = config.instance.get(attr) def __getitem__(self, attr: str) -> typing.Any: - if attr not in self._cache: + try: + return self._cache[attr] + except KeyError: assert not config.instance.get_opt(attr).supports_pattern self._cache[attr] = config.instance.get(attr) - return self._cache[attr] + return self._cache[attr] diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index bed4d9659..b6d4736ae 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -1768,6 +1768,11 @@ tabs.pinned.shrink: type: Bool desc: Shrink pinned tabs down to their contents. +tabs.pinned.frozen: + type: Bool + default: True + desc: Force pinned tabs to stay at fixed URL. + tabs.wrap: default: true type: Bool diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index 54ca91488..de50dfca9 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -308,7 +308,7 @@ class YamlConfig(QObject): self._migrate_bool(settings, 'tabs.favicons.show', 'always', 'never') self._migrate_bool(settings, 'scrolling.bar', - 'when-searching', 'never') + 'always', 'when-searching') self._migrate_bool(settings, 'qt.force_software_rendering', 'software-opengl', 'none') diff --git a/scripts/dev/ci/travis_install.sh b/scripts/dev/ci/travis_install.sh index 18f5aa9ec..c736a01d3 100644 --- a/scripts/dev/ci/travis_install.sh +++ b/scripts/dev/ci/travis_install.sh @@ -71,7 +71,7 @@ EOF set -e -if [[ $DOCKER ]]; then +if [[ -n $DOCKER ]]; then exit 0 elif [[ $TRAVIS_OS_NAME == osx ]]; then # Disable App Nap diff --git a/scripts/dev/ci/travis_run.sh b/scripts/dev/ci/travis_run.sh index a287e844e..4e338221f 100644 --- a/scripts/dev/ci/travis_run.sh +++ b/scripts/dev/ci/travis_run.sh @@ -1,6 +1,6 @@ #!/bin/bash -if [[ $DOCKER ]]; then +if [[ -n $DOCKER ]]; then docker run \ --privileged \ -v "$PWD:/outside" \ diff --git a/tests/end2end/features/downloads.feature b/tests/end2end/features/downloads.feature index 7bde58b4f..b1d92145d 100644 --- a/tests/end2end/features/downloads.feature +++ b/tests/end2end/features/downloads.feature @@ -93,7 +93,7 @@ Feature: Downloading things from a website. Then no crash should happen # https://github.com/qutebrowser/qutebrowser/issues/4240 - @qt!=5.11.2 + @qt<5.11.2 Scenario: Downloading with SSL errors (issue 1413) When SSL is supported And I clear SSL errors diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index b9677a158..48273bdf8 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -331,19 +331,16 @@ Feature: Various utility commands. When I set content.headers.do_not_track to true And I open headers Then the header Dnt should be set to 1 - And the header X-Do-Not-Track should be set to 1 Scenario: DNT header (off) When I set content.headers.do_not_track to false And I open headers Then the header Dnt should be set to 0 - And the header X-Do-Not-Track should be set to 0 Scenario: DNT header (unset) When I set content.headers.do_not_track to And I open headers Then the header Dnt should be set to - And the header X-Do-Not-Track should be set to Scenario: Accept-Language header When I set content.headers.accept_language to en,de diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature index 7f4d4635c..804f72bbf 100644 --- a/tests/end2end/features/tabs.feature +++ b/tests/end2end/features/tabs.feature @@ -1289,6 +1289,14 @@ Feature: Tab management And the following tabs should be open: - data/numbers/1.txt (active) (pinned) + Scenario: :tab-pin open url with tabs.pinned.frozen = false + When I set tabs.pinned.frozen to false + And I open data/numbers/1.txt + And I run :tab-pin + And I open data/numbers/2.txt + Then the following tabs should be open: + - data/numbers/2.txt (active) (pinned) + Scenario: :home on a pinned tab When I open data/numbers/1.txt And I run :tab-pin @@ -1297,6 +1305,16 @@ Feature: Tab management And the following tabs should be open: - data/numbers/1.txt (active) (pinned) + Scenario: :home on a pinned tab with tabs.pinned.frozen = false + When I set url.start_pages to ["http://localhost:(port)/data/numbers/2.txt"] + And I set tabs.pinned.frozen to false + And I open data/numbers/1.txt + And I run :tab-pin + And I run :home + Then data/numbers/2.txt should be loaded + And the following tabs should be open: + - data/numbers/2.txt (active) (pinned) + Scenario: Cloning a pinned tab When I open data/numbers/1.txt And I run :tab-pin diff --git a/tests/unit/browser/test_shared.py b/tests/unit/browser/test_shared.py index 78302d8c1..b8da41a02 100644 --- a/tests/unit/browser/test_shared.py +++ b/tests/unit/browser/test_shared.py @@ -26,18 +26,15 @@ from qutebrowser.browser import shared @pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [ # DNT - (True, None, {}, {b'DNT': b'1', b'X-Do-Not-Track': b'1'}), - (False, None, {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0'}), + (True, None, {}, {b'DNT': b'1'}), + (False, None, {}, {b'DNT': b'0'}), (None, None, {}, {}), # Accept-Language - (False, 'de, en', {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0', - b'Accept-Language': b'de, en'}), + (False, 'de, en', {}, {b'DNT': b'0', b'Accept-Language': b'de, en'}), # Custom headers - (False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Do-Not-Track': b'0', - b'X-Qute': b'yes'}), + (False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Qute': b'yes'}), # Mixed (False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0', - b'X-Do-Not-Track': b'0', b'Accept-Language': b'de, en', b'X-Qute': b'yes'}), ]) diff --git a/tests/unit/browser/webkit/network/test_pac.py b/tests/unit/browser/webkit/network/test_pac.py index 8c03c6cee..5aebecbf2 100644 --- a/tests/unit/browser/webkit/network/test_pac.py +++ b/tests/unit/browser/webkit/network/test_pac.py @@ -205,6 +205,20 @@ def test_secret_url(url, has_secret, from_file): res.resolve(QNetworkProxyQuery(QUrl(url)), from_file=from_file) +def test_logging(qtlog): + """Make sure console.log() works for PAC files.""" + test_str = """ + function FindProxyForURL(domain, host) { + console.log("logging test"); + return "DIRECT"; + } + """ + res = pac.PACResolver(test_str) + res.resolve(QNetworkProxyQuery(QUrl("https://example.com/test"))) + assert len(qtlog.records) == 1 + assert qtlog.records[0].message == 'logging test' + + def fetcher_test(test_str): class PACHandler(http.server.BaseHTTPRequestHandler): def do_GET(self): diff --git a/tests/unit/completion/test_completiondelegate.py b/tests/unit/completion/test_completiondelegate.py index 2d122927d..7d310380e 100644 --- a/tests/unit/completion/test_completiondelegate.py +++ b/tests/unit/completion/test_completiondelegate.py @@ -20,7 +20,8 @@ from unittest import mock import pytest from PyQt5.QtCore import Qt -from PyQt5.QtGui import QTextDocument +from PyQt5.QtGui import QTextDocument, QColor +from PyQt5.QtWidgets import QTextEdit from qutebrowser.completion import completiondelegate @@ -50,3 +51,24 @@ def test_highlight(pat, txt, segments): highlighter.setFormat.assert_has_calls([ mock.call(s[0], s[1], mock.ANY) for s in segments ]) + + +def test_highlighted(qtbot): + """Make sure highlighting works. + + Note that with Qt 5.11.3 and > 5.12.1 we need to call setPlainText *after* + creating the highlighter for highlighting to work. Ideally, we'd test + whether CompletionItemDelegate._get_textdoc() works properly, but testing + that is kind of hard, so we just test it in isolation here. + """ + doc = QTextDocument() + completiondelegate._Highlighter(doc, 'Hello', Qt.red) + doc.setPlainText('Hello World') + + # Needed so the highlighting actually works. + edit = QTextEdit() + qtbot.addWidget(edit) + edit.setDocument(doc) + + colors = [f.foreground().color() for f in doc.allFormats()] + assert QColor('red') in colors diff --git a/tests/unit/config/test_configcache.py b/tests/unit/config/test_configcache.py index 91e2f22fa..7c0f6012f 100644 --- a/tests/unit/config/test_configcache.py +++ b/tests/unit/config/test_configcache.py @@ -50,3 +50,17 @@ def test_configcache_get_after_set(config_stub): assert not config.cache['auto_save.session'] config_stub.val.auto_save.session = True assert config.cache['auto_save.session'] + + +def test_configcache_naive_benchmark(config_stub, benchmark): + def _run_bench(): + for _i in range(10000): + # pylint: disable=pointless-statement + config.cache['tabs.padding'] + config.cache['tabs.indicator.width'] + config.cache['tabs.indicator.padding'] + config.cache['tabs.min_width'] + config.cache['tabs.max_width'] + config.cache['tabs.pinned.shrink'] + # pylint: enable=pointless-statement + benchmark(_run_bench) diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py index 2b793b58b..79d4b9d89 100644 --- a/tests/unit/config/test_configfiles.py +++ b/tests/unit/config/test_configfiles.py @@ -250,36 +250,28 @@ class TestYaml: data = autoconfig.read() assert data['content.webrtc_ip_handling_policy']['global'] == expected - @pytest.mark.parametrize('show, expected', [ - (True, 'always'), - (False, 'never'), - ('always', 'always'), - ('never', 'never'), - ('pinned', 'pinned'), + @pytest.mark.parametrize('setting, old, new', [ + ('tabs.favicons.show', True, 'always'), + ('tabs.favicons.show', False, 'never'), + ('tabs.favicons.show', 'always', 'always'), + + ('scrolling.bar', True, 'always'), + ('scrolling.bar', False, 'when-searching'), + ('scrolling.bar', 'always', 'always'), + + ('qt.force_software_rendering', True, 'software-opengl'), + ('qt.force_software_rendering', False, 'none'), + ('qt.force_software_rendering', 'chromium', 'chromium'), ]) - def test_tabs_favicons_show(self, yaml, autoconfig, show, expected): - """Tests for migration of tabs.favicons.show.""" - autoconfig.write({'tabs.favicons.show': {'global': show}}) + def test_bool_migrations(self, yaml, autoconfig, setting, old, new): + """Tests for migration of former boolean settings.""" + autoconfig.write({setting: {'global': old}}) yaml.load() yaml._save() data = autoconfig.read() - assert data['tabs.favicons.show']['global'] == expected - - @pytest.mark.parametrize('force, expected', [ - (True, 'software-opengl'), - (False, 'none'), - ('chromium', 'chromium'), - ]) - def test_force_software_rendering(self, yaml, autoconfig, force, expected): - autoconfig.write({'qt.force_software_rendering': {'global': force}}) - - yaml.load() - yaml._save() - - data = autoconfig.read() - assert data['qt.force_software_rendering']['global'] == expected + assert data[setting]['global'] == new def test_renamed_key_unknown_target(self, monkeypatch, yaml, autoconfig):