overwriting-text-once-per-interaction.html (3689B)
1 <!DOCTYPE html> 2 <meta charset="utf-8" /> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/resources/testdriver.js"></script> 6 <script src="/resources/testdriver-vendor.js"></script> 7 <script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script> 8 9 <button id="navigateButton">Click here!</button> 10 <h1>Heading!</h1> 11 <div id="content" elementtiming="content-text">Initial Text</div> 12 <div id="container"></div> 13 14 <script> 15 promise_test(async t => { 16 const url = 'soft-nav-1'; 17 18 // Wait for the initial text load and make its way through the text timing 19 // pipeline before changing its contents. 20 const elementId = "content-text"; 21 let entries = await new Promise(resolve => { 22 new PerformanceObserver((list, observer) => { 23 resolve(list.getEntries()); 24 observer.disconnect(); 25 }).observe({type: 'element', buffered: true}); 26 }); 27 assert_equals( 28 entries.length, 1, 29 `Expected exactly one ElementTiming entry for "${elementId}"`); 30 assert_equals( 31 entries[0].identifier, elementId, 32 `Unexpected ElementTiming entry: expected "${elementId}"`); 33 34 const softNavPromise = 35 SoftNavigationTestHelper.getPerformanceEntries("soft-navigation"); 36 let icpPromise = 37 SoftNavigationTestHelper.getPerformanceEntries("interaction-contentful-paint"); 38 const {promise, resolve} = Promise.withResolvers(); 39 40 navigateButton.addEventListener('click', async () => { 41 // This is sufficient to trigger an initial soft nav and ICP entry. 42 history.pushState({}, '', url); 43 content.innerText = 'This is some new text!'; 44 45 // Wait for the first round of soft nav/ICP checking. 46 await promise; 47 48 // Add more text, which should produce another ICP entry. 49 container.innerHTML = `<div id="container-text">${content.innerText} (and more text)</div>`; 50 // Now, update the same text as before with even more text than above. 51 // We shouldn't get an ICP entry for this, even though it's larger, 52 // because we already have an entry for this node. 53 content.innerText = content.innerText + ' (and even more text)'; 54 }, {once: true}); 55 56 if (test_driver) { 57 test_driver.click(navigateButton); 58 } 59 60 const helper = new SoftNavigationTestHelper(t); 61 // Check if we detected a soft nav. 62 const softNavs = await helper.withTimeoutMessage( 63 softNavPromise, "Soft navigation not detected.", /*timeout=*/ 3000); 64 assert_equals(softNavs.length, 1, 'Expected exactly one soft navigation.'); 65 assert_true( 66 softNavs[0].name.endsWith(url), 67 `Unexpected Soft Navigation URL. Expected url to end with ${url} but got ${softNavs[0].name}`); 68 69 // Check that we only get one ICP entry, and that it's for the node whose 70 // text we overwrote. 71 let icps = await helper.withTimeoutMessage( 72 icpPromise, 'ICP not detected.', /*timeout=*/ 3000); 73 assert_equals(icps.length, 1, 'Expected exactly one ICP entry.'); 74 assert_equals(icps[0].id, 'content', 'Expected ICP candidate to be "content"'); 75 76 77 // Set things up for the next ICP entry. 78 icpPromise = SoftNavigationTestHelper.getPerformanceEntries("interaction-contentful-paint"); 79 resolve(); 80 81 icps = await helper.withTimeoutMessage( 82 icpPromise, 'New ICP not detected.', /*timeout=*/ 3000); 83 assert_equals(icps.length, 1, 'Expected exactly one ICP entry.'); 84 assert_equals(icps[0].id, 'container-text', 'Expected ICP candidate to be "container-text"'); 85 }, 'Soft Navigation Detection supports replacing existing text once per interaction'); 86 </script>