browser/extensions/formautofill/test/mochitest/test_basic_creditcard_autocomplete_form.html
author Timothy Guan-tin Chien <timdream@gmail.com>
Wed, 17 Oct 2018 02:31:04 +0000
changeset 489951 96a6e1ceb6977a32bc6a29f46f5a47622bfc4d50
parent 481982 1f763bb7c0efd5b8e85d6c19ad8d7c267011239e
child 490142 831b8aa6281e5e200d92be09a519d17f9367f5ca
permissions -rw-r--r--
Bug 1486954 - Part I, (Nighty-only feature) Encrypt credit card numbers with OS key store r=MattN This patch morphs MasterPassword.jsm to OSKeyStore.jsm while keeping the same API, as an adaptor between the API and the native API exposed as nsIOSKeyStore.idl. Noted that OS Key Store has the concept of "recovery phrase" that we won't be adopting here. The recovery phrase, together with our label, allow the user to re-create the same key in OS key store. Test case changes are needed because we have started asking for login in places where we'll only do previously when "master password is enabled". This also made some "when master password is enabled" tests invalid because it is always considered enabled. Some more test changes are needed simply because they previously rely on the stable order of microtask resolutions (and the stable # of promises for a specific operation). That has certainly changed with OSKeyStore. The credit card form autofill is only enabled on Nightly. Differential Revision: https://phabricator.services.mozilla.com/D4498

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test basic autofill</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
  <script type="text/javascript" src="formautofill_common.js"></script>
  <script type="text/javascript" src="satchel_common.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Form autofill test: simple form credit card autofill

<script>
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */

"use strict";

const MOCK_STORAGE = [{
  "cc-name": "John Doe",
  "cc-number": "4929001587121045",
  "cc-exp-month": 4,
  "cc-exp-year": 2017,
  "cc-type": "visa",
}, {
  "cc-name": "Timothy Berners-Lee",
  "cc-number": "5103059495477870",
  "cc-exp-month": 12,
  "cc-exp-year": 2022,
  "cc-type": "mastercard",
}];

const reducedMockRecord = {
  "cc-name": "John Doe",
  "cc-number": "4929001587121045",
};

async function setupCreditCardStorage() {
  await addCreditCard(MOCK_STORAGE[0]);
  await addCreditCard(MOCK_STORAGE[1]);
}

async function setupFormHistory() {
  await updateFormHistory([
    {op: "add", fieldname: "cc-name", value: "John Smith"},
    {op: "add", fieldname: "cc-exp-year", value: 2023},
  ]);
}

initPopupListener();

// Form with history only.
add_task(async function history_only_menu_checking() {
  // TODO: eliminate the timeout when we're able to indicate the right
  // timing to start.
  //
  // After test process was re-spawning to https scheme. Wait 2 secs
  // to ensure the environment is ready to do storage setup.
  await sleep(2000);
  await setupFormHistory();

  await setInput("#cc-exp-year", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(["2023"], false);
});

// Display credit card result even if the number of fillable fields is less than the threshold.
add_task(async function all_saved_fields_less_than_threshold() {
  await addCreditCard(reducedMockRecord);

  await setInput("#cc-name", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries([reducedMockRecord].map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-name"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));

  await cleanUpCreditCards();
});

// Form with both history and credit card storage.
add_task(async function check_menu_when_both_existed() {
  await setupCreditCardStorage();

  await setInput("#cc-number", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
    primaryAffix: cc.ccNumberFmt.affix,
    primary: cc.ccNumberFmt.label,
    secondary: cc["cc-name"],
  })));

  await setInput("#cc-name", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-name"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));

  await setInput("#cc-exp-year", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-exp-year"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));

  await setInput("#cc-exp-month", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-exp-month"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));

  await cleanUpCreditCards();
});

// Display history search result if no matched data in credit card.
add_task(async function check_fallback_for_mismatched_field() {
  await addCreditCard(reducedMockRecord);

  await setInput("#cc-exp-year", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(["2023"], false);

  await cleanUpCreditCards();
});

// Display history search result if credit card autofill is disabled.
add_task(async function check_search_result_for_pref_off() {
  await setupCreditCardStorage();

  await SpecialPowers.pushPrefEnv({
    set: [["extensions.formautofill.creditCards.enabled", false]],
  });

  await setInput("#cc-name", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(["John Smith"], false);

  await SpecialPowers.popPrefEnv();
});

let canTest;

// Autofill the credit card from dropdown menu.
add_task(async function check_fields_after_form_autofill() {
  canTest = await canTestOSKeyStoreLogin();
  if (!canTest) {
    todo(canTest, "Cannot test OS key store login on official builds.");
    return;
  }

  await setInput("#cc-exp-year", 202);

  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.slice(1).map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-exp-year"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));

  synthesizeKey("KEY_ArrowDown");
  let osKeyStoreLoginShown = waitForOSKeyStoreLogin(true);
  await new Promise(resolve => SimpleTest.executeSoon(resolve));
  await triggerAutofillAndCheckProfile(MOCK_STORAGE[1]);
  await osKeyStoreLoginShown;
});

// Fallback to history search after autofill address.
add_task(async function check_fallback_after_form_autofill() {
  if (!canTest) {
    return;
  }

  await setInput("#cc-name", "", true);
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(["John Smith"], false);
});

// Resume form autofill once all the autofilled fileds are changed.
add_task(async function check_form_autofill_resume() {
  if (!canTest) {
    return;
  }

  document.querySelector("#cc-name").blur();
  document.querySelector("#form1").reset();

  await setInput("#cc-name", "");
  synthesizeKey("KEY_ArrowDown");
  await expectPopup();
  checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
    primary: cc["cc-name"],
    secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
  })));
});

</script>

<p id="display"></p>

<div id="content">

  <form id="form1">
    <p>This is a basic form.</p>
    <p><label>Name: <input id="cc-name" autocomplete="cc-name"></label></p>
    <p><label>Card Number: <input id="cc-number" autocomplete="cc-number"></label></p>
    <p><label>Expiration month: <input id="cc-exp-month" autocomplete="cc-exp-month"></label></p>
    <p><label>Expiration year: <input id="cc-exp-year" autocomplete="cc-exp-year"></label></p>
    <p><label>Card Type: <select id="cc-type" autocomplete="cc-type">
      <option value="discover">Discover</option>
      <option value="jcb">JCB</option>
      <option value="visa">Visa</option>
      <option value="mastercard">MasterCard</option>
    </select></label></p>
    <p><label>CSC: <input id="cc-csc" autocomplete="cc-csc"></label></p>
  </form>
</div>

<pre id="test"></pre>
</body>
</html>