test: isolate navigation loads and deterministic font and HTTP fixtures

This commit is contained in:
llk
2026-10-11 08:14:05 +08:00
committed by Donough Liu
parent 5fc03c58f4
commit bd246f6b92
4 changed files with 74 additions and 20 deletions
@@ -2876,15 +2876,30 @@ async fn named_popup_references_from_sibling_pages_share_the_close_lifetime() {
}
async fn navigate_dynamic_page_and_wait_for_load(page: &mut TestCdpSocket, id: u64, url: &str) {
send_cdp_command_without_wait(page, id, "Page.navigate", None, json!({"url": url})).await;
let mut responded = false;
let mut loaded = false;
recv_until_match(page, |message| {
responded |= message["id"] == id;
loaded |= message["method"] == "Page.loadEventFired";
responded && loaded
})
send_cdp_command(
page,
id,
"Page.setLifecycleEventsEnabled",
None,
json!({"enabled": true}),
)
.await;
let navigation = send_cdp_command(page, id, "Page.navigate", None, json!({"url": url})).await;
let response = response_by_id(&navigation, id);
assert!(response["error"].is_null(), "{response}");
let loader = response["result"]["loaderId"]
.as_str()
.expect("dynamic navigation loader");
// A popup's previous load may still be queued. Only the requested
// navigation's loader can establish that its document has finished.
let loaded = |message: &serde_json::Value| {
message["method"] == "Page.lifecycleEvent"
&& message["params"]["loaderId"] == loader
&& message["params"]["name"] == "load"
};
if !navigation.iter().any(loaded) {
recv_until_match(page, loaded).await;
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -628,6 +628,22 @@ impl JsContextHost {
)
}
#[cfg(test)]
pub(crate) fn register_layout_test_font(&self, family: &str, bytes: Vec<u8>) {
let document = self.document_handle();
self.document_layout_state
.borrow_mut()
.with_services_for_document(document, document, |services, _| {
services
.register_web_font(moli_layout::WebFontRegistration::new(
"layout-test-font",
moli_layout::WebFontFace::new(family),
bytes,
))
.expect("valid layout test font");
});
}
#[cfg(test)]
pub(crate) fn layout_snapshot_cache_observability_for_test(
&self,
@@ -1339,7 +1339,7 @@ fn inline_end_border_preserves_tall_atomic_content() {
}
}
// Geometry measured in Chromium 145.0.7632.116, before and after publication.
// Geometry uses the bundled Ahem face, independently checked in Chromium.
#[test]
fn empty_inline_alignment_resolves_placement_separately_from_line_contribution() {
let cases = [
@@ -1389,14 +1389,14 @@ fn empty_inline_alignment_resolves_placement_separately_from_line_contribution()
(
"text_top",
"<span id=b style=vertical-align:text-top></span>",
[46.0, -46.0],
[91.0, 11.0],
[40.0, -40.0],
[95.0, 15.0],
),
(
"text_bottom",
"<span id=b style=vertical-align:text-bottom></span>",
[32.0, 12.0],
[91.0, -11.0],
[30.0, 10.0],
[95.0, -15.0],
),
(
"top",
@@ -1421,9 +1421,14 @@ fn empty_inline_alignment_resolves_placement_separately_from_line_contribution()
] {
for (id, content, quirks_geometry, standards_geometry) in cases {
let markup = format!(
r#"{doctype}<style>.line{{font:50px/80px monospace;width:300px}}.atom{{display:inline-block;width:10px;height:20px}}em,i{{font-style:normal}}</style><div id=line class=line><span id=a></span>{content}<i class=atom></i></div>"#
r#"{doctype}<style>.line{{font:50px/80px MoliAhem;width:300px}}.atom{{display:inline-block;width:10px;height:20px}}em,i{{font-style:normal}}</style><div id=line class=line><span id=a></span>{content}<i class=atom></i></div>"#
);
let mut vm = new_parsed_test_vm("https://inline-alignment.test/", &markup);
vm._context_host.borrow().register_layout_test_font(
"MoliAhem",
include_bytes!("../../../../../../../moli-layout/tests/fixtures/moli-ahem.ttf")
.to_vec(),
);
let query = "JSON.stringify([line.getBoundingClientRect().height,b.getBoundingClientRect().top-a.getBoundingClientRect().top])";
let expected = if quirks {
quirks_geometry
@@ -1471,15 +1476,22 @@ fn forced_breaks_restore_ancestor_bidi_before_closing_inner_inline_boxes() {
let whitespace = if preserved { ";white-space:pre" } else { "" };
let newline = if preserved { "\n" } else { "<br>" };
let markup = format!(
r#"{doctype}<style>#line{{font:20px/30px monospace}}</style><div id=line><span {outer}><span style="font:30px/60px monospace{whitespace}">x{newline}</span><span id=second>x</span></span></div>"#
r#"{doctype}<style>#line{{font:20px/30px MoliAhem}}</style><div id=line><span {outer}><span style="font:30px/60px MoliAhem{whitespace}">x{newline}</span><span id=second>x</span></span></div>"#
);
let mut vm =
new_parsed_test_vm("https://inline-bidi-forced-break.test/", &markup);
vm._context_host.borrow().register_layout_test_font(
"MoliAhem",
include_bytes!(
"../../../../../../../moli-layout/tests/fixtures/moli-ahem.ttf"
)
.to_vec(),
);
let query = "JSON.stringify([line.getBoundingClientRect().height,second.getBoundingClientRect().top-line.getBoundingClientRect().top])";
let expected = if quirks || bidi == "normal" {
[90.0, 63.0]
[90.0, 65.0]
} else {
[120.0, 81.0]
[120.0, 83.0]
};
let first = vm.eval(query).unwrap();
assert_eq!(
+14 -3
View File
@@ -2,8 +2,8 @@ use anyhow::Result;
use axum::{
Router,
extract::Path,
http::StatusCode,
response::{Html, IntoResponse, Redirect},
http::{HeaderValue, StatusCode, header},
response::{Html, IntoResponse, Redirect, Response},
routing::get,
};
use base64::{Engine as _, engine::general_purpose::STANDARD};
@@ -99,7 +99,18 @@ impl HttpFailureFixture {
)
.into_response()
}),
);
)
.layer(axum::middleware::map_response(
|mut response: Response| async move {
// Separate requests must have identical fixture headers when
// the test compares their complete selected-format output.
response.headers_mut().insert(
header::DATE,
HeaderValue::from_static("Thu, 01 Jan 1970 00:00:00 GMT"),
);
response
},
));
let listener = TcpListener::bind("127.0.0.1:0").await?;
let base_url = format!("http://{}", listener.local_addr()?);
let task = tokio::spawn(async move {