lcp-unbuffered.html (3777B)
1 <!doctype html> 2 <meta charset="utf-8" /> 3 <title>Soft Navigation Detection: LCP, with unbuffered observers.</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/resources/testdriver.js"></script> 7 <script src="/resources/testdriver-vendor.js"></script> 8 <script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script> 9 <script> 10 // The click handler is triggered by user interaction; it modifies 11 // the DOM by adding an image to the page; this triggers both 12 // a soft navigation and a soft navigation LCP entry. 13 function clickHandler() { 14 const img = new Image(); 15 img.src = "/images/lcp-256x256.png"; 16 img.id = "lcp-img"; 17 document.body.appendChild(img); 18 history.pushState({}, "", "/show-image"); 19 } 20 21 // We start this promise early, so that it can observe the initial LCP, 22 // which is expected to be the div just below. 23 const firstLcpPromise = 24 SoftNavigationTestHelper.getPerformanceEntries("largest-contentful-paint"); 25 </script> 26 <div id="click-target" onclick="clickHandler()">Click here!</div> 27 28 <script> 29 promise_test(async (t) => { 30 const helper = new SoftNavigationTestHelper(t); 31 const firstLcp = await helper.withTimeoutMessage(firstLcpPromise, "First LCP missing."); 32 assert_equals(firstLcp.length, 1, "Expecting first LCP."); 33 assert_equals(firstLcp[0].id, "click-target", "LCP should be click target."); 34 35 // Set up promises for soft navigation and LCP entries, before the click. 36 const softNavPromise = 37 SoftNavigationTestHelper.getPerformanceEntries("soft-navigation"); 38 const icpPromise = 39 SoftNavigationTestHelper.getPerformanceEntries("interaction-contentful-paint"); 40 if (test_driver) { 41 test_driver.click(document.getElementById("click-target")); 42 } 43 // Now that we've clicked, we expect to see a soft navigation, 44 // and a soft navigation LCP entry. 45 const results = await Promise.allSettled([ 46 helper.withTimeoutMessage(softNavPromise, "Soft navigation entry never arrived.", 3000), 47 helper.withTimeoutMessage(icpPromise, "ICP entry never arrived.", 3000), 48 ]); 49 50 // If either or both of soft nav entry or soft nav LCP are missing, 51 // fail the test. 52 const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason.message); 53 if (errors.length > 0) { 54 throw new AssertionError("PerformanceObservers failed: " + format_value(errors)); 55 } 56 57 // Examine the soft navigation entries. 58 const softNavs = results[0].value; 59 assert_equals(softNavs.length, 1, "Expecting one soft navigation entry."); 60 assert_equals( 61 softNavs[0].name.replace(/.*\//, ""), 62 "show-image", 63 "Expecting soft navigation to 'show-image'", 64 ); 65 66 // Examine the soft navigation LCP entry. 67 const icps = results[1].value; 68 assert_equals(icps.length, 1, "Expecting one LCP after click."); 69 assert_equals(icps[0].id, "lcp-img", "LCP after click should be for the image."); 70 71 // Examine timestamps. 72 assert_less_than( 73 firstLcp[0].startTime, 74 softNavs[0].startTime, 75 "Soft navigation should start after first LCP.", 76 ); 77 assert_less_than( 78 softNavs[0].startTime, 79 icps[0].startTime, 80 "LCP should start after soft navigation.", 81 ); 82 83 // Examine navigation ids. 84 assert_equals( 85 icps[0].navigationId, 86 softNavs[0].navigationId, 87 "LCP should have the same navigation id as soft navigation.", 88 ); 89 assert_not_equals( 90 icps[0].navigationId, 91 firstLcp[0].navigationId, 92 "LCP should have a different navigation id than first LCP.", 93 ); 94 }, "Detect soft navigation and LCP after a click with unbuffered observers."); 95 </script>