mod common;
use std::rc::Rc;
use servo::{JSValue, WebViewBuilder};
use servo_config::prefs::Preferences;
use url::Url;
use crate::common::{
ServoTest, WebViewDelegateImpl, evaluate_javascript,
show_webview_and_wait_for_rendering_to_be_ready,
};
#[test]
fn test_paint_timing_js_api() {
let servo_test = ServoTest::new();
let delegate = Rc::new(WebViewDelegateImpl::default());
let webview = WebViewBuilder::new(servo_test.servo(), servo_test.rendering_context.clone())
.delegate(delegate.clone())
.url(
Url::parse(
"data:text/html,<!DOCTYPE html>\
<a href=\"https://servo.org\"><div style=\"width: 50px; height: 50px;\">Link</div></a> \
<div><img src=\"data:image/svg+xml,<svg width='50' height='50'><circle cx='25' cy='25' r='20' fill='green'/></svg>\"\
style=\"width: 50px; height: 50px;\"></div>"
)
.unwrap(),
)
.build();
show_webview_and_wait_for_rendering_to_be_ready(&servo_test, &webview, &delegate);
let paint_entries = evaluate_javascript(
&servo_test,
webview.clone(),
"performance.getEntriesByType('paint').length;",
);
assert_eq!(paint_entries, Ok(JSValue::Number(2.0)));
let first_paint = evaluate_javascript(
&servo_test,
webview.clone(),
"performance.getEntriesByName('first-paint')[0].toJSON();",
);
if let Ok(JSValue::Object(obj)) = first_paint {
assert_eq!(
obj.get("name"),
Some(JSValue::String("first-paint".to_string())).as_ref()
);
assert_eq!(
obj.get("entryType"),
Some(JSValue::String("paint".to_string())).as_ref()
);
assert!(obj.get("startTime").is_some());
assert_eq!(obj.get("duration"), Some(JSValue::Number(0.0)).as_ref());
} else {
panic!("first-paint entry is not an object");
}
let first_contentful_paint = evaluate_javascript(
&servo_test,
webview.clone(),
"performance.getEntriesByName('first-contentful-paint')[0].toJSON();",
);
if let Ok(JSValue::Object(obj)) = first_contentful_paint {
assert_eq!(
obj.get("name"),
Some(JSValue::String("first-contentful-paint".to_string())).as_ref()
);
assert_eq!(
obj.get("entryType"),
Some(JSValue::String("paint".to_string())).as_ref()
);
assert!(obj.get("startTime").is_some());
assert_eq!(obj.get("duration"), Some(JSValue::Number(0.0)).as_ref());
} else {
panic!("first-contentful-paint entry is not an object");
}
}
#[allow(dead_code)]
fn verify_first_paint(servo_test: &ServoTest, data_url: &str, expected_fp: i32) {
let delegate = Rc::new(WebViewDelegateImpl::default());
let webview = WebViewBuilder::new(servo_test.servo(), servo_test.rendering_context.clone())
.delegate(delegate.clone())
.url(Url::parse(data_url).unwrap())
.build();
let _ = evaluate_javascript(
&servo_test,
webview.clone(),
"await new Promise(requestAnimationFrame);",
);
let paint_entries = evaluate_javascript(
&servo_test,
webview.clone(),
"performance.getEntriesByType('paint').length;",
);
assert_eq!(paint_entries, Ok(JSValue::Number(expected_fp as f64)));
if expected_fp > 0 {
let first_paint = evaluate_javascript(
&servo_test,
webview.clone(),
"performance.getEntriesByName('first-paint')[0].toJSON();",
);
if let Ok(JSValue::Object(obj)) = first_paint {
assert_eq!(
obj.get("name"),
Some(JSValue::String("first-paint".to_string())).as_ref()
);
} else {
panic!("first-paint entry is not an object");
}
}
}
#[test]
fn test_default_pref_with_unset_background() {
let servo_test = ServoTest::new();
verify_first_paint(&servo_test, "data:text/html, <html>", 0);
}
#[test]
fn test_non_default_pref_with_unset_background() {
let servo_test = ServoTest::new_with_builder(|builder| {
let mut preferences = Preferences::default();
preferences.shell_background_color_rgba = [0.5, 0.5, 0.5, 1.0]; builder.preferences(preferences)
});
verify_first_paint(&servo_test, "data:text/html, <html>", 0);
}
#[test]
fn test_default_pref_with_transparent_background() {
let servo_test = ServoTest::new();
verify_first_paint(
&servo_test,
"data:text/html, <html style='background: transparent;'>",
0,
);
}
#[test]
fn test_non_default_pref_with_transparent_background() {
let servo_test = ServoTest::new_with_builder(|builder| {
let mut preferences = Preferences::default();
preferences.shell_background_color_rgba = [0.5, 0.5, 0.5, 1.0]; builder.preferences(preferences)
});
verify_first_paint(
&servo_test,
"data:text/html, <html style='background: transparent;'>",
0,
);
}
#[test]
fn test_default_pref_with_background() {
let servo_test = ServoTest::new();
verify_first_paint(
&servo_test,
"data:text/html, <html style='background: red;'>",
1,
);
}
#[test]
fn test_non_default_pref_with_background() {
let servo_test = ServoTest::new_with_builder(|builder| {
let mut preferences = Preferences::default();
preferences.shell_background_color_rgba = [0.5, 0.5, 0.5, 1.0]; builder.preferences(preferences)
});
verify_first_paint(
&servo_test,
"data:text/html, <html style='background: green;'>",
1,
);
}
#[test]
fn test_non_default_pref_with_same_background() {
let servo_test = ServoTest::new_with_builder(|builder| {
let mut preferences = Preferences::default();
preferences.shell_background_color_rgba = [0.0, 0.0, 1.0, 1.0]; builder.preferences(preferences)
});
verify_first_paint(
&servo_test,
"data:text/html, <html style='background: blue;'>",
0,
);
}