tor-browser

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

test_addressRecords.js (12828B)


      1 /**
      2 * Tests FormAutofillStorage object with addresses records.
      3 */
      4 
      5 "use strict";
      6 
      7 const TEST_STORE_FILE_NAME = "test-profile.json";
      8 const COLLECTION_NAME = "addresses";
      9 
     10 const TEST_ADDRESS_1 = {
     11  name: "Timothy John Berners-Lee",
     12  organization: "World Wide Web Consortium",
     13  "street-address": "32 Vassar Street\nMIT Room 32-G524",
     14  "address-level2": "Cambridge",
     15  "address-level1": "MA",
     16  "postal-code": "02139",
     17  country: "US",
     18  tel: "+16172535702",
     19  email: "timbl@w3.org",
     20  "unknown-1": "an unknown field from another client",
     21 };
     22 
     23 const TEST_ADDRESS_2 = {
     24  "street-address": "Some Address",
     25  country: "US",
     26 };
     27 
     28 const TEST_ADDRESS_3 = {
     29  name: "Timothy Berners-Lee",
     30  "street-address": "Other Address",
     31  "postal-code": "12345",
     32 };
     33 
     34 const TEST_ADDRESS_4 = {
     35  name: "Timothy Berners-Lee",
     36  "street-address": "32 Vassar Street",
     37  "postal-code": "12345",
     38  email: "timbl@w3.org",
     39 };
     40 
     41 const TEST_ADDRESS_WITH_EMPTY_FIELD = {
     42  name: "Tim Berners",
     43  "street-address": "",
     44 };
     45 
     46 const TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD = {
     47  "given-name": "",
     48  "additional-name": "",
     49  "family-name": "",
     50  "address-line1": "",
     51  "address-line2": "",
     52  "address-line3": "",
     53  "country-name": "",
     54  "tel-country-code": "",
     55  "tel-national": "",
     56  "tel-area-code": "",
     57  "tel-local": "",
     58  "tel-local-prefix": "",
     59  "tel-local-suffix": "",
     60  email: "timbl@w3.org",
     61 };
     62 
     63 const TEST_ADDRESS_WITH_INVALID_FIELD = {
     64  "street-address": "Another Address",
     65  email: { email: "invalidemail" },
     66 };
     67 
     68 const TEST_ADDRESS_EMPTY_AFTER_NORMALIZE = {
     69  country: "XXXXXX",
     70 };
     71 
     72 ChromeUtils.defineESModuleGetters(this, {
     73  Preferences: "resource://gre/modules/Preferences.sys.mjs",
     74 });
     75 
     76 let do_check_record_matches = (recordWithMeta, record) => {
     77  for (let key in record) {
     78    Assert.equal(recordWithMeta[key], record[key]);
     79  }
     80 };
     81 
     82 add_task(async function test_initialize() {
     83  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME);
     84 
     85  Assert.equal(profileStorage._store.data.version, 1);
     86  Assert.equal(profileStorage._store.data.addresses.length, 0);
     87 
     88  let data = profileStorage._store.data;
     89  Assert.deepEqual(data.addresses, []);
     90 
     91  await profileStorage._saveImmediately();
     92 
     93  profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME);
     94 
     95  Assert.deepEqual(profileStorage._store.data, data);
     96  for (let { _sync } of profileStorage._store.data.addresses) {
     97    Assert.ok(_sync);
     98    Assert.equal(_sync.changeCounter, 1);
     99  }
    100 });
    101 
    102 add_task(async function test_getAll() {
    103  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    104    TEST_ADDRESS_1,
    105    TEST_ADDRESS_2,
    106    TEST_ADDRESS_4,
    107  ]);
    108 
    109  let addresses = await profileStorage.addresses.getAll();
    110 
    111  Assert.equal(addresses.length, 3);
    112  do_check_record_matches(addresses[0], TEST_ADDRESS_1);
    113  do_check_record_matches(addresses[1], TEST_ADDRESS_2);
    114 
    115  // Check computed fields.
    116  Assert.equal(addresses[0]["given-name"], "Timothy");
    117  Assert.equal(addresses[0]["additional-name"], "John");
    118  Assert.equal(addresses[0]["family-name"], "Berners-Lee");
    119  Assert.equal(addresses[0]["address-line1"], "32 Vassar Street");
    120  Assert.equal(addresses[0]["address-line2"], "MIT Room 32-G524");
    121  // Until we resolve Bug 1964405 with computing house numbers from addresses containing newline characters, we'll test it using an additional profile.
    122  // Assert.equal(addresses[0]["address-housenumber"], 32); <- This is what should be computed.
    123  Assert.equal(addresses[2]["address-housenumber"], "32");
    124 
    125  // Test with rawData set.
    126  addresses = await profileStorage.addresses.getAll({ rawData: true });
    127  // For backward-compatibility, we keep *-name fields when `rawData` is true
    128  Assert.equal(addresses[0]["given-name"], "Timothy");
    129  Assert.equal(addresses[0]["additional-name"], "John");
    130  Assert.equal(addresses[0]["family-name"], "Berners-Lee");
    131  Assert.equal(addresses[0]["address-line1"], undefined);
    132  Assert.equal(addresses[0]["address-line2"], undefined);
    133 
    134  // Modifying output shouldn't affect the storage.
    135  addresses[0].organization = "test";
    136  do_check_record_matches(
    137    (await profileStorage.addresses.getAll())[0],
    138    TEST_ADDRESS_1
    139  );
    140 });
    141 
    142 add_task(async function test_get() {
    143  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    144    TEST_ADDRESS_1,
    145    TEST_ADDRESS_2,
    146  ]);
    147 
    148  let addresses = await profileStorage.addresses.getAll();
    149  let guid = addresses[0].guid;
    150 
    151  let address = await profileStorage.addresses.get(guid);
    152  do_check_record_matches(address, TEST_ADDRESS_1);
    153 
    154  // Test with rawData set.
    155  address = await profileStorage.addresses.get(guid, { rawData: true });
    156  // For backward-compatibility, we keep *-name fields when `rawData` is true
    157  Assert.equal(address["given-name"], "Timothy");
    158  Assert.equal(address["additional-name"], "John");
    159  Assert.equal(address["family-name"], "Berners-Lee");
    160  Assert.equal(address["address-line1"], undefined);
    161  Assert.equal(address["address-line2"], undefined);
    162 
    163  // Modifying output shouldn't affect the storage.
    164  address.organization = "test";
    165  do_check_record_matches(
    166    await profileStorage.addresses.get(guid),
    167    TEST_ADDRESS_1
    168  );
    169 
    170  Assert.equal(await profileStorage.addresses.get("INVALID_GUID"), null);
    171 });
    172 
    173 add_task(async function test_add() {
    174  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    175    TEST_ADDRESS_1,
    176    TEST_ADDRESS_2,
    177  ]);
    178 
    179  let addresses = await profileStorage.addresses.getAll();
    180 
    181  Assert.equal(addresses.length, 2);
    182 
    183  do_check_record_matches(addresses[0], TEST_ADDRESS_1);
    184  do_check_record_matches(addresses[1], TEST_ADDRESS_2);
    185 
    186  Assert.notEqual(addresses[0].guid, undefined);
    187  Assert.equal(addresses[0].version, 1);
    188  Assert.notEqual(addresses[0].timeCreated, undefined);
    189  Assert.equal(addresses[0].timeLastModified, addresses[0].timeCreated);
    190  Assert.equal(addresses[0].timeLastUsed, 0);
    191  Assert.equal(addresses[0].timesUsed, 0);
    192 
    193  // Empty string should be deleted before saving.
    194  await profileStorage.addresses.add(TEST_ADDRESS_WITH_EMPTY_FIELD);
    195  let address = profileStorage.addresses._data[2];
    196  Assert.equal(address.name, TEST_ADDRESS_WITH_EMPTY_FIELD.name);
    197  Assert.equal(address["street-address"], undefined);
    198 
    199  // Empty computed fields shouldn't cause any problem.
    200  await profileStorage.addresses.add(TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD);
    201  address = profileStorage.addresses._data[3];
    202  Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email);
    203 
    204  await Assert.rejects(
    205    profileStorage.addresses.add(TEST_ADDRESS_WITH_INVALID_FIELD),
    206    /"email" contains invalid data type: object/
    207  );
    208 
    209  await Assert.rejects(
    210    profileStorage.addresses.add({}),
    211    /Record contains no valid field\./
    212  );
    213 
    214  await Assert.rejects(
    215    profileStorage.addresses.add(TEST_ADDRESS_EMPTY_AFTER_NORMALIZE),
    216    /Record contains no valid field\./
    217  );
    218 });
    219 
    220 add_task(async function test_update() {
    221  // Test assumes that when an entry is saved a second time, it's last modified date will
    222  // be different from the first. With high values of precision reduction, we execute too
    223  // fast for that to be true.
    224  let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
    225  Preferences.set("privacy.reduceTimerPrecision", false);
    226 
    227  registerCleanupFunction(function () {
    228    Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
    229  });
    230 
    231  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    232    TEST_ADDRESS_1,
    233    TEST_ADDRESS_2,
    234  ]);
    235 
    236  let addresses = await profileStorage.addresses.getAll();
    237  let guid = addresses[1].guid;
    238  // We need to cheat a little due to race conditions of Date.now() when
    239  // we're running these tests, so we subtract one and test accordingly
    240  // in the times Date.now() returns the same timestamp
    241  let timeLastModified = addresses[1].timeLastModified - 1;
    242 
    243  let onChanged = TestUtils.topicObserved(
    244    "formautofill-storage-changed",
    245    (subject, data) =>
    246      data == "update" &&
    247      subject.wrappedJSObject.guid == guid &&
    248      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    249  );
    250 
    251  Assert.notEqual(addresses[1].country, undefined);
    252 
    253  await profileStorage.addresses.update(guid, TEST_ADDRESS_3);
    254  await onChanged;
    255  await profileStorage._saveImmediately();
    256 
    257  profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below.
    258 
    259  let address = await profileStorage.addresses.get(guid, { rawData: true });
    260 
    261  Assert.equal(address.country, "US");
    262  Assert.greater(address.timeLastModified, timeLastModified);
    263  do_check_record_matches(address, TEST_ADDRESS_3);
    264  Assert.equal(getSyncChangeCounter(profileStorage.addresses, guid), 1);
    265 
    266  // Test preserveOldProperties parameter and field with empty string.
    267  await profileStorage.addresses.update(
    268    guid,
    269    TEST_ADDRESS_WITH_EMPTY_FIELD,
    270    true
    271  );
    272  await onChanged;
    273  await profileStorage._saveImmediately();
    274 
    275  profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below.
    276 
    277  address = await profileStorage.addresses.get(guid, { rawData: true });
    278 
    279  Assert.equal(address.name, "Tim Berners");
    280  Assert.equal(address["street-address"], undefined);
    281  Assert.equal(address["postal-code"], "12345");
    282  Assert.notEqual(address.timeLastModified, timeLastModified);
    283  Assert.equal(getSyncChangeCounter(profileStorage.addresses, guid), 2);
    284 
    285  // Empty string should be deleted while updating.
    286  await profileStorage.addresses.update(
    287    profileStorage.addresses._data[0].guid,
    288    TEST_ADDRESS_WITH_EMPTY_FIELD
    289  );
    290  address = profileStorage.addresses._data[0];
    291  Assert.equal(address.name, TEST_ADDRESS_WITH_EMPTY_FIELD.name);
    292  Assert.equal(address["street-address"], undefined);
    293  Assert.equal(address[("unknown-1", "an unknown field from another client")]);
    294 
    295  // Empty computed fields shouldn't cause any problem.
    296  await profileStorage.addresses.update(
    297    profileStorage.addresses._data[0].guid,
    298    TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD,
    299    false
    300  );
    301  address = profileStorage.addresses._data[0];
    302  Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email);
    303  await profileStorage.addresses.update(
    304    profileStorage.addresses._data[1].guid,
    305    TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD,
    306    true
    307  );
    308  address = profileStorage.addresses._data[1];
    309  Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email);
    310 
    311  await Assert.rejects(
    312    profileStorage.addresses.update("INVALID_GUID", TEST_ADDRESS_3),
    313    /No matching record\./
    314  );
    315 
    316  await Assert.rejects(
    317    profileStorage.addresses.update(guid, TEST_ADDRESS_WITH_INVALID_FIELD),
    318    /"email" contains invalid data type: object/
    319  );
    320 
    321  await Assert.rejects(
    322    profileStorage.addresses.update(guid, {}),
    323    /Record contains no valid field\./
    324  );
    325 
    326  await Assert.rejects(
    327    profileStorage.addresses.update(guid, TEST_ADDRESS_EMPTY_AFTER_NORMALIZE),
    328    /Record contains no valid field\./
    329  );
    330 
    331  profileStorage.addresses.update(guid, TEST_ADDRESS_2);
    332 });
    333 
    334 add_task(async function test_notifyUsed() {
    335  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    336    TEST_ADDRESS_1,
    337    TEST_ADDRESS_2,
    338  ]);
    339 
    340  let addresses = await profileStorage.addresses.getAll();
    341  let guid = addresses[1].guid;
    342  let timeLastUsed = addresses[1].timeLastUsed;
    343  let timesUsed = addresses[1].timesUsed;
    344 
    345  profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below.
    346  let changeCounter = getSyncChangeCounter(profileStorage.addresses, guid);
    347 
    348  let onChanged = TestUtils.topicObserved(
    349    "formautofill-storage-changed",
    350    (subject, data) =>
    351      data == "notifyUsed" &&
    352      subject.wrappedJSObject.guid == guid &&
    353      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    354  );
    355 
    356  profileStorage.addresses.notifyUsed(guid);
    357  await onChanged;
    358 
    359  let address = await profileStorage.addresses.get(guid);
    360 
    361  Assert.equal(address.timesUsed, timesUsed + 1);
    362  Assert.notEqual(address.timeLastUsed, timeLastUsed);
    363 
    364  // Using a record should not bump its change counter.
    365  Assert.equal(
    366    getSyncChangeCounter(profileStorage.addresses, guid),
    367    changeCounter
    368  );
    369 });
    370 
    371 add_task(async function test_remove() {
    372  let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [
    373    TEST_ADDRESS_1,
    374    TEST_ADDRESS_2,
    375  ]);
    376 
    377  let addresses = await profileStorage.addresses.getAll();
    378  let guid = addresses[1].guid;
    379 
    380  let onChanged = TestUtils.topicObserved(
    381    "formautofill-storage-changed",
    382    (subject, data) =>
    383      data == "remove" &&
    384      subject.wrappedJSObject.guid == guid &&
    385      subject.wrappedJSObject.collectionName == COLLECTION_NAME
    386  );
    387 
    388  Assert.equal(addresses.length, 2);
    389 
    390  profileStorage.addresses.remove(guid);
    391  await onChanged;
    392 
    393  addresses = await profileStorage.addresses.getAll();
    394 
    395  Assert.equal(addresses.length, 1);
    396 
    397  Assert.equal(await profileStorage.addresses.get(guid), null);
    398 });