Repository: servo/servo
File: components/servo/tests/largest_contentful_paint.rs (Rust)

Code before:
use crate::common::{
    ServoTest, WebViewDelegateImpl, click_at_point, evaluate_javascript,
    show_webview_and_wait_for_rendering_to_be_ready,
};

// Page with a single 50x50 red square image using a data URL.
static URL: &str = "data:text/html,<!DOCTYPE html>\
<div><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEklEQVQIW2P8z8AARAwMjDAGACwBA/+8RVWvAAAAAElFTkSuQmCC\"\
style=\"width: 50px; height: 50px;\"></div>";

#[test]
fn test_largest_contentful_paint_js_api() {
    let servo_test = ServoTest::new_with_builder(|builder| {
        let mut preferences = Preferences::default();
        preferences.largest_contentful_paint_enabled = true;
        builder.preferences(preferences)
    });

    let delegate = Rc::new(WebViewDelegateImpl::default());
    let webview = WebViewBuilder::new(servo_test.servo(), servo_test.rendering_context.clone())
        .delegate(delegate.clone())
        .url(Url::parse(URL).unwrap())
        .build();

    // Wait for the page to load and render before evaluating the LCP to ensure we don't miss LCP candidate.
    show_webview_and_wait_for_rendering_to_be_ready(&servo_test, &webview, &delegate);

    let lcp_script = "(async () => {
        window.lcp = await new Promise(resolve => {
            (new PerformanceObserver(entryList => {
                resolve(entryList.getEntries()[0]);
            }))
            .observe({type: 'largest-contentful-paint', buffered: true});
        })
    })();";

    if let Err(err) = evaluate_javascript(&servo_test, webview.clone(), lcp_script) {
        panic!("Failed to evaluate LCP setup script: {:?}", err);
    }

    // Read from a global variable used to store the result since evaluate_javascript doesn't handle Promises
    let lcp = evaluate_javascript(&servo_test, webview.clone(), "window.lcp.toJSON();");

    if let Ok(JSValue::Object(obj)) = lcp {
        assert_eq!(obj.get("name"), Some(JSValue::String("".into())).as_ref());
        assert_eq!(obj.get("duration"), Some(JSValue::Number(0.0)).as_ref());
        assert_eq!(
            obj.get("entryType"),
            Some(JSValue::String("largest-contentful-paint".into())).as_ref()
        );
        assert_eq!(obj.get("size"), Some(JSValue::Number(2500.0)).as_ref());

Review comment (suggestion):
Indeed. This is meant to be the first thing run before interacting with the `WebView`. Sorry that this was not caught in earlier reviews.

Code after:
use crate::common::{
    ServoTest, WebViewDelegateImpl, click_at_point, evaluate_javascript,
    show_webview_and_wait_for_rendering_to_be_ready,
};

// Page with a single 50x50 red square image using a data URL.
static DATA_URL_FOR_PAGE_WITH_SINGLE_RED_SQUARE: &str = "data:text/html,<!DOCTYPE html>\
<div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEklEQVQIW2P8z8AARAwMjDAGACwBA/+8RVWvAAAAAElFTkSuQmCC'\
style='width: 50px; height: 50px;'></div>";

#[test]
fn test_largest_contentful_paint_js_api() {
    let servo_test = ServoTest::new_with_builder(|builder| {
        let mut preferences = Preferences::default();
        preferences.largest_contentful_paint_enabled = true;
        builder.preferences(preferences)
    });

    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_FOR_PAGE_WITH_SINGLE_RED_SQUARE).unwrap())
        .build();

    // Wait for the page to load and render before evaluating the LCP to ensure we don't miss LCP candidate.
    show_webview_and_wait_for_rendering_to_be_ready(&servo_test, &webview, &delegate);

    let lcp_script = "(async () => {
        window.lcp = await new Promise(resolve => {
            (new PerformanceObserver(entryList => {
                resolve(entryList.getEntries()[0]);
            }))
            .observe({type: 'largest-contentful-paint', buffered: true});
        })
    })();";

    if let Err(err) = evaluate_javascript(&servo_test, webview.clone(), lcp_script) {
        panic!("Failed to evaluate LCP setup script: {:?}", err);
    }

    // Read from a global variable used to store the result since evaluate_javascript doesn't handle Promises
    let lcp = evaluate_javascript(&servo_test, webview.clone(), "window.lcp.toJSON();");

    if let Ok(JSValue::Object(obj)) = lcp {
        assert_eq!(obj.get("name"), Some(JSValue::String("".into())).as_ref());
        assert_eq!(obj.get("duration"), Some(JSValue::Number(0.0)).as_ref());
        assert_eq!(
            obj.get("entryType"),
            Some(JSValue::String("largest-contentful-paint".into())).as_ref()
        );
        assert_eq!(obj.get("size"), Some(JSValue::Number(2500.0)).as_ref());