lcp.html (4132B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>Soft Navigation Detection: LCP.</title> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/resources/testdriver.js"></script> 9 <script src="/resources/testdriver-vendor.js"></script> 10 <script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script> 11 <script> 12 // The click handler is triggered by user interaction; it modifies 13 // the DOM by adding an image to the page; this triggers both 14 // a soft navigation and a soft navigation LCP entry. 15 function clickHandler() { 16 const img = new Image(); 17 img.src = "/images/lcp-256x256.png"; 18 img.id = "lcp-img"; 19 document.body.appendChild(img); 20 history.pushState({}, "", "/show-image"); 21 } 22 </script> 23 </head> 24 <body> 25 <div id="click-target" onclick="clickHandler()">Click here!</div> 26 27 <script> 28 promise_test(async (t) => { 29 const helper = new SoftNavigationTestHelper(t); 30 31 // Wait for the initial LCP entry, prior to clicking, so that 32 // we may later observe the soft navigation LCP entry in addition. 33 const initial_lcp = 34 await helper.getBufferedPerformanceEntriesWithTimeout("largest-contentful-paint"); 35 assert_equals(initial_lcp.length, 1, "There's one initial LCP entry."); 36 assert_equals( 37 initial_lcp[0].id, 38 "click-target", 39 "The initial LCP entry is the div for the click target.", 40 ); 41 42 if (test_driver) { 43 test_driver.click(document.getElementById("click-target")); 44 } 45 46 // Now that we've clicked, we expect to see a soft navigation, 47 // and a soft navigation LCP entry; 48 const results = await Promise.allSettled([ 49 helper.getBufferedPerformanceEntriesWithTimeout("soft-navigation"), 50 helper.getBufferedPerformanceEntriesWithTimeout("interaction-contentful-paint"), 51 ]); 52 53 // If either or both of soft nav entry or soft nav LCP are missing, 54 // fail the test. 55 const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason.message); 56 if (errors.length > 0) { 57 throw new AssertionError("PerformanceObservers failed: " + format_value(errors)); 58 } 59 60 // Examine the soft navigation entries. 61 const soft_navs = results[0].value; 62 assert_equals(soft_navs.length, 1, "Expecting one soft navigation entry."); 63 assert_equals( 64 soft_navs[0].name.replace(/.*\//, ""), 65 "show-image", 66 "Expecting soft navigation to 'greeting'", 67 ); 68 69 // Examine the soft navigation LCP entries. 70 const icps = results[1].value; 71 assert_equals( 72 icps.length, 73 1, 74 "Expecting 1 entry.", 75 ); 76 77 // Now observe the hard navs again. There should only be one entry. 78 // See also crbug.com/40073849: We really don't want to emit hard nav 79 // LCP entries for soft navigations unintentionally. 80 const observer = new PerformanceObserver(assert_unreached); 81 observer.observe({ 82 type: "largest-contentful-paint", 83 buffered: true, 84 }); 85 const hard_nav_lcp = observer.takeRecords(); 86 observer.disconnect(); 87 88 assert_equals(hard_nav_lcp.length, 1, "Expecting one entry for the hard nav LCP."); 89 90 // Compare the first soft nav LCP entry with the hard nav LCP entry. 91 assert_equals( 92 hard_nav_lcp[0].id, 93 "click-target", 94 "Hard nav LCP entry is (still) for the click target.", 95 ); 96 97 assert_equals( 98 icps[0].id, 99 "lcp-img", 100 "Soft nav LCP entry is for the image.", 101 ); 102 103 assert_equals( 104 icps[0].navigationId, 105 soft_navs[0].navigationId, 106 "Soft nav LCP entry has the same navigation ID as the soft nav entry.", 107 ); 108 }, "Detect soft navigation and LCP after a click."); 109 </script> 110 </body> 111 </html>