tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

overwriting-text.html (3731B)


      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  async function waitForExactlyOneElementTimingEntry(id, buffered) {
     16    let entries = await new Promise(resolve => {
     17      new PerformanceObserver((list, observer) => {
     18        resolve(list.getEntries());
     19        observer.disconnect();
     20      }).observe({type: 'element', buffered});
     21    });
     22    assert_equals(
     23        entries.length, 1,
     24        `Expected exactly one ElementTiming entry for "${id}"`);
     25    assert_equals(
     26        entries[0].identifier, id,
     27        `Unexpected ElementTiming entry: expected "${id}"`);
     28  }
     29 
     30  async function runTest(t, url, text) {
     31    navigateButton.addEventListener('click', async () => {
     32      // We expect to get a timing entry for this, but not a soft nav ICP entry.
     33      // This lets us check that we don't get more than the initial timing entry
     34      // for `content`.
     35      const div = document.createElement("div");
     36      div.innerHTML = `<div id="additional" elementtiming="${url}">hi</div>`;
     37      container.appendChild(div);
     38 
     39      content.innerText = text;
     40 
     41      history.pushState({}, '', url);
     42    }, {once: true});
     43 
     44    // Set up the PerformanceObservers before clicking to avoid races,
     45    // and use unbuffered here so we don't get duplicate entries.
     46    const elementTimingPromise =
     47        waitForExactlyOneElementTimingEntry(url, /*buffered=*/false);
     48    const softNavPromise =
     49        SoftNavigationTestHelper.getPerformanceEntries("soft-navigation");
     50    const icpPromise =
     51        SoftNavigationTestHelper.getPerformanceEntries("interaction-contentful-paint");
     52 
     53    if (test_driver) {
     54      test_driver.click(navigateButton);
     55    }
     56 
     57    const helper = new SoftNavigationTestHelper(t);
     58 
     59    // Check if we detected a soft nav.
     60    const softNavs = await helper.withTimeoutMessage(
     61        softNavPromise, "Soft navigation not detected.", /*timeout=*/ 3000);
     62    assert_equals(softNavs.length, 1, 'Expected exactly one soft navigation.');
     63    assert_true(
     64      softNavs[0].name.endsWith(url),
     65      `Unexpected Soft Navigation URL. Expected url to end with ${url} but got ${softNavs[0].name}`);
     66 
     67    // Check that we only get one ICP entry, and that it's for the node whose
     68    // text we overwrote.
     69    const icps = await helper.withTimeoutMessage(
     70        icpPromise, 'ICP not detected.', /*timeout=*/ 3000);
     71    assert_equals(icps.length, 1, 'Expected exactly one ICP entry.');
     72    assert_equals(icps[0].id, 'content', 'Expected ICP candidate to be "content"');
     73 
     74    // Finally, check to make sure we don't get an additional timing entry.
     75    return elementTimingPromise;
     76  }
     77 
     78  // Wait for the initial text load and make its way through the text timing
     79  // pipeline before changing its contents.
     80  promise_setup(() => waitForExactlyOneElementTimingEntry('content-text', /*buffered=*/true));
     81 
     82  promise_test(t => {
     83    const url = 'soft-nav-1';
     84    const text = 'The initial text has been replaced!';
     85    return runTest(t, url, text);
     86  }, 'Soft Navigation Detection supports replacing existing text');
     87 
     88  promise_test(t => {
     89    const url = 'soft-nav-2';
     90    const text = 'The initial text has been replaced again!';
     91    return runTest(t, url, text);
     92  }, 'Soft Navigation Detection supports replacing existing text in multiple interactions');
     93 </script>