tor-browser

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

test_creditCardRecords.js (21595B)


      1 /**
      2 * Tests FormAutofillStorage object with creditCards records.
      3 */
      4 
      5 "use strict";
      6 
      7 ChromeUtils.defineESModuleGetters(this, {
      8  Preferences: "resource://gre/modules/Preferences.sys.mjs",
      9 });
     10 const { CreditCard } = ChromeUtils.importESModule(
     11  "resource://gre/modules/CreditCard.sys.mjs"
     12 );
     13 
     14 let FormAutofillStorage;
     15 let CREDIT_CARD_SCHEMA_VERSION;
     16 add_setup(async () => {
     17  ({ FormAutofillStorage } = ChromeUtils.importESModule(
     18    "resource://autofill/FormAutofillStorage.sys.mjs"
     19  ));
     20  ({ CREDIT_CARD_SCHEMA_VERSION } = ChromeUtils.importESModule(
     21    "resource://autofill/FormAutofillStorageBase.sys.mjs"
     22  ));
     23 });
     24 
     25 const TEST_STORE_FILE_NAME = "test-credit-card.json";
     26 const COLLECTION_NAME = "creditCards";
     27 
     28 const TEST_CREDIT_CARD_1 = {
     29  "cc-name": "John Doe",
     30  "cc-number": "4929001587121045",
     31  "cc-exp-month": 4,
     32  "cc-exp-year": 2017,
     33 };
     34 
     35 const TEST_CREDIT_CARD_2 = {
     36  "cc-name": "Timothy Berners-Lee",
     37  "cc-number": "5103059495477870",
     38  "cc-exp-month": 12,
     39  "cc-exp-year": 2022,
     40 };
     41 
     42 const TEST_CREDIT_CARD_3 = {
     43  "cc-number": "3589993783099582",
     44  "cc-exp-month": 1,
     45  "cc-exp-year": 2000,
     46 };
     47 
     48 const TEST_CREDIT_CARD_WITH_BILLING_ADDRESS = {
     49  "cc-name": "J. Smith",
     50  "cc-number": "4111111111111111",
     51  billingAddressGUID: "9m6hf4gfr6ge",
     52 };
     53 
     54 const TEST_CREDIT_CARD_WITH_EMPTY_FIELD = {
     55  billingAddressGUID: "",
     56  "cc-name": "",
     57  "cc-number": "344060747836806",
     58  "cc-exp-month": 1,
     59 };
     60 
     61 const TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD = {
     62  "cc-given-name": "",
     63  "cc-additional-name": "",
     64  "cc-family-name": "",
     65  "cc-exp": "",
     66  "cc-number": "5415425865751454",
     67 };
     68 
     69 const TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR = {
     70  "cc-number": "344060747836806",
     71  "cc-exp-month": 1,
     72  "cc-exp-year": 12,
     73 };
     74 
     75 const TEST_CREDIT_CARD_WITH_INVALID_EXPIRY_DATE = {
     76  "cc-name": "John Doe",
     77  "cc-number": "5103059495477870",
     78  "cc-exp-month": 13,
     79  "cc-exp-year": -3,
     80 };
     81 
     82 const TEST_CREDIT_CARD_WITH_SPACES_BETWEEN_DIGITS = {
     83  "cc-name": "John Doe",
     84  "cc-number": "5103 0594 9547 7870",
     85 };
     86 
     87 const TEST_CREDIT_CARD_EMPTY_AFTER_NORMALIZE = {
     88  "cc-exp-month": 13,
     89 };
     90 
     91 const TEST_CREDIT_CARD_EMPTY_AFTER_UPDATE_CREDIT_CARD_1 = {
     92  "cc-name": "",
     93  "cc-number": "",
     94  "cc-exp-month": 13,
     95  "cc-exp-year": "",
     96 };
     97 
     98 let prepareTestCreditCards = async function (path) {
     99  let profileStorage = new FormAutofillStorage(path);
    100  await profileStorage.initialize();
    101 
    102  let onChanged = TestUtils.topicObserved(
    103    "formautofill-storage-changed",
    104    (subject, data) =>
    105      data == "add" &&
    106      subject.wrappedJSObject.guid &&
    107      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    108  );
    109  Assert.ok(await profileStorage.creditCards.add(TEST_CREDIT_CARD_1));
    110  await onChanged;
    111  Assert.ok(await profileStorage.creditCards.add(TEST_CREDIT_CARD_2));
    112  await onChanged;
    113  await profileStorage._saveImmediately();
    114 };
    115 
    116 let reCCNumber = /^(\*+)(.{4})$/;
    117 
    118 let do_check_credit_card_matches = (creditCardWithMeta, creditCard) => {
    119  for (let key in creditCard) {
    120    if (key == "cc-number") {
    121      let matches = reCCNumber.exec(creditCardWithMeta["cc-number"]);
    122      Assert.notEqual(matches, null);
    123      Assert.equal(
    124        creditCardWithMeta["cc-number"].length,
    125        creditCard["cc-number"].length
    126      );
    127      Assert.equal(creditCard["cc-number"].endsWith(matches[2]), true);
    128      Assert.notEqual(creditCard["cc-number-encrypted"], "");
    129    } else {
    130      Assert.equal(creditCardWithMeta[key], creditCard[key], "Testing " + key);
    131    }
    132  }
    133 };
    134 
    135 add_task(async function test_initialize() {
    136  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    137  let profileStorage = new FormAutofillStorage(path);
    138  await profileStorage.initialize();
    139 
    140  Assert.equal(profileStorage._store.data.version, 1);
    141  Assert.equal(profileStorage._store.data.creditCards.length, 0);
    142 
    143  let data = profileStorage._store.data;
    144  Assert.deepEqual(data.creditCards, []);
    145 
    146  await profileStorage._saveImmediately();
    147 
    148  profileStorage = new FormAutofillStorage(path);
    149  await profileStorage.initialize();
    150 
    151  Assert.deepEqual(profileStorage._store.data, data);
    152 });
    153 
    154 add_task(async function test_getAll() {
    155  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    156  await prepareTestCreditCards(path);
    157 
    158  let profileStorage = new FormAutofillStorage(path);
    159  await profileStorage.initialize();
    160 
    161  let creditCards = await profileStorage.creditCards.getAll();
    162 
    163  Assert.equal(creditCards.length, 2);
    164  do_check_credit_card_matches(creditCards[0], TEST_CREDIT_CARD_1);
    165  do_check_credit_card_matches(creditCards[1], TEST_CREDIT_CARD_2);
    166 
    167  // Check computed fields.
    168  Assert.equal(creditCards[0]["cc-given-name"], "John");
    169  Assert.equal(creditCards[0]["cc-family-name"], "Doe");
    170  Assert.equal(creditCards[0]["cc-exp"], "2017-04");
    171 
    172  // Test with rawData set.
    173  creditCards = await profileStorage.creditCards.getAll({ rawData: true });
    174  Assert.equal(creditCards[0]["cc-given-name"], undefined);
    175  Assert.equal(creditCards[0]["cc-family-name"], undefined);
    176  Assert.equal(creditCards[0]["cc-exp"], undefined);
    177 
    178  // Modifying output shouldn't affect the storage.
    179  creditCards[0]["cc-name"] = "test";
    180  do_check_credit_card_matches(
    181    (await profileStorage.creditCards.getAll())[0],
    182    TEST_CREDIT_CARD_1
    183  );
    184 });
    185 
    186 add_task(async function test_get() {
    187  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    188  await prepareTestCreditCards(path);
    189 
    190  let profileStorage = new FormAutofillStorage(path);
    191  await profileStorage.initialize();
    192 
    193  let creditCards = await profileStorage.creditCards.getAll();
    194  let guid = creditCards[0].guid;
    195 
    196  let creditCard = await profileStorage.creditCards.get(guid);
    197  do_check_credit_card_matches(creditCard, TEST_CREDIT_CARD_1);
    198 
    199  // Modifying output shouldn't affect the storage.
    200  creditCards[0]["cc-name"] = "test";
    201  do_check_credit_card_matches(
    202    await profileStorage.creditCards.get(guid),
    203    TEST_CREDIT_CARD_1
    204  );
    205 
    206  Assert.equal(await profileStorage.creditCards.get("INVALID_GUID"), null);
    207 });
    208 
    209 add_task(async function test_add() {
    210  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    211  await prepareTestCreditCards(path);
    212 
    213  let profileStorage = new FormAutofillStorage(path);
    214  await profileStorage.initialize();
    215 
    216  let creditCards = await profileStorage.creditCards.getAll();
    217 
    218  Assert.equal(creditCards.length, 2);
    219 
    220  do_check_credit_card_matches(creditCards[0], TEST_CREDIT_CARD_1);
    221  do_check_credit_card_matches(creditCards[1], TEST_CREDIT_CARD_2);
    222 
    223  Assert.notEqual(creditCards[0].guid, undefined);
    224  Assert.equal(creditCards[0].version, CREDIT_CARD_SCHEMA_VERSION);
    225  Assert.notEqual(creditCards[0].timeCreated, undefined);
    226  Assert.equal(creditCards[0].timeLastModified, creditCards[0].timeCreated);
    227  Assert.equal(creditCards[0].timeLastUsed, 0);
    228  Assert.equal(creditCards[0].timesUsed, 0);
    229 
    230  // Empty string should be deleted before saving.
    231  await profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_EMPTY_FIELD);
    232  let creditCard = profileStorage.creditCards._data[2];
    233  Assert.equal(
    234    creditCard["cc-exp-month"],
    235    TEST_CREDIT_CARD_WITH_EMPTY_FIELD["cc-exp-month"]
    236  );
    237  Assert.equal(creditCard["cc-name"], undefined);
    238  Assert.equal(creditCard.billingAddressGUID, undefined);
    239 
    240  // Empty computed fields shouldn't cause any problem.
    241  await profileStorage.creditCards.add(
    242    TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD
    243  );
    244  creditCard = profileStorage.creditCards._data[3];
    245  Assert.equal(
    246    creditCard["cc-number"],
    247    CreditCard.getLongMaskedNumber(
    248      TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD["cc-number"]
    249    )
    250  );
    251 
    252  await Assert.rejects(
    253    profileStorage.creditCards.add({}),
    254    /Record contains no valid field\./
    255  );
    256 
    257  await Assert.rejects(
    258    profileStorage.creditCards.add(TEST_CREDIT_CARD_EMPTY_AFTER_NORMALIZE),
    259    /Record contains no valid field\./
    260  );
    261 });
    262 
    263 add_task(async function test_addWithBillingAddress() {
    264  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    265  let profileStorage = new FormAutofillStorage(path);
    266  await profileStorage.initialize();
    267 
    268  let creditCards = await profileStorage.creditCards.getAll();
    269 
    270  Assert.equal(creditCards.length, 0);
    271 
    272  await profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_BILLING_ADDRESS);
    273 
    274  creditCards = await profileStorage.creditCards.getAll();
    275  Assert.equal(creditCards.length, 1);
    276  do_check_credit_card_matches(
    277    creditCards[0],
    278    TEST_CREDIT_CARD_WITH_BILLING_ADDRESS
    279  );
    280 });
    281 
    282 add_task(async function test_update() {
    283  // Test assumes that when an entry is saved a second time, it's last modified date will
    284  // be different from the first. With high values of precision reduction, we execute too
    285  // fast for that to be true.
    286  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
    287  Preferences.set("privacy.reduceTimerPrecision", false);
    288 
    289  registerCleanupFunction(function () {
    290    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
    291  });
    292 
    293  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    294  await prepareTestCreditCards(path);
    295 
    296  let profileStorage = new FormAutofillStorage(path);
    297  await profileStorage.initialize();
    298 
    299  let creditCards = await profileStorage.creditCards.getAll();
    300  let guid = creditCards[1].guid;
    301  let timeLastModified = creditCards[1].timeLastModified;
    302 
    303  let onChanged = TestUtils.topicObserved(
    304    "formautofill-storage-changed",
    305    (subject, data) =>
    306      data == "update" &&
    307      subject.wrappedJSObject.guid == guid &&
    308      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    309  );
    310 
    311  Assert.notEqual(creditCards[1]["cc-name"], undefined);
    312  await profileStorage.creditCards.update(guid, TEST_CREDIT_CARD_3);
    313  await onChanged;
    314  await profileStorage._saveImmediately();
    315 
    316  profileStorage = new FormAutofillStorage(path);
    317  await profileStorage.initialize();
    318 
    319  let creditCard = await profileStorage.creditCards.get(guid);
    320 
    321  Assert.equal(creditCard["cc-name"], undefined);
    322  Assert.notEqual(creditCard.timeLastModified, timeLastModified);
    323  do_check_credit_card_matches(creditCard, TEST_CREDIT_CARD_3);
    324 
    325  // Empty string should be deleted while updating.
    326  await profileStorage.creditCards.update(
    327    profileStorage.creditCards._data[0].guid,
    328    TEST_CREDIT_CARD_WITH_EMPTY_FIELD
    329  );
    330  creditCard = profileStorage.creditCards._data[0];
    331  Assert.equal(
    332    creditCard["cc-exp-month"],
    333    TEST_CREDIT_CARD_WITH_EMPTY_FIELD["cc-exp-month"]
    334  );
    335  Assert.equal(creditCard["cc-name"], undefined);
    336  Assert.equal(creditCard["cc-type"], "amex");
    337  Assert.equal(creditCard.billingAddressGUID, undefined);
    338 
    339  // Empty computed fields shouldn't cause any problem.
    340  await profileStorage.creditCards.update(
    341    profileStorage.creditCards._data[0].guid,
    342    TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD,
    343    false
    344  );
    345  creditCard = profileStorage.creditCards._data[0];
    346  Assert.equal(
    347    creditCard["cc-number"],
    348    CreditCard.getLongMaskedNumber(
    349      TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD["cc-number"]
    350    )
    351  );
    352  await profileStorage.creditCards.update(
    353    profileStorage.creditCards._data[1].guid,
    354    TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD,
    355    true
    356  );
    357  creditCard = profileStorage.creditCards._data[1];
    358  Assert.equal(
    359    creditCard["cc-number"],
    360    CreditCard.getLongMaskedNumber(
    361      TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD["cc-number"]
    362    )
    363  );
    364 
    365  // Decryption failure of existing record should not prevent it from being updated.
    366  creditCard = profileStorage.creditCards._data[0];
    367  creditCard["cc-number-encrypted"] = "INVALID";
    368  await profileStorage.creditCards.update(
    369    profileStorage.creditCards._data[0].guid,
    370    TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD,
    371    false
    372  );
    373  creditCard = profileStorage.creditCards._data[0];
    374  Assert.equal(
    375    creditCard["cc-number"],
    376    CreditCard.getLongMaskedNumber(
    377      TEST_CREDIT_CARD_WITH_EMPTY_COMPUTED_FIELD["cc-number"]
    378    )
    379  );
    380 
    381  await Assert.rejects(
    382    profileStorage.creditCards.update("INVALID_GUID", TEST_CREDIT_CARD_3),
    383    /No matching record\./
    384  );
    385 
    386  await Assert.rejects(
    387    profileStorage.creditCards.update(guid, {}),
    388    /Record contains no valid field\./
    389  );
    390 
    391  await Assert.rejects(
    392    profileStorage.creditCards.update(
    393      guid,
    394      TEST_CREDIT_CARD_EMPTY_AFTER_NORMALIZE
    395    ),
    396    /Record contains no valid field\./
    397  );
    398 
    399  await profileStorage.creditCards.update(guid, TEST_CREDIT_CARD_1);
    400  await Assert.rejects(
    401    profileStorage.creditCards.update(
    402      guid,
    403      TEST_CREDIT_CARD_EMPTY_AFTER_UPDATE_CREDIT_CARD_1
    404    ),
    405    /Record contains no valid field\./
    406  );
    407 });
    408 
    409 add_task(async function test_validate() {
    410  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    411 
    412  let profileStorage = new FormAutofillStorage(path);
    413  await profileStorage.initialize();
    414 
    415  await profileStorage.creditCards.add(
    416    TEST_CREDIT_CARD_WITH_INVALID_EXPIRY_DATE
    417  );
    418  await profileStorage.creditCards.add(TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR);
    419  await profileStorage.creditCards.add(
    420    TEST_CREDIT_CARD_WITH_SPACES_BETWEEN_DIGITS
    421  );
    422  let creditCards = await profileStorage.creditCards.getAll();
    423 
    424  Assert.equal(creditCards[0]["cc-exp-month"], undefined);
    425  Assert.equal(creditCards[0]["cc-exp-year"], undefined);
    426  Assert.equal(creditCards[0]["cc-exp"], undefined);
    427 
    428  let month = TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR["cc-exp-month"];
    429  let year =
    430    parseInt(TEST_CREDIT_CARD_WITH_2_DIGITS_YEAR["cc-exp-year"], 10) + 2000;
    431  Assert.equal(creditCards[1]["cc-exp-month"], month);
    432  Assert.equal(creditCards[1]["cc-exp-year"], year);
    433  Assert.equal(
    434    creditCards[1]["cc-exp"],
    435    year + "-" + month.toString().padStart(2, "0")
    436  );
    437 
    438  Assert.equal(creditCards[2]["cc-number"].length, 16);
    439 });
    440 
    441 add_task(async function test_notifyUsed() {
    442  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    443  await prepareTestCreditCards(path);
    444 
    445  let profileStorage = new FormAutofillStorage(path);
    446  await profileStorage.initialize();
    447 
    448  let creditCards = await profileStorage.creditCards.getAll();
    449  let guid = creditCards[1].guid;
    450  let timeLastUsed = creditCards[1].timeLastUsed;
    451  let timesUsed = creditCards[1].timesUsed;
    452 
    453  let onChanged = TestUtils.topicObserved(
    454    "formautofill-storage-changed",
    455    (subject, data) =>
    456      data == "notifyUsed" &&
    457      subject.wrappedJSObject.collectionName == COLLECTION_NAME &&
    458      subject.wrappedJSObject.guid == guid
    459  );
    460 
    461  profileStorage.creditCards.notifyUsed(guid);
    462  await onChanged;
    463  await profileStorage._saveImmediately();
    464 
    465  profileStorage = new FormAutofillStorage(path);
    466  await profileStorage.initialize();
    467 
    468  let creditCard = await profileStorage.creditCards.get(guid);
    469 
    470  Assert.equal(creditCard.timesUsed, timesUsed + 1);
    471  Assert.notEqual(creditCard.timeLastUsed, timeLastUsed);
    472 });
    473 
    474 add_task(async function test_remove() {
    475  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    476  await prepareTestCreditCards(path);
    477 
    478  let profileStorage = new FormAutofillStorage(path);
    479  await profileStorage.initialize();
    480 
    481  let creditCards = await profileStorage.creditCards.getAll();
    482  let guid = creditCards[1].guid;
    483 
    484  let onChanged = TestUtils.topicObserved(
    485    "formautofill-storage-changed",
    486    (subject, data) =>
    487      data == "remove" &&
    488      subject.wrappedJSObject.guid == guid &&
    489      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    490  );
    491 
    492  Assert.equal(creditCards.length, 2);
    493 
    494  profileStorage.creditCards.remove(guid);
    495  await onChanged;
    496  await profileStorage._saveImmediately();
    497 
    498  profileStorage = new FormAutofillStorage(path);
    499  await profileStorage.initialize();
    500 
    501  creditCards = await profileStorage.creditCards.getAll();
    502 
    503  Assert.equal(creditCards.length, 1);
    504 
    505  Assert.equal(await profileStorage.creditCards.get(guid), null);
    506 });
    507 
    508 add_task(async function test_getDuplicateRecords() {
    509  let profileStorage = await initProfileStorage(
    510    TEST_STORE_FILE_NAME,
    511    [TEST_CREDIT_CARD_3],
    512    "creditCards"
    513  );
    514  let guid = profileStorage.creditCards._data[0].guid;
    515 
    516  // Absolutely a duplicate.
    517  let getDuplicateRecords =
    518    profileStorage.creditCards.getDuplicateRecords(TEST_CREDIT_CARD_3);
    519  let dupe = (await getDuplicateRecords.next()).value;
    520  Assert.equal(dupe.guid, guid);
    521 
    522  // Absolutely not a duplicate.
    523  getDuplicateRecords =
    524    profileStorage.creditCards.getDuplicateRecords(TEST_CREDIT_CARD_1);
    525  dupe = (await getDuplicateRecords.next()).value;
    526  Assert.equal(dupe, null);
    527 
    528  // Subset with the same number is a duplicate.
    529  let record = Object.assign({}, TEST_CREDIT_CARD_3);
    530  delete record["cc-exp-month"];
    531  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    532  dupe = (await getDuplicateRecords.next()).value;
    533  Assert.equal(dupe.guid, guid);
    534 
    535  // Superset with the same number is a duplicate.
    536  record = Object.assign({}, TEST_CREDIT_CARD_3);
    537  record["cc-name"] = "John Doe";
    538  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    539  dupe = (await getDuplicateRecords.next()).value;
    540  Assert.equal(dupe.guid, guid);
    541 
    542  // Numbers with the same last 4 digits shouldn't be treated as a duplicate.
    543  record = Object.assign({}, TEST_CREDIT_CARD_3);
    544  let last4Digits = record["cc-number"].substr(-4);
    545  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    546  dupe = (await getDuplicateRecords.next()).value;
    547  Assert.equal(dupe.guid, guid);
    548 
    549  // This number differs from TEST_CREDIT_CARD_3 by swapping the order of the
    550  // 09 and 90 adjacent digits, which is still a valid credit card number.
    551  record["cc-number"] = "358999378390" + last4Digits;
    552 
    553  // We don't treat numbers with the same last 4 digits as a duplicate.
    554  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    555  dupe = (await getDuplicateRecords.next()).value;
    556  Assert.equal(dupe, null);
    557 });
    558 
    559 add_task(async function test_getDuplicateRecordsMatch() {
    560  let profileStorage = await initProfileStorage(
    561    TEST_STORE_FILE_NAME,
    562    [TEST_CREDIT_CARD_2],
    563    "creditCards"
    564  );
    565  let guid = profileStorage.creditCards._data[0].guid;
    566 
    567  // Absolutely a duplicate.
    568  let getDuplicateRecords =
    569    profileStorage.creditCards.getDuplicateRecords(TEST_CREDIT_CARD_2);
    570  let dupe = (await getDuplicateRecords.next()).value;
    571  Assert.equal(dupe.guid, guid);
    572 
    573  // Absolutely not a duplicate.
    574  getDuplicateRecords =
    575    profileStorage.creditCards.getDuplicateRecords(TEST_CREDIT_CARD_1);
    576  dupe = (await getDuplicateRecords.next()).value;
    577  Assert.equal(dupe, null);
    578 
    579  record = Object.assign({}, TEST_CREDIT_CARD_2);
    580 
    581  // We change month from `1` to `2`
    582  record["cc-exp-month"] = 2;
    583  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    584  dupe = (await getDuplicateRecords.next()).value;
    585  Assert.equal(dupe.guid, guid);
    586 
    587  // We change year from `2000` to `2001`
    588  record["cc-exp-year"] = 2001;
    589  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    590  dupe = (await getDuplicateRecords.next()).value;
    591  Assert.equal(dupe.guid, guid);
    592 
    593  // New name, same card
    594  record["cc-name"] = "John Doe";
    595  getDuplicateRecords = profileStorage.creditCards.getDuplicateRecords(record);
    596  dupe = (await getDuplicateRecords.next()).value;
    597  Assert.equal(dupe.guid, guid);
    598 });
    599 
    600 add_task(async function test_getMatchRecord() {
    601  let profileStorage = await initProfileStorage(
    602    TEST_STORE_FILE_NAME,
    603    [TEST_CREDIT_CARD_2],
    604    "creditCards"
    605  );
    606  let guid = profileStorage.creditCards._data[0].guid;
    607 
    608  const TEST_FIELDS = {
    609    "cc-name": "John Doe",
    610    "cc-exp-month": 10,
    611    "cc-exp-year": 2001,
    612  };
    613 
    614  // Absolutely a match.
    615  let getMatchRecords =
    616    profileStorage.creditCards.getMatchRecords(TEST_CREDIT_CARD_2);
    617  let match = (await getMatchRecords.next()).value;
    618  Assert.equal(match.guid, guid);
    619 
    620  // Subset with the same number is a match.
    621  for (const field of Object.keys(TEST_FIELDS)) {
    622    let record = Object.assign({}, TEST_CREDIT_CARD_2);
    623    delete record[field];
    624    getMatchRecords = profileStorage.creditCards.getMatchRecords(record);
    625    match = (await getMatchRecords.next()).value;
    626    Assert.equal(match.guid, guid);
    627  }
    628 
    629  // Subset with different number is not a match.
    630  for (const field of Object.keys(TEST_FIELDS)) {
    631    let record = Object.assign({}, TEST_CREDIT_CARD_2, {
    632      "cc-number": TEST_CREDIT_CARD_1["cc-number"],
    633    });
    634    delete record[field];
    635    getMatchRecords = profileStorage.creditCards.getMatchRecords(record);
    636    match = (await getMatchRecords.next()).value;
    637    Assert.equal(match, null);
    638  }
    639 
    640  // Superset with the same number is not a match.
    641  for (const [field, value] of Object.entries(TEST_FIELDS)) {
    642    let record = Object.assign({}, TEST_CREDIT_CARD_2);
    643    record[field] = value;
    644    getMatchRecords = profileStorage.creditCards.getMatchRecords(record);
    645    match = (await getMatchRecords.next()).value;
    646    Assert.equal(match, null);
    647  }
    648 
    649  // Superset with different number is not a match.
    650  for (const [field, value] of Object.entries(TEST_FIELDS)) {
    651    let record = Object.assign({}, TEST_CREDIT_CARD_2, {
    652      "cc-number": TEST_CREDIT_CARD_1["cc-number"],
    653    });
    654    record[field] = value;
    655    getMatchRecords = profileStorage.creditCards.getMatchRecords(record);
    656    match = (await getMatchRecords.next()).value;
    657    Assert.equal(match, null);
    658  }
    659 });
    660 
    661 add_task(async function test_creditCardFillDisabled() {
    662  Services.prefs.setBoolPref(
    663    "extensions.formautofill.creditCards.enabled",
    664    false
    665  );
    666 
    667  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    668  let profileStorage = new FormAutofillStorage(path);
    669  await profileStorage.initialize();
    670 
    671  Assert.equal(
    672    !!profileStorage.creditCards,
    673    true,
    674    "credit card records initialized and available."
    675  );
    676 
    677  Services.prefs.setBoolPref(
    678    "extensions.formautofill.creditCards.enabled",
    679    true
    680  );
    681 });