#![cfg(all(feature = "servo-engine", target_os = "macos"))] use std::{error::Error, thread, time::Duration}; use ely_domain::{ProfileId, TabId, UrlText}; use ely_servo_host::{ NavigationRequest, ServoHost, ServoSurfaceSize, SoftwareServoHost, WebViewState, }; const EXPECTED_PASS_COLOR: [u8; 3] = [31, 143, 76]; #[test] fn macos_fallback_preserves_css_family_style_and_language() -> Result<(), Box> { let mut host = SoftwareServoHost::new(ServoSurfaceSize::new(320, 240))?; let tab_id = TabId::new(); let profile_id = ProfileId::new(); let webview_id = host.create_webview(tab_id.clone(), profile_id)?; host.navigate(NavigationRequest { webview_id: webview_id.clone(), tab_id, url: UrlText::parse(font_probe_url())?, })?; for _ in 0..5_000 { host.tick(); let snapshot = host.snapshot(&webview_id)?; if snapshot.has_pending_frame() { host.paint(&webview_id)?; } let snapshot = host.snapshot(&webview_id)?; if snapshot.state() == &WebViewState::Complete && host .last_rendered_frame() .is_ok_and(|frame| center_pixel_rgb(&frame) == EXPECTED_PASS_COLOR) { return Ok(()); } thread::sleep(Duration::from_millis(2)); } let actual = host.last_rendered_frame().map(|frame| center_pixel_rgb(&frame)); let title = host.snapshot(&webview_id)?.title().map(str::to_owned); Err(format!( "macOS font fallback probe failed with center pixel {actual:?} and title {title:?}" ) .into()) } fn font_probe_url() -> String { let html = r#" starting"#; format!("data:text/html,{}", percent_encode(html)) } fn percent_encode(value: &str) -> String { value .bytes() .map(|byte| match byte { b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b'.' | b'~' => { (byte as char).to_string() } _ => format!("%{byte:02X}"), }) .collect() } fn center_pixel_rgb(frame: &ely_servo_host::RenderedFrame) -> [u8; 3] { let index = (((frame.height() / 2) * frame.width() + frame.width() / 2) * 4) as usize; let rgba = &frame.rgba_bytes()[index..index + 4]; [rgba[0], rgba[1], rgba[2]] }