From 42dfc82fb875a7cbeb15cdf10f00deaf01dd921e Mon Sep 17 00:00:00 2001 From: Philipp Albrecht Date: Wed, 23 Aug 2023 09:26:07 +0200 Subject: Use (testdata) in "I open {path}" BDD step --- tests/end2end/features/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index 9dd497c0b..d25905bfe 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -199,6 +199,7 @@ def open_path(quteproc, server, path): - With "... as a URL", it's opened according to new_instance_open_target. """ path = path.replace('(port)', str(server.port)) + path = path.replace('(testdata)', testutils.abs_datapath()) new_tab = False new_bg_tab = False -- cgit v1.2.3-54-g00ecf From 21751603b48b507b1216479b05c0bfc711c1cdd9 Mon Sep 17 00:00:00 2001 From: Philipp Albrecht Date: Wed, 23 Aug 2023 09:27:31 +0200 Subject: Support opening file:// URLs in end2end tests This is required to use BDD steps like the following: ``` When I open file://path/to/file.html ``` If we don't treat `file:` as a special scheme, we implicitly convert it to an invalid URL: ``` http://localhost:48595/file:///path/to/file.html ``` --- tests/end2end/fixtures/quteprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py index a3929ed7e..cf00c38da 100644 --- a/tests/end2end/fixtures/quteprocess.py +++ b/tests/end2end/fixtures/quteprocess.py @@ -393,7 +393,7 @@ class QuteProc(testprocess.Process): verbatim. """ special_schemes = ['about:', 'qute:', 'chrome:', 'view-source:', - 'data:', 'http:', 'https:'] + 'data:', 'http:', 'https:', 'file:'] server = self.request.getfixturevalue('server') server_port = server.port if port is None else port -- cgit v1.2.3-54-g00ecf From 3974725932c2e3e06bd16e73a3a6b6f15e1beec4 Mon Sep 17 00:00:00 2001 From: Philipp Albrecht Date: Wed, 23 Aug 2023 09:42:50 +0200 Subject: Normalize end2end data directory path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given the following scenario: ``` When I open file://(testdata)/some/file.html Then file://(testdata)/some/file.html should be loaded ``` If the end2end data directory is not normalized, the scenario fails because we try to compare ``` file:///home/palbrecht/dev/qutebrowser/tests/helpers/../end2end/data/hints/link_inject.html?port=50… ``` to ``` file:///home/palbrecht/dev/qutebrowser/tests/end2end/data/hints/link_inject.html?port=50… ``` Normalizing the path resolves the `..` and fixes the issue. --- tests/end2end/features/conftest.py | 9 ++++----- tests/helpers/testutils.py | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index d25905bfe..62a81c5fc 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -33,8 +33,7 @@ def _get_echo_exe_path(): Path to the "echo"-utility. """ if utils.is_windows: - return os.path.join(testutils.abs_datapath(), 'userscripts', - 'echo.bat') + return str(testutils.abs_datapath() / 'userscripts' / 'echo.bat') else: return shutil.which("echo") @@ -199,7 +198,7 @@ def open_path(quteproc, server, path): - With "... as a URL", it's opened according to new_instance_open_target. """ path = path.replace('(port)', str(server.port)) - path = path.replace('(testdata)', testutils.abs_datapath()) + path = path.replace('(testdata)', os.fspath(testutils.abs_datapath())) new_tab = False new_bg_tab = False @@ -271,7 +270,7 @@ def run_command(quteproc, server, tmpdir, command): invalid = False command = command.replace('(port)', str(server.port)) - command = command.replace('(testdata)', testutils.abs_datapath()) + command = command.replace('(testdata)', str(testutils.abs_datapath())) command = command.replace('(tmpdir)', str(tmpdir)) command = command.replace('(dirsep)', os.sep) command = command.replace('(echo-exe)', _get_echo_exe_path()) @@ -365,7 +364,7 @@ def hint(quteproc, args): @bdd.when(bdd.parsers.parse('I hint with args "{args}" and follow {letter}')) def hint_and_follow(quteproc, args, letter): - args = args.replace('(testdata)', testutils.abs_datapath()) + args = args.replace('(testdata)', str(testutils.abs_datapath())) args = args.replace('(python-executable)', sys.executable) quteproc.send_cmd(':hint {}'.format(args)) quteproc.wait_for(message='hints: *') diff --git a/tests/helpers/testutils.py b/tests/helpers/testutils.py index dc6fdac32..a6022a6f9 100644 --- a/tests/helpers/testutils.py +++ b/tests/helpers/testutils.py @@ -192,8 +192,8 @@ def pattern_match(*, pattern, value): def abs_datapath(): """Get the absolute path to the end2end data directory.""" - file_abs = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(file_abs, '..', 'end2end', 'data') + path = pathlib.Path(__file__).parent / '..' / 'end2end' / 'data' + return path.resolve() @contextlib.contextmanager -- cgit v1.2.3-54-g00ecf From 43ca14aa5339b828f64ca2b0150f75604056062d Mon Sep 17 00:00:00 2001 From: Philipp Albrecht Date: Wed, 23 Aug 2023 09:51:29 +0200 Subject: Allow hinted navigation from file:// to remote origins As of Qt 6 navigating from local to remote origins requires user interaction. This broke following links to remote origins via hints from a local file (e.g. `bookmarks.html`), because hints use JavaScript to open links by default. Example: 1. Have a local `bookmarks.html`: ```html My bookmarks some bookmark ``` 2. Open that local `bookmarks.html` in qutebrowser (e.g. `:open path/to/bookmarks.html`) 3. Start hinting 4. Follow a link to a bookmark (e.g. https://example.com/) 5. Instead of the link opening, be presented with `Your internet access is blocked` error To fix this, we simply force a user interaction for all hints on file:// URLs (like we did for `qute://` URLs in 8defe1ae44c1c524e937ae08ed16052ee0724e0f). We skip the end2end test for webkit, because webkit does not support URLSearchParams[1] used in `tests/end2end/data/hints/link_inject.html` [1] https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams --- qutebrowser/browser/webengine/webengineelem.py | 16 +++++++++------- tests/end2end/data/hints/link_inject.html | 19 +++++++++++++++++++ tests/end2end/features/hints.feature | 7 +++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 tests/end2end/data/hints/link_inject.html diff --git a/qutebrowser/browser/webengine/webengineelem.py b/qutebrowser/browser/webengine/webengineelem.py index 20c3a36d4..c387ebbcf 100644 --- a/qutebrowser/browser/webengine/webengineelem.py +++ b/qutebrowser/browser/webengine/webengineelem.py @@ -215,14 +215,16 @@ class WebEngineElement(webelem.AbstractWebElement): return False # Qt 6.3+ needs a user interaction to allow navigations from qute:// to - # outside qute:// (like e.g. on qute://bookmarks). + # outside qute:// (like e.g. on qute://bookmarks), as well as from file:// to + # outside of file:// (e.g. users having a local bookmarks.html). versions = version.qtwebengine_versions() - if ( - baseurl.scheme() == "qute" and - url.scheme() != "qute" and - versions.webengine >= utils.VersionNumber(6, 3) - ): - return True + for scheme in ["qute", "file"]: + if ( + baseurl.scheme() == scheme and + url.scheme() != scheme and + versions.webengine >= utils.VersionNumber(6, 3) + ): + return True return url.scheme() not in urlutils.WEBENGINE_SCHEMES diff --git a/tests/end2end/data/hints/link_inject.html b/tests/end2end/data/hints/link_inject.html new file mode 100644 index 000000000..7ef352028 --- /dev/null +++ b/tests/end2end/data/hints/link_inject.html @@ -0,0 +1,19 @@ + + + + + A link to use hints on + + + + Follow me! + + diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature index 80348c908..ddf42132f 100644 --- a/tests/end2end/features/hints.feature +++ b/tests/end2end/features/hints.feature @@ -44,6 +44,13 @@ Feature: Using hints - data/hints/link_blank.html - data/hello.txt + # https://github.com/qutebrowser/qutebrowser/issues/7842 + @qtwebkit_skip + Scenario: Following a hint from a local file to a remote origin + When I open file://(testdata)/hints/link_inject.html?port=(port) + And I hint with args "links" and follow a + Then data/hello.txt should be loaded + Scenario: Following a hint to link with sub-element and force to open in current tab. When I open data/hints/link_span.html And I hint with args "links current" and follow a -- cgit v1.2.3-54-g00ecf From ff6668f2955ac8b3e5a6f02ca3e86c4cc3130b8e Mon Sep 17 00:00:00 2001 From: Philipp Albrecht Date: Mon, 28 Aug 2023 09:49:08 +0200 Subject: Generalize (testdata) substitution in end2end tests We replace the `(testdata)` placeholder with `testutils.abs_datapath()` in a few end2end tests. So far we only needed to replace `(testdata)` with an OS path (e.g. in `tests/end2end/features/spawn.feature`). By introducing `(testdata)` to an end2end test in `tests/end2end/features/hints.feature`, we required a new use case: replacing `(testdata)` as part of a valid file:// URI. ``` When I open file://(testdata)/some/file.txt ``` Replacing `(testdata)` in above BDD step with a plain OS path resulted in invalid URIs, e.g. for the path "C:\\Users" above BDD step results in this invalid URI: ``` When I open file://C:\Users/some/file.txt ``` We deal with this by first isolating the `(testdata)` substitution in a single place. Having `(testdata)` substitutions in a single place, we simply special-case the substitution of file:// paths, which will be part of a URI. Successful substitution for above BDD step looks like the following: ``` When I open file:///C:/Users/some/file.txt ``` --- tests/end2end/features/conftest.py | 6 +++--- tests/helpers/testutils.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index 62a81c5fc..089f0c42c 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -198,7 +198,7 @@ def open_path(quteproc, server, path): - With "... as a URL", it's opened according to new_instance_open_target. """ path = path.replace('(port)', str(server.port)) - path = path.replace('(testdata)', os.fspath(testutils.abs_datapath())) + path = testutils.substitute_testdata(path) new_tab = False new_bg_tab = False @@ -270,7 +270,7 @@ def run_command(quteproc, server, tmpdir, command): invalid = False command = command.replace('(port)', str(server.port)) - command = command.replace('(testdata)', str(testutils.abs_datapath())) + command = testutils.substitute_testdata(command) command = command.replace('(tmpdir)', str(tmpdir)) command = command.replace('(dirsep)', os.sep) command = command.replace('(echo-exe)', _get_echo_exe_path()) @@ -364,7 +364,7 @@ def hint(quteproc, args): @bdd.when(bdd.parsers.parse('I hint with args "{args}" and follow {letter}')) def hint_and_follow(quteproc, args, letter): - args = args.replace('(testdata)', str(testutils.abs_datapath())) + args = testutils.substitute_testdata(args) args = args.replace('(python-executable)', sys.executable) quteproc.send_cmd(':hint {}'.format(args)) quteproc.wait_for(message='hints: *') diff --git a/tests/helpers/testutils.py b/tests/helpers/testutils.py index a6022a6f9..d74c46fcb 100644 --- a/tests/helpers/testutils.py +++ b/tests/helpers/testutils.py @@ -196,6 +196,24 @@ def abs_datapath(): return path.resolve() +def substitute_testdata(path): + r"""Replace the (testdata) placeholder in path with `abs_datapath()`. + + If path is starting with file://, return path as an URI with file:// removed. This + is useful if path is going to be inserted into an URI: + + >>> path = substitute_testdata("C:\Users\qute") + >>> f"file://{path}/slug # results in valid URI + 'file:///C:/Users/qute/slug' + """ + if path.startswith('file://'): + testdata_path = abs_datapath().as_uri().replace('file://', '') + else: + testdata_path = str(abs_datapath()) + + return path.replace('(testdata)', testdata_path) + + @contextlib.contextmanager def nop_contextmanager(): yield -- cgit v1.2.3-54-g00ecf