mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWeb+WebContent+headless-browser: Support async text tests
Previously, we used `on_load_finish` to determine when the text test was completed. This method did not allow testing of async functions because there was no way to indicate that the runner should wait for the async call to end. This change introduces a function in the `internals` object that is intended to be called when the text test execution is completed. The text test runner will now ignore `on_load_finish` which means a test will timeout if this new function is never called. `test(f)` function in `include.js` has been modified to automatically terminate a test once `load` event is fired on `window`. new `asyncTest(f)` function has been introduces. `f` receives function that will terminate a test as a first argument. Every test is expected to call either `test()` or `asyncTest()` to complete. If not, it will remain hanging until a timeout occurs.
This commit is contained in:
parent
c74f7e5f2a
commit
6f8be44c0e
Notes:
sideshowbarker
2024-07-17 03:10:07 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/6f8be44c0e Pull-request: https://github.com/SerenityOS/serenity/pull/21073 Issue: https://github.com/SerenityOS/serenity/issues/19359
20 changed files with 98 additions and 40 deletions
|
@ -1 +1 @@
|
||||||
PASS
|
PASS
|
|
@ -1 +1 @@
|
||||||
PASS
|
PASS
|
|
@ -1 +1,8 @@
|
||||||
<head><link rel="stylesheet" href="style-sheet-with-byte-order-mark.css"></head><div class="pass">PASS
|
<head>
|
||||||
|
<link rel="stylesheet" href="style-sheet-with-byte-order-mark.css" />
|
||||||
|
</head>
|
||||||
|
<div class="pass">PASS</div>
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {});
|
||||||
|
</script>
|
||||||
|
|
|
@ -12,4 +12,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
|
||||||
function test(f) {
|
function test(f) {
|
||||||
document.addEventListener("DOMContentLoaded", f);
|
document.addEventListener("DOMContentLoaded", f);
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
internals.signalTextTestIsDone();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function asyncTest(f) {
|
||||||
|
const done = () => internals.signalTextTestIsDone();
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
f(done);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background: green;
|
background: green;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="include.js"></script>
|
<script src="include.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let link = document.createElement("link");
|
test(() => {
|
||||||
link.setAttribute("rel", "stylesheet");
|
let link = document.createElement("link");
|
||||||
link.setAttribute("href", "body-background-color-red.css");
|
link.setAttribute("rel", "stylesheet");
|
||||||
link.setAttribute("media", "print")
|
link.setAttribute("href", "body-background-color-red.css");
|
||||||
document.head.appendChild(link)
|
link.setAttribute("media", "print");
|
||||||
|
document.head.appendChild(link);
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function () {
|
||||||
println("document background: " + getComputedStyle(document.body).backgroundColor)
|
println("document background: " + getComputedStyle(document.body).backgroundColor);
|
||||||
}
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
<script src="include.js"></script>
|
<script src="include.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let link = document.createElement("link");
|
test(() => {
|
||||||
link.setAttribute("rel", "preload");
|
let link = document.createElement("link");
|
||||||
link.setAttribute("href", "valid.css");
|
link.setAttribute("rel", "preload");
|
||||||
link.setAttribute("as", "style");
|
link.setAttribute("href", "valid.css");
|
||||||
link.setAttribute("onload", "println('link element onload')");
|
link.setAttribute("as", "style");
|
||||||
document.head.appendChild(link);
|
link.setAttribute("onload", "println('link element onload')");
|
||||||
|
document.head.appendChild(link);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
<script src="include.js"></script>
|
<script src="include.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let goodLink = document.createElement("link");
|
test(() => {
|
||||||
goodLink.setAttribute("rel", "preload");
|
let goodLink = document.createElement("link");
|
||||||
goodLink.setAttribute("href", "valid.css");
|
goodLink.setAttribute("rel", "preload");
|
||||||
goodLink.setAttribute("as", "style");
|
goodLink.setAttribute("href", "valid.css");
|
||||||
goodLink.addEventListener("load", function() {
|
goodLink.setAttribute("as", "style");
|
||||||
println("Got load event");
|
goodLink.addEventListener("load", function () {
|
||||||
});
|
println("Got load event");
|
||||||
document.head.appendChild(goodLink);
|
});
|
||||||
|
document.head.appendChild(goodLink);
|
||||||
|
|
||||||
let badLink = document.createElement("link");
|
let badLink = document.createElement("link");
|
||||||
badLink.setAttribute("rel", "preload");
|
badLink.setAttribute("rel", "preload");
|
||||||
badLink.setAttribute("href", "this-file-does-not-exist-and-so-is-invalid.css");
|
badLink.setAttribute("href", "this-file-does-not-exist-and-so-is-invalid.css");
|
||||||
badLink.setAttribute("as", "style");
|
badLink.setAttribute("as", "style");
|
||||||
badLink.addEventListener("error", function() {
|
badLink.addEventListener("error", function () {
|
||||||
println("Got error event");
|
println("Got error event");
|
||||||
|
});
|
||||||
|
document.head.appendChild(badLink);
|
||||||
});
|
});
|
||||||
document.head.appendChild(badLink);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<a id="link-with-query" rel="search" href="https://serenityos.org/search?q=some:query"</a>
|
<a id="link-with-query" rel="search" href="https://serenityos.org/search?q=some:query"></a>
|
||||||
<script src="include.js"></script>
|
<script src="include.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.onload = function() {
|
asyncTest((done) => {
|
||||||
println(document.getElementById("link-with-query").search);
|
window.onload = function () {
|
||||||
}
|
println(document.getElementById("link-with-query").search);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<body></body>
|
<body></body>
|
||||||
|
<script src="include.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.body.appendChild(document.createTextNode("PASS"));
|
document.body.appendChild(document.createTextNode("PASS"));
|
||||||
|
test(() => {});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -28,6 +28,13 @@ void Internals::initialize(JS::Realm& realm)
|
||||||
Object::set_prototype(&Bindings::ensure_web_prototype<Bindings::InternalsPrototype>(realm, "Internals"));
|
Object::set_prototype(&Bindings::ensure_web_prototype<Bindings::InternalsPrototype>(realm, "Internals"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Internals::signal_text_test_is_done()
|
||||||
|
{
|
||||||
|
if (auto* page = global_object().browsing_context()->page()) {
|
||||||
|
page->client().page_did_finish_text_test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Internals::gc()
|
void Internals::gc()
|
||||||
{
|
{
|
||||||
vm().heap().collect_garbage();
|
vm().heap().collect_garbage();
|
||||||
|
|
|
@ -16,6 +16,8 @@ class Internals final : public Bindings::PlatformObject {
|
||||||
public:
|
public:
|
||||||
virtual ~Internals() override;
|
virtual ~Internals() override;
|
||||||
|
|
||||||
|
void signal_text_test_is_done();
|
||||||
|
|
||||||
void gc();
|
void gc();
|
||||||
JS::Object* hit_test(double x, double y);
|
JS::Object* hit_test(double x, double y);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[Exposed=Nobody] interface Internals {
|
[Exposed=Nobody] interface Internals {
|
||||||
|
|
||||||
|
undefined signalTextTestIsDone();
|
||||||
undefined gc();
|
undefined gc();
|
||||||
object hitTest(double x, double y);
|
object hitTest(double x, double y);
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,8 @@ public:
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable
|
// https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable
|
||||||
virtual void page_did_request_file_picker(WeakPtr<DOM::EventTarget>, [[maybe_unused]] bool multiple) {};
|
virtual void page_did_request_file_picker(WeakPtr<DOM::EventTarget>, [[maybe_unused]] bool multiple) {};
|
||||||
|
|
||||||
|
virtual void page_did_finish_text_test() {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~PageClient() = default;
|
virtual ~PageClient() = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -151,6 +151,7 @@ public:
|
||||||
Function<Gfx::IntRect()> on_minimize_window;
|
Function<Gfx::IntRect()> on_minimize_window;
|
||||||
Function<Gfx::IntRect()> on_fullscreen_window;
|
Function<Gfx::IntRect()> on_fullscreen_window;
|
||||||
Function<void(bool)> on_finish_handling_input_event;
|
Function<void(bool)> on_finish_handling_input_event;
|
||||||
|
Function<void()> on_text_test_finish;
|
||||||
|
|
||||||
virtual Gfx::IntRect viewport_rect() const = 0;
|
virtual Gfx::IntRect viewport_rect() const = 0;
|
||||||
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
|
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
|
||||||
|
|
|
@ -44,6 +44,12 @@ void WebContentClient::did_finish_loading(AK::URL const& url)
|
||||||
m_view.on_load_finish(url);
|
m_view.on_load_finish(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContentClient::did_finish_text_test()
|
||||||
|
{
|
||||||
|
if (m_view.on_text_test_finish)
|
||||||
|
m_view.on_text_test_finish();
|
||||||
|
}
|
||||||
|
|
||||||
void WebContentClient::did_request_navigate_back()
|
void WebContentClient::did_request_navigate_back()
|
||||||
{
|
{
|
||||||
if (m_view.on_navigate_back)
|
if (m_view.on_navigate_back)
|
||||||
|
|
|
@ -83,6 +83,7 @@ private:
|
||||||
virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window() override;
|
virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window() override;
|
||||||
virtual void did_request_file(DeprecatedString const& path, i32) override;
|
virtual void did_request_file(DeprecatedString const& path, i32) override;
|
||||||
virtual void did_finish_handling_input_event(bool event_was_accepted) override;
|
virtual void did_finish_handling_input_event(bool event_was_accepted) override;
|
||||||
|
virtual void did_finish_text_test() override;
|
||||||
|
|
||||||
ViewImplementation& m_view;
|
ViewImplementation& m_view;
|
||||||
};
|
};
|
||||||
|
|
|
@ -291,6 +291,11 @@ void PageHost::page_did_finish_loading(const URL& url)
|
||||||
m_client.async_did_finish_loading(url);
|
m_client.async_did_finish_loading(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PageHost::page_did_finish_text_test()
|
||||||
|
{
|
||||||
|
m_client.async_did_finish_text_test();
|
||||||
|
}
|
||||||
|
|
||||||
void PageHost::page_did_request_context_menu(Web::CSSPixelPoint content_position)
|
void PageHost::page_did_request_context_menu(Web::CSSPixelPoint content_position)
|
||||||
{
|
{
|
||||||
m_client.async_did_request_context_menu(page().css_to_device_point(content_position).to_type<int>());
|
m_client.async_did_request_context_menu(page().css_to_device_point(content_position).to_type<int>());
|
||||||
|
|
|
@ -112,6 +112,7 @@ private:
|
||||||
virtual void page_did_request_activate_tab() override;
|
virtual void page_did_request_activate_tab() override;
|
||||||
virtual void page_did_close_browsing_context(Web::HTML::BrowsingContext const&) override;
|
virtual void page_did_close_browsing_context(Web::HTML::BrowsingContext const&) override;
|
||||||
virtual void request_file(Web::FileRequest) override;
|
virtual void request_file(Web::FileRequest) override;
|
||||||
|
virtual void page_did_finish_text_test() override;
|
||||||
|
|
||||||
explicit PageHost(ConnectionFromClient&);
|
explicit PageHost(ConnectionFromClient&);
|
||||||
|
|
||||||
|
|
|
@ -64,4 +64,6 @@ endpoint WebContentClient
|
||||||
did_output_js_console_message(i32 message_index) =|
|
did_output_js_console_message(i32 message_index) =|
|
||||||
did_get_js_console_messages(i32 start_index, Vector<DeprecatedString> message_types, Vector<DeprecatedString> messages) =|
|
did_get_js_console_messages(i32 start_index, Vector<DeprecatedString> message_types, Vector<DeprecatedString> messages) =|
|
||||||
|
|
||||||
|
did_finish_text_test() =|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,8 +196,10 @@ static ErrorOr<TestResult> run_dump_test(HeadlessWebContentView& view, StringVie
|
||||||
result = builder.to_string().release_value_but_fixme_should_propagate_errors();
|
result = builder.to_string().release_value_but_fixme_should_propagate_errors();
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
};
|
};
|
||||||
|
view.on_text_test_finish = {};
|
||||||
} else if (mode == TestMode::Text) {
|
} else if (mode == TestMode::Text) {
|
||||||
view.on_load_finish = [&](auto const&) {
|
view.on_load_finish = {};
|
||||||
|
view.on_text_test_finish = [&]() {
|
||||||
result = view.dump_text().release_value_but_fixme_should_propagate_errors();
|
result = view.dump_text().release_value_but_fixme_should_propagate_errors();
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue