tor-browser

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

browser_form_validation.js (12550B)


      1 var gInvalidFormPopup =
      2  gBrowser.selectedBrowser.browsingContext.currentWindowGlobal
      3    .getActor("FormValidation")
      4    ._getAndMaybeCreatePanel(document);
      5 ok(
      6  gInvalidFormPopup,
      7  "The browser should have a popup to show when a form is invalid"
      8 );
      9 
     10 function isWithinHalfPixel(a, b) {
     11  return Math.abs(a - b) <= 0.5;
     12 }
     13 
     14 function checkPopupShow(anchorRect) {
     15  ok(
     16    gInvalidFormPopup.state == "showing" || gInvalidFormPopup.state == "open",
     17    "[Test " + testId + "] The invalid form popup should be shown"
     18  );
     19  // Just check the vertical position, as the horizontal position of an
     20  // arrow panel will be offset.
     21  is(
     22    isWithinHalfPixel(gInvalidFormPopup.screenY),
     23    isWithinHalfPixel(anchorRect.bottom),
     24    "popup top"
     25  );
     26 }
     27 
     28 function checkPopupHide() {
     29  ok(
     30    gInvalidFormPopup.state != "showing" && gInvalidFormPopup.state != "open",
     31    "[Test " + testId + "] The invalid form popup should not be shown"
     32  );
     33 }
     34 
     35 var testId = 0;
     36 
     37 function incrementTest() {
     38  testId++;
     39  info("Starting next part of test");
     40 }
     41 
     42 function getDocHeader() {
     43  return "<html><head><meta charset='utf-8'></head><body>" + getEmptyFrame();
     44 }
     45 
     46 function getDocFooter() {
     47  return "</body></html>";
     48 }
     49 
     50 function getEmptyFrame() {
     51  return (
     52    "<iframe style='width:100px; height:30px; margin:3px; border:1px solid lightgray;' " +
     53    "name='t' srcdoc=\"<html><head><meta charset='utf-8'></head><body>form target</body></html>\"></iframe>"
     54  );
     55 }
     56 
     57 async function openNewTab(uri, background) {
     58  let tab = BrowserTestUtils.addTab(gBrowser);
     59  let browser = gBrowser.getBrowserForTab(tab);
     60  if (!background) {
     61    gBrowser.selectedTab = tab;
     62  }
     63  await BrowserTestUtils.loadURIString({
     64    browser: tab.linkedBrowser,
     65    uriString: "data:text/html," + escape(uri),
     66  });
     67  return browser;
     68 }
     69 
     70 function clickChildElement(browser) {
     71  return SpecialPowers.spawn(browser, [], async function () {
     72    let element = content.document.getElementById("s");
     73    element.click();
     74    return {
     75      bottom: content.mozInnerScreenY + element.getBoundingClientRect().bottom,
     76    };
     77  });
     78 }
     79 
     80 async function blurChildElement(browser) {
     81  await SpecialPowers.spawn(browser, [], async function () {
     82    content.document.getElementById("i").blur();
     83  });
     84 }
     85 
     86 async function checkChildFocus(browser, message) {
     87  await SpecialPowers.spawn(
     88    browser,
     89    [[message, testId]],
     90    async function (args) {
     91      let [msg, id] = args;
     92      var focused =
     93        content.document.activeElement == content.document.getElementById("i");
     94 
     95      var validMsg = true;
     96      if (msg) {
     97        validMsg =
     98          msg == content.document.getElementById("i").validationMessage;
     99      }
    100 
    101      Assert.equal(
    102        focused,
    103        true,
    104        "Test " + id + " First invalid element should be focused"
    105      );
    106      Assert.equal(
    107        validMsg,
    108        true,
    109        "Test " +
    110          id +
    111          " The panel should show the message from validationMessage"
    112      );
    113    }
    114  );
    115 }
    116 
    117 /**
    118 * In this test, we check that no popup appears if the form is valid.
    119 */
    120 add_task(async function () {
    121  incrementTest();
    122  let uri =
    123    getDocHeader() +
    124    "<form target='t' action='data:text/html,'><input><input id='s' type='submit'></form>" +
    125    getDocFooter();
    126  let browser = await openNewTab(uri);
    127 
    128  await clickChildElement(browser);
    129 
    130  await new Promise(resolve => {
    131    // XXXndeakin This isn't really going to work when the content is another process
    132    executeSoon(function () {
    133      checkPopupHide();
    134      resolve();
    135    });
    136  });
    137 
    138  gBrowser.removeCurrentTab();
    139 });
    140 
    141 /**
    142 * In this test, we check that, when an invalid form is submitted,
    143 * the invalid element is focused and a popup appears.
    144 */
    145 add_task(async function () {
    146  incrementTest();
    147  let uri =
    148    getDocHeader() +
    149    "<form target='t' action='data:text/html,'><input required id='i'><input id='s' type='submit'></form>" +
    150    getDocFooter();
    151  let browser = await openNewTab(uri);
    152 
    153  let popupShownPromise = BrowserTestUtils.waitForEvent(
    154    gInvalidFormPopup,
    155    "popupshown"
    156  );
    157  let anchorRect = await clickChildElement(browser);
    158  await popupShownPromise;
    159 
    160  checkPopupShow(anchorRect);
    161 
    162  await checkChildFocus(
    163    browser,
    164    gInvalidFormPopup.firstElementChild.textContent
    165  );
    166 
    167  gBrowser.removeCurrentTab();
    168 });
    169 
    170 /**
    171 * In this test, we check that, when an invalid form is submitted,
    172 * the first invalid element is focused and a popup appears.
    173 */
    174 add_task(async function () {
    175  incrementTest();
    176  let uri =
    177    getDocHeader() +
    178    "<form target='t' action='data:text/html,'><input><input id='i' required><input required><input id='s' type='submit'></form>" +
    179    getDocFooter();
    180  let browser = await openNewTab(uri);
    181 
    182  let popupShownPromise = BrowserTestUtils.waitForEvent(
    183    gInvalidFormPopup,
    184    "popupshown"
    185  );
    186  let anchorRect = await clickChildElement(browser);
    187  await popupShownPromise;
    188 
    189  checkPopupShow(anchorRect);
    190  await checkChildFocus(
    191    browser,
    192    gInvalidFormPopup.firstElementChild.textContent
    193  );
    194 
    195  gBrowser.removeCurrentTab();
    196 });
    197 
    198 /**
    199 * In this test, we check that, we hide the popup by interacting with the
    200 * invalid element if the element becomes valid.
    201 */
    202 add_task(async function () {
    203  incrementTest();
    204  let uri =
    205    getDocHeader() +
    206    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    207    getDocFooter();
    208  let browser = await openNewTab(uri);
    209 
    210  let popupShownPromise = BrowserTestUtils.waitForEvent(
    211    gInvalidFormPopup,
    212    "popupshown"
    213  );
    214  let anchorRect = await clickChildElement(browser);
    215  await popupShownPromise;
    216 
    217  checkPopupShow(anchorRect);
    218  await checkChildFocus(
    219    browser,
    220    gInvalidFormPopup.firstElementChild.textContent
    221  );
    222 
    223  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    224    gInvalidFormPopup,
    225    "popuphidden"
    226  );
    227  EventUtils.sendString("a");
    228  await popupHiddenPromise;
    229 
    230  gBrowser.removeCurrentTab();
    231 });
    232 
    233 /**
    234 * In this test, we check that, we don't hide the popup by interacting with the
    235 * invalid element if the element is still invalid.
    236 */
    237 add_task(async function () {
    238  incrementTest();
    239  let uri =
    240    getDocHeader() +
    241    "<form target='t' action='data:text/html,'><input type='email' id='i' required><input id='s' type='submit'></form>" +
    242    getDocFooter();
    243  let browser = await openNewTab(uri);
    244 
    245  let popupShownPromise = BrowserTestUtils.waitForEvent(
    246    gInvalidFormPopup,
    247    "popupshown"
    248  );
    249  let anchorRect = await clickChildElement(browser);
    250  await popupShownPromise;
    251 
    252  checkPopupShow(anchorRect);
    253  await checkChildFocus(
    254    browser,
    255    gInvalidFormPopup.firstElementChild.textContent
    256  );
    257 
    258  await new Promise(resolve => {
    259    EventUtils.sendString("a");
    260    executeSoon(function () {
    261      checkPopupShow(anchorRect);
    262      resolve();
    263    });
    264  });
    265 
    266  gBrowser.removeCurrentTab();
    267 });
    268 
    269 /**
    270 * In this test, we check that we can hide the popup by blurring the invalid
    271 * element.
    272 */
    273 add_task(async function () {
    274  incrementTest();
    275  let uri =
    276    getDocHeader() +
    277    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    278    getDocFooter();
    279  let browser = await openNewTab(uri);
    280 
    281  let popupShownPromise = BrowserTestUtils.waitForEvent(
    282    gInvalidFormPopup,
    283    "popupshown"
    284  );
    285  let anchorRect = await clickChildElement(browser);
    286  await popupShownPromise;
    287 
    288  checkPopupShow(anchorRect);
    289  await checkChildFocus(
    290    browser,
    291    gInvalidFormPopup.firstElementChild.textContent
    292  );
    293 
    294  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    295    gInvalidFormPopup,
    296    "popuphidden"
    297  );
    298  await blurChildElement(browser);
    299  await popupHiddenPromise;
    300 
    301  gBrowser.removeCurrentTab();
    302 });
    303 
    304 /**
    305 * In this test, we check that we can hide the popup by pressing TAB.
    306 */
    307 add_task(async function () {
    308  incrementTest();
    309  let uri =
    310    getDocHeader() +
    311    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    312    getDocFooter();
    313  let browser = await openNewTab(uri);
    314 
    315  let popupShownPromise = BrowserTestUtils.waitForEvent(
    316    gInvalidFormPopup,
    317    "popupshown"
    318  );
    319  let anchorRect = await clickChildElement(browser);
    320  await popupShownPromise;
    321 
    322  checkPopupShow(anchorRect);
    323  await checkChildFocus(
    324    browser,
    325    gInvalidFormPopup.firstElementChild.textContent
    326  );
    327 
    328  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    329    gInvalidFormPopup,
    330    "popuphidden"
    331  );
    332  EventUtils.synthesizeKey("KEY_Tab");
    333  await popupHiddenPromise;
    334 
    335  gBrowser.removeCurrentTab();
    336 });
    337 
    338 /**
    339 * In this test, we check that the popup will hide if we move to another tab.
    340 */
    341 add_task(async function () {
    342  incrementTest();
    343  let uri =
    344    getDocHeader() +
    345    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    346    getDocFooter();
    347  let browser1 = await openNewTab(uri);
    348 
    349  let popupShownPromise = BrowserTestUtils.waitForEvent(
    350    gInvalidFormPopup,
    351    "popupshown"
    352  );
    353  let anchorRect = await clickChildElement(browser1);
    354  await popupShownPromise;
    355 
    356  checkPopupShow(anchorRect);
    357  await checkChildFocus(
    358    browser1,
    359    gInvalidFormPopup.firstElementChild.textContent
    360  );
    361 
    362  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    363    gInvalidFormPopup,
    364    "popuphidden"
    365  );
    366 
    367  let browser2 = await openNewTab("data:text/html,<html></html>");
    368  await popupHiddenPromise;
    369 
    370  gBrowser.removeTab(gBrowser.getTabForBrowser(browser1));
    371  gBrowser.removeTab(gBrowser.getTabForBrowser(browser2));
    372 });
    373 
    374 /**
    375 * In this test, we check that the popup will hide if we navigate to another
    376 * page.
    377 */
    378 add_task(async function () {
    379  incrementTest();
    380  let uri =
    381    getDocHeader() +
    382    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    383    getDocFooter();
    384  let browser = await openNewTab(uri);
    385 
    386  let popupShownPromise = BrowserTestUtils.waitForEvent(
    387    gInvalidFormPopup,
    388    "popupshown"
    389  );
    390  let anchorRect = await clickChildElement(browser);
    391  await popupShownPromise;
    392 
    393  checkPopupShow(anchorRect);
    394  await checkChildFocus(
    395    browser,
    396    gInvalidFormPopup.firstElementChild.textContent
    397  );
    398 
    399  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    400    gInvalidFormPopup,
    401    "popuphidden"
    402  );
    403  BrowserTestUtils.startLoadingURIString(
    404    browser,
    405    "data:text/html,<div>hello!</div>"
    406  );
    407  await BrowserTestUtils.browserLoaded(browser);
    408 
    409  await popupHiddenPromise;
    410 
    411  gBrowser.removeCurrentTab();
    412 });
    413 
    414 /**
    415 * In this test, we check that the message is correctly updated when it changes.
    416 */
    417 add_task(async function () {
    418  incrementTest();
    419  let uri =
    420    getDocHeader() +
    421    "<form target='t' action='data:text/html,'><input type='email' required id='i'><input id='s' type='submit'></form>" +
    422    getDocFooter();
    423  let browser = await openNewTab(uri);
    424 
    425  let popupShownPromise = BrowserTestUtils.waitForEvent(
    426    gInvalidFormPopup,
    427    "popupshown"
    428  );
    429  let anchorRect = await clickChildElement(browser);
    430  await popupShownPromise;
    431 
    432  checkPopupShow(anchorRect);
    433  await checkChildFocus(
    434    browser,
    435    gInvalidFormPopup.firstElementChild.textContent
    436  );
    437 
    438  let inputPromise = BrowserTestUtils.waitForContentEvent(browser, "input");
    439  EventUtils.sendString("f");
    440  await inputPromise;
    441 
    442  // Now, the element suffers from another error, the message should have
    443  // been updated.
    444  await new Promise(resolve => {
    445    // XXXndeakin This isn't really going to work when the content is another process
    446    executeSoon(function () {
    447      checkChildFocus(browser, gInvalidFormPopup.firstElementChild.textContent);
    448      resolve();
    449    });
    450  });
    451 
    452  gBrowser.removeCurrentTab();
    453 });
    454 
    455 /**
    456 * In this test, we reload the page while the form validation popup is visible. The validation
    457 * popup should hide.
    458 */
    459 add_task(async function () {
    460  incrementTest();
    461  let uri =
    462    getDocHeader() +
    463    "<form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>" +
    464    getDocFooter();
    465  let browser = await openNewTab(uri);
    466 
    467  let popupShownPromise = BrowserTestUtils.waitForEvent(
    468    gInvalidFormPopup,
    469    "popupshown"
    470  );
    471  let anchorRect = await clickChildElement(browser);
    472  await popupShownPromise;
    473 
    474  checkPopupShow(anchorRect);
    475  await checkChildFocus(
    476    browser,
    477    gInvalidFormPopup.firstElementChild.textContent
    478  );
    479 
    480  let popupHiddenPromise = BrowserTestUtils.waitForEvent(
    481    gInvalidFormPopup,
    482    "popuphidden"
    483  );
    484  BrowserCommands.reloadSkipCache();
    485  await popupHiddenPromise;
    486 
    487  gBrowser.removeCurrentTab();
    488 });