mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
Tests: Wait for fonts before completing tests (WIP)
This commit is contained in:
parent
5f42f1318a
commit
4c1d4aa678
17 changed files with 112 additions and 19 deletions
|
@ -28,7 +28,7 @@ namespace Web::CSS {
|
|||
GC_DEFINE_ALLOCATOR(FontFaceSet);
|
||||
|
||||
// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-fontfaceset
|
||||
GC::Ref<FontFaceSet> FontFaceSet::construct_impl(JS::Realm& realm, Vector<GC::Root<FontFace>> const& initial_faces)
|
||||
GC::Ref<FontFaceSet> FontFaceSet::construct_impl(Web::Page& page, JS::Realm& realm, Vector<GC::Root<FontFace>> const& initial_faces)
|
||||
{
|
||||
auto ready_promise = WebIDL::create_promise(realm);
|
||||
auto set_entries = JS::Set::create(realm);
|
||||
|
@ -37,16 +37,17 @@ GC::Ref<FontFaceSet> FontFaceSet::construct_impl(JS::Realm& realm, Vector<GC::Ro
|
|||
for (auto const& face : initial_faces)
|
||||
set_entries->set_add(face);
|
||||
|
||||
return realm.create<FontFaceSet>(realm, ready_promise, set_entries);
|
||||
return realm.create<FontFaceSet>(page, realm, ready_promise, set_entries);
|
||||
}
|
||||
|
||||
GC::Ref<FontFaceSet> FontFaceSet::create(JS::Realm& realm)
|
||||
GC::Ref<FontFaceSet> FontFaceSet::create(Web::Page& page, JS::Realm& realm)
|
||||
{
|
||||
return construct_impl(realm, {});
|
||||
return construct_impl(page, realm, {});
|
||||
}
|
||||
|
||||
FontFaceSet::FontFaceSet(JS::Realm& realm, GC::Ref<WebIDL::Promise> ready_promise, GC::Ref<JS::Set> set_entries)
|
||||
FontFaceSet::FontFaceSet(Web::Page& page, JS::Realm& realm, GC::Ref<WebIDL::Promise> ready_promise, GC::Ref<JS::Set> set_entries)
|
||||
: DOM::EventTarget(realm)
|
||||
, m_page(page)
|
||||
, m_set_entries(set_entries)
|
||||
, m_ready_promise(ready_promise)
|
||||
, m_status(Bindings::FontFaceSetLoadStatus::Loaded)
|
||||
|
@ -63,6 +64,7 @@ void FontFaceSet::initialize(JS::Realm& realm)
|
|||
void FontFaceSet::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_page);
|
||||
visitor.visit(m_set_entries);
|
||||
visitor.visit(m_ready_promise);
|
||||
visitor.visit(m_loading_fonts);
|
||||
|
@ -289,7 +291,10 @@ GC::Ref<WebIDL::Promise> FontFaceSet::ready() const
|
|||
|
||||
void FontFaceSet::resolve_ready_promise()
|
||||
{
|
||||
dbgln("FontFaceSet::resolve_ready_promise(): {}", m_page->url());
|
||||
WebIDL::resolve_promise(realm(), m_ready_promise);
|
||||
|
||||
m_page->client().page_did_finish_loading_page_and_fonts(m_page->url());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/CSS/FontFace.h>
|
||||
#include <LibWeb/DOM/EventTarget.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -21,8 +23,8 @@ class FontFaceSet final : public DOM::EventTarget {
|
|||
GC_DECLARE_ALLOCATOR(FontFaceSet);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static GC::Ref<FontFaceSet> construct_impl(JS::Realm&, Vector<GC::Root<FontFace>> const& initial_faces);
|
||||
[[nodiscard]] static GC::Ref<FontFaceSet> create(JS::Realm&);
|
||||
[[nodiscard]] static GC::Ref<FontFaceSet> construct_impl(Web::Page&, JS::Realm&, Vector<GC::Root<FontFace>> const& initial_faces);
|
||||
[[nodiscard]] static GC::Ref<FontFaceSet> create(Web::Page&, JS::Realm&);
|
||||
virtual ~FontFaceSet() override = default;
|
||||
|
||||
GC::Ref<JS::Set> set_entries() const { return m_set_entries; }
|
||||
|
@ -46,11 +48,12 @@ public:
|
|||
void resolve_ready_promise();
|
||||
|
||||
private:
|
||||
FontFaceSet(JS::Realm&, GC::Ref<WebIDL::Promise> ready_promise, GC::Ref<JS::Set> set_entries);
|
||||
FontFaceSet(Web::Page&, JS::Realm&, GC::Ref<WebIDL::Promise> ready_promise, GC::Ref<JS::Set> set_entries);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
GC::Ref<Web::Page> m_page;
|
||||
GC::Ref<JS::Set> m_set_entries;
|
||||
GC::Ref<WebIDL::Promise> m_ready_promise; // [[ReadyPromise]]
|
||||
|
||||
|
|
|
@ -1606,7 +1606,7 @@ GC::Ref<HTML::HTMLAllCollection> Document::all()
|
|||
GC::Ref<CSS::FontFaceSet> Document::fonts()
|
||||
{
|
||||
if (!m_fonts)
|
||||
m_fonts = CSS::FontFaceSet::create(realm());
|
||||
m_fonts = CSS::FontFaceSet::create(page(), realm());
|
||||
return *m_fonts;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE)
|
|||
GC::Ref<CSS::FontFaceSet> WorkerGlobalScope::fonts()
|
||||
{
|
||||
if (!m_fonts)
|
||||
m_fonts = CSS::FontFaceSet::create(realm());
|
||||
m_fonts = CSS::FontFaceSet::create(*page(), realm());
|
||||
return *m_fonts;
|
||||
}
|
||||
|
||||
|
|
|
@ -578,6 +578,14 @@ Vector<GC::Root<DOM::Document>> Page::documents_in_active_window() const
|
|||
return documents;
|
||||
}
|
||||
|
||||
URL::URL Page::url() const
|
||||
{
|
||||
if (!top_level_traversable_is_initialized())
|
||||
return {};
|
||||
|
||||
return top_level_traversable()->active_document()->url();
|
||||
}
|
||||
|
||||
void Page::clear_selection()
|
||||
{
|
||||
for (auto const& document : documents_in_active_window()) {
|
||||
|
|
|
@ -212,6 +212,8 @@ public:
|
|||
FindInPageResult find_in_page_previous_match();
|
||||
Optional<FindInPageQuery> last_find_in_page_query() const { return m_last_find_in_page_query; }
|
||||
|
||||
URL::URL url() const;
|
||||
|
||||
private:
|
||||
explicit Page(GC::Ref<PageClient>);
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
@ -368,6 +370,7 @@ public:
|
|||
virtual void page_did_request_select_dropdown([[maybe_unused]] Web::CSSPixelPoint content_position, [[maybe_unused]] Web::CSSPixels minimum_width, [[maybe_unused]] Vector<Web::HTML::SelectItem> items) { }
|
||||
|
||||
virtual void page_did_finish_text_test([[maybe_unused]] String const& text) { }
|
||||
virtual void page_did_finish_loading_page_and_fonts([[maybe_unused]] URL::URL const& url) { }
|
||||
|
||||
virtual void page_did_change_theme_color(Gfx::Color) { }
|
||||
|
||||
|
|
|
@ -231,11 +231,14 @@ public:
|
|||
Function<void(String const&)> on_inspector_executed_console_script;
|
||||
Function<void(String const&)> on_inspector_exported_inspector_html;
|
||||
Function<void()> on_web_content_crashed;
|
||||
Function<void(URL::URL const&)> on_loading_page_and_fonts_finish;
|
||||
|
||||
virtual Web::DevicePixelSize viewport_size() const = 0;
|
||||
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
|
||||
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const = 0;
|
||||
|
||||
u64 page_id() const;
|
||||
|
||||
protected:
|
||||
static constexpr auto ZOOM_MIN_LEVEL = 0.3f;
|
||||
static constexpr auto ZOOM_MAX_LEVEL = 5.0f;
|
||||
|
@ -245,7 +248,6 @@ protected:
|
|||
|
||||
WebContentClient& client();
|
||||
WebContentClient const& client() const;
|
||||
u64 page_id() const;
|
||||
virtual void update_zoom() = 0;
|
||||
|
||||
void handle_resize();
|
||||
|
|
|
@ -93,6 +93,15 @@ void WebContentClient::did_finish_text_test(u64 page_id, String const& text)
|
|||
}
|
||||
}
|
||||
|
||||
void WebContentClient::did_finish_loading_page_and_fonts(u64 page_id, URL::URL const& url)
|
||||
{
|
||||
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||
if (view->on_loading_page_and_fonts_finish)
|
||||
view->on_loading_page_and_fonts_finish(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WebContentClient::did_find_in_page(u64 page_id, size_t current_match_index, Optional<size_t> const& total_match_count)
|
||||
{
|
||||
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
virtual void did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) override;
|
||||
virtual void did_finish_handling_input_event(u64 page_id, Web::EventResult event_result) override;
|
||||
virtual void did_finish_text_test(u64 page_id, String const& text) override;
|
||||
virtual void did_finish_loading_page_and_fonts(u64 page_id, URL::URL const& url) override;
|
||||
virtual void did_find_in_page(u64 page_id, size_t current_match_index, Optional<size_t> const& total_match_count) override;
|
||||
virtual void did_change_theme_color(u64 page_id, Gfx::Color color) override;
|
||||
virtual void did_insert_clipboard_entry(u64 page_id, String const& data, String const& presentation_style, String const& mime_type) override;
|
||||
|
|
|
@ -140,6 +140,7 @@ void ConnectionFromClient::update_screen_rects(u64 page_id, Vector<Web::DevicePi
|
|||
|
||||
void ConnectionFromClient::load_url(u64 page_id, const URL::URL& url)
|
||||
{
|
||||
dbgln("ConnectionFromClient::load_url({}, {})", page_id, url);
|
||||
auto page = this->page(page_id);
|
||||
if (!page.has_value())
|
||||
return;
|
||||
|
|
|
@ -355,6 +355,12 @@ void PageClient::page_did_finish_text_test(String const& text)
|
|||
client().async_did_finish_text_test(m_id, text);
|
||||
}
|
||||
|
||||
void PageClient::page_did_finish_loading_page_and_fonts(URL::URL const& url)
|
||||
{
|
||||
dbgln("PageClient::page_did_finish_loading_page_and_fonts: {}", url);
|
||||
client().async_did_finish_loading_page_and_fonts(m_id, url);
|
||||
}
|
||||
|
||||
void PageClient::page_did_request_context_menu(Web::CSSPixelPoint content_position)
|
||||
{
|
||||
client().async_did_request_context_menu(m_id, page().css_to_device_point(content_position).to_type<int>());
|
||||
|
|
|
@ -155,6 +155,7 @@ private:
|
|||
virtual void page_did_request_file_picker(Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles) override;
|
||||
virtual void page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) override;
|
||||
virtual void page_did_finish_text_test(String const& text) override;
|
||||
virtual void page_did_finish_loading_page_and_fonts(URL::URL const& url) override;
|
||||
virtual void page_did_change_theme_color(Gfx::Color color) override;
|
||||
virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override;
|
||||
virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override;
|
||||
|
|
|
@ -95,7 +95,7 @@ endpoint WebContentClient
|
|||
did_get_js_console_messages(u64 page_id, i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages) =|
|
||||
|
||||
did_finish_text_test(u64 page_id, String text) =|
|
||||
|
||||
did_finish_loading_page_and_fonts(u64 page_id, URL::URL url) =|
|
||||
did_find_in_page(u64 page_id, size_t current_match_index, Optional<size_t> total_match_count) =|
|
||||
|
||||
request_worker_agent(u64 page_id) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/javascript">
|
||||
window.onload = (event) => {
|
||||
console.log('expectation onload', event.target.location.href);
|
||||
}
|
||||
document.fonts.ready.then(() => {
|
||||
internals.finishLoading();
|
||||
console.log('exceptation document.fonts.ready');
|
||||
})
|
||||
internals.disableAutomaticPageFinish();
|
||||
// internals.disableAutomaticPageFinish();
|
||||
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-numeric", true, false));
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/javascript">
|
||||
window.onload = (event) => {
|
||||
console.log('actual onload', event.target.location.href);
|
||||
}
|
||||
document.fonts.ready.then(() => {
|
||||
internals.finishLoading();
|
||||
console.log('actual document.fonts.ready');
|
||||
})
|
||||
internals.disableAutomaticPageFinish();
|
||||
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-numeric", false, false));
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -102,6 +102,7 @@ static ErrorOr<void> collect_ref_tests(Vector<Test>& tests, StringView path, Str
|
|||
static void clear_test_callbacks(HeadlessWebView& view)
|
||||
{
|
||||
view.on_load_finish = {};
|
||||
view.on_loading_page_and_fonts_finish = {};
|
||||
view.on_text_test_finish = {};
|
||||
view.on_web_content_crashed = {};
|
||||
}
|
||||
|
@ -240,6 +241,7 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url,
|
|||
{
|
||||
auto timer = Core::Timer::create_single_shot(timeout_in_milliseconds, [&view, &test]() {
|
||||
view.on_load_finish = {};
|
||||
view.on_loading_page_and_fonts_finish = {};
|
||||
view.on_text_test_finish = {};
|
||||
|
||||
view.on_test_complete({ test, TestResult::Timeout });
|
||||
|
@ -288,20 +290,63 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url,
|
|||
view.on_test_complete({ test, TestResult::Crashed });
|
||||
};
|
||||
|
||||
view.on_load_finish = [&view, &test, on_test_complete = move(on_test_complete)](auto const&) {
|
||||
view.on_load_finish = [&view, &test, &on_test_complete](auto const&) {
|
||||
dbgln("on loading page: page={}, url={}", test.did_load_page, view.url().serialize_path());
|
||||
test.did_load_page = true;
|
||||
if (!test.did_load_fonts)
|
||||
return;
|
||||
//dbgln("DONE on loading page: fonts={}, {}", test.did_load_fonts, view.url());
|
||||
test.did_load_page = true;
|
||||
if (test.actual_screenshot) {
|
||||
view.take_screenshot()->when_resolved([&test, on_test_complete = move(on_test_complete)](RefPtr<Gfx::Bitmap> screenshot) {
|
||||
//dbgln("Take expectation screenshot <- this happens too early");
|
||||
view.take_screenshot()->when_resolved([&test, &on_test_complete](RefPtr<Gfx::Bitmap> screenshot) {
|
||||
test.expectation_screenshot = move(screenshot);
|
||||
test.did_load_fonts = false;
|
||||
test.did_load_page = false;
|
||||
on_test_complete();
|
||||
});
|
||||
} else {
|
||||
//dbgln("\nTake actual screenshot");
|
||||
view.take_screenshot()->when_resolved([&view, &test](RefPtr<Gfx::Bitmap> screenshot) {
|
||||
test.actual_screenshot = move(screenshot);
|
||||
test.did_load_fonts = false;
|
||||
test.did_load_page = false;
|
||||
test.loading_reference_page = true;
|
||||
dbgln("load-reference-page");
|
||||
view.debug_request("load-reference-page");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: rename to on_fonts_ready
|
||||
view.on_loading_page_and_fonts_finish = [&view, &test, &on_test_complete](auto const&) {
|
||||
dbgln("on fonts finish: load={}, url={}", test.did_load_fonts, view.url().serialize_path());
|
||||
// This callback will be called multiple times, one for normal page load and one for the reference page load.
|
||||
// We only want to take the screenshot once the reference page has loaded its fonts
|
||||
if (test.loading_reference_page && !view.url().serialize_path().ends_with_bytes("-ref.html"sv))
|
||||
return;
|
||||
if (test.did_load_fonts)
|
||||
return;
|
||||
test.did_load_fonts = true;
|
||||
if (!test.did_load_page)
|
||||
return;
|
||||
if (test.actual_screenshot) {
|
||||
view.take_screenshot()->when_resolved([&test, &on_test_complete](RefPtr<Gfx::Bitmap> screenshot) {
|
||||
test.expectation_screenshot = move(screenshot);
|
||||
on_test_complete();
|
||||
});
|
||||
} else {
|
||||
dbgln("\nTake actual screenshot");
|
||||
view.take_screenshot()->when_resolved([&view, &test](RefPtr<Gfx::Bitmap> screenshot) {
|
||||
test.actual_screenshot = move(screenshot);
|
||||
test.did_load_fonts = false;
|
||||
test.did_load_page = false;
|
||||
test.loading_reference_page = true;
|
||||
dbgln("load-reference-page");
|
||||
view.debug_request("load-reference-page");
|
||||
});
|
||||
}
|
||||
};
|
||||
view.on_text_test_finish = [&](auto const&) {
|
||||
dbgln("Unexpected text test finished during ref test for {}", url);
|
||||
};
|
||||
|
|
|
@ -66,9 +66,13 @@ struct Test {
|
|||
String text {};
|
||||
bool did_finish_test { false };
|
||||
bool did_finish_loading { false };
|
||||
|
||||
bool did_load_page { false };
|
||||
bool did_load_fonts { false };
|
||||
bool loading_reference_page { false };
|
||||
RefPtr<Gfx::Bitmap> actual_screenshot {};
|
||||
RefPtr<Gfx::Bitmap> expectation_screenshot {};
|
||||
|
||||
bool is_ref() const { return mode == TestMode::Ref; };
|
||||
};
|
||||
|
||||
struct TestCompletion {
|
||||
|
|
Loading…
Reference in a new issue