tor-browser

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

browser_test_position_sticky.js (4714B)


      1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
      2 /* vim: set sts=2 sw=2 et tw=80: */
      3 "use strict";
      4 
      5 Services.scriptloader.loadSubScript(
      6  "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_utils.js",
      7  this
      8 );
      9 
     10 Services.scriptloader.loadSubScript(
     11  "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js",
     12  this
     13 );
     14 
     15 Services.scriptloader.loadSubScript(
     16  "chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js",
     17  this
     18 );
     19 
     20 // usesFailurePatterns is defined in SimpleTest.js and used in
     21 // WindowSnapshot.js but SimpleTest.js can't be loaded in browser mochitests
     22 // (there's an equivalent script named browser-test.js for browser mochitests),
     23 // so we define usesFailurePatterns which just returns false to make functions
     24 // in WindowSnapshot.js work without loading SimpleTest.js.
     25 function usesFailurePatterns() {
     26  return false;
     27 }
     28 
     29 async function convertDataURLtoCanvas(aDataURL, aWidth, aHeight) {
     30  const canvas = document.createElementNS(
     31    "http://www.w3.org/1999/xhtml",
     32    "canvas"
     33  );
     34  canvas.width = aWidth;
     35  canvas.height = aHeight;
     36  const image = new Image();
     37  const ctx = canvas.getContext("2d");
     38  const loadPromise = new Promise(resolve =>
     39    image.addEventListener("load", resolve)
     40  );
     41  image.src = aDataURL;
     42  await loadPromise;
     43  ctx.drawImage(image, 0, 0);
     44  return canvas;
     45 }
     46 
     47 add_task(async () => {
     48  function httpURL(filename) {
     49    let chromeURL = getRootDirectory(gTestPath) + filename;
     50    return chromeURL.replace(
     51      "chrome://mochitests/content/",
     52      "http://mochi.test:8888/"
     53    );
     54  }
     55 
     56  const url = httpURL("helper_position_sticky_flicker.html");
     57  const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
     58 
     59  const { rect, scrollbarWidth } = await SpecialPowers.spawn(
     60    tab.linkedBrowser,
     61    [],
     62    async () => {
     63      const sticky = content.document.getElementById("sticky");
     64 
     65      // Get the area in the screen coords where the position:sticky element is.
     66      let stickyRect = sticky.getBoundingClientRect();
     67      stickyRect.x += content.window.mozInnerScreenX;
     68      stickyRect.y += content.window.mozInnerScreenY;
     69 
     70      // generate some DIVs to make the page complex enough.
     71      for (let i = 1; i <= 120000; i++) {
     72        const div = content.document.createElement("div");
     73        div.innerText = `${i}`;
     74        content.document.body.appendChild(div);
     75      }
     76 
     77      await content.wrappedJSObject.promiseApzFlushedRepaints();
     78      await content.wrappedJSObject.waitUntilApzStable();
     79 
     80      let w = {},
     81        h = {};
     82      SpecialPowers.DOMWindowUtils.getScrollbarSizes(
     83        content.document.documentElement,
     84        w,
     85        h
     86      );
     87 
     88      // Reduce the scrollbar width from the sticky area.
     89      stickyRect.width -= w.value;
     90      return {
     91        rect: stickyRect,
     92        scrollbarWidth: w.value,
     93      };
     94    }
     95  );
     96 
     97  // Take a snapshot where the position:sticky element is initially painted.
     98  const referenceDataURL = await getSnapshot(rect);
     99  const referenceCanvas = await convertDataURLtoCanvas(
    100    referenceDataURL,
    101    rect.width,
    102    rect.height
    103  );
    104 
    105  let mouseX = window.innerWidth - scrollbarWidth / 2;
    106  let mouseY = tab.linkedBrowser.getBoundingClientRect().y + 5;
    107 
    108  // Scroll fast to cause checkerboarding multiple times.
    109  const dragFinisher = await promiseNativeMouseDrag(
    110    window,
    111    mouseX,
    112    mouseY,
    113    0,
    114    window.innerHeight,
    115    100
    116  );
    117 
    118  // On debug builds there seems to be no chance that the content process gets
    119  // painted during above promiseNativeMouseDrag call, wait two frames to make
    120  // sure it happens so that this test is likely able to fail without proper
    121  // fix.
    122  if (AppConstants.DEBUG) {
    123    await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
    124      await content.wrappedJSObject.promiseFrame(content.window);
    125      await content.wrappedJSObject.promiseFrame(content.window);
    126    });
    127  }
    128 
    129  // Take a snapshot again where the position:sticky element should be painted.
    130  const snapshotDataURL = await getSnapshot(rect);
    131  const snapshotCanvas = await convertDataURLtoCanvas(
    132    snapshotDataURL,
    133    rect.width,
    134    rect.height
    135  );
    136 
    137  await dragFinisher();
    138 
    139  const disablePixelAlignment = SpecialPowers.getBoolPref(
    140    "layout.disable-pixel-alignment"
    141  );
    142  // With disabling pixel alignment, there appears 1px line glitch at the top of
    143  // the image, we allow it.
    144  const fuzz = disablePixelAlignment
    145    ? { maxDifference: 1, numDifferentPixels: rect.width }
    146    : null;
    147 
    148  assertSnapshots(
    149    snapshotCanvas,
    150    referenceCanvas,
    151    true /* expectEqual */,
    152    fuzz,
    153    "test case",
    154    "reference"
    155  );
    156 
    157  BrowserTestUtils.removeTab(tab);
    158 });