From acd604c5e1ab0579e9492cf8b88622e27f66bb62 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Sat, 14 Sep 2024 21:16:46 -0600 Subject: [PATCH] LibWeb: Add a test-only API to spoof the current URL and origin This is not that easy to use for test developers, as forgetting to set the url back to its original state after testing your specific API will cause future navigations to fail in inexplicable ways. --- .../Text/expected/all-window-properties.txt | 2 ++ Tests/LibWeb/Text/input/include.js | 22 ++++++++++++++++--- .../Libraries/LibWeb/Internals/Internals.cpp | 14 ++++++++++++ .../Libraries/LibWeb/Internals/Internals.h | 2 ++ .../Libraries/LibWeb/Internals/Internals.idl | 1 + 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index b377c043e14..d48e72a3729 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -383,12 +383,14 @@ XMLHttpRequest XMLHttpRequestEventTarget XMLHttpRequestUpload XMLSerializer +__finishTest __preventMultipleTestFunctions animationFrame asyncTest printElement println promiseTest +spoofCurrentURL test timeout webkitURL diff --git a/Tests/LibWeb/Text/input/include.js b/Tests/LibWeb/Text/input/include.js index 9bf5927da12..92a3820b0a4 100644 --- a/Tests/LibWeb/Text/input/include.js +++ b/Tests/LibWeb/Text/input/include.js @@ -1,5 +1,6 @@ var __outputElement = null; let __alreadyCalledTest = false; +let __originalURL = null; function __preventMultipleTestFunctions() { if (__alreadyCalledTest) { throw new Error("You must only call test() or asyncTest() once per page"); @@ -10,9 +11,24 @@ function __preventMultipleTestFunctions() { if (globalThis.internals === undefined) { internals = { signalTextTestIsDone: function () {}, + spoofCurrentURL: function (url) {}, }; } +function __finishTest() { + if (__originalURL) { + internals.spoofCurrentURL(__originalURL); + } + internals.signalTextTestIsDone(); +} + +function spoofCurrentURL(url) { + if (__originalURL === null) { + __originalURL = document.location.href; + } + internals.spoofCurrentURL(url); +} + function println(s) { __outputElement.appendChild(document.createTextNode(s + "\n")); } @@ -46,14 +62,14 @@ function test(f) { __preventMultipleTestFunctions(); document.addEventListener("DOMContentLoaded", f); window.addEventListener("load", () => { - internals.signalTextTestIsDone(); + __finishTest(); }); } function asyncTest(f) { const done = () => { __preventMultipleTestFunctions(); - internals.signalTextTestIsDone(); + __finishTest(); }; document.addEventListener("DOMContentLoaded", () => { f(done); @@ -64,7 +80,7 @@ function promiseTest(f) { document.addEventListener("DOMContentLoaded", () => { f().then(() => { __preventMultipleTestFunctions(); - internals.signalTextTestIsDone(); + __finishTest(); }); }); } diff --git a/Userland/Libraries/LibWeb/Internals/Internals.cpp b/Userland/Libraries/LibWeb/Internals/Internals.cpp index 9e7cc2fb5f3..a765a5bcf65 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.cpp +++ b/Userland/Libraries/LibWeb/Internals/Internals.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,19 @@ WebIDL::ExceptionOr Internals::dispatch_user_activated_event(DOM::EventTar return target.dispatch_event(event); } +void Internals::spoof_current_url(String const& url_string) +{ + auto url = DOMURL::parse(url_string); + + VERIFY(url.is_valid()); + + auto origin = DOMURL::url_origin(url); + + auto& window = internals_window(); + window.associated_document().set_url(url); + window.associated_document().set_origin(origin); +} + JS::NonnullGCPtr Internals::create_internal_animation_timeline() { auto& realm = this->realm(); diff --git a/Userland/Libraries/LibWeb/Internals/Internals.h b/Userland/Libraries/LibWeb/Internals/Internals.h index 03a338c4839..c814c1491ca 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.h +++ b/Userland/Libraries/LibWeb/Internals/Internals.h @@ -35,6 +35,8 @@ public: WebIDL::ExceptionOr dispatch_user_activated_event(DOM::EventTarget&, DOM::Event& event); + void spoof_current_url(String const& url); + JS::NonnullGCPtr create_internal_animation_timeline(); void simulate_drag_start(double x, double y, String const& name, String const& contents); diff --git a/Userland/Libraries/LibWeb/Internals/Internals.idl b/Userland/Libraries/LibWeb/Internals/Internals.idl index 959a34bf093..c851c7937d2 100644 --- a/Userland/Libraries/LibWeb/Internals/Internals.idl +++ b/Userland/Libraries/LibWeb/Internals/Internals.idl @@ -19,6 +19,7 @@ interface Internals { undefined wheel(double x, double y, double deltaX, double deltaY); boolean dispatchUserActivatedEvent(EventTarget target, Event event); + undefined spoofCurrentURL(USVString url); InternalAnimationTimeline createInternalAnimationTimeline();