From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../formautofill/test/unit/test_addressRecords.js | 392 +++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 browser/extensions/formautofill/test/unit/test_addressRecords.js (limited to 'browser/extensions/formautofill/test/unit/test_addressRecords.js') diff --git a/browser/extensions/formautofill/test/unit/test_addressRecords.js b/browser/extensions/formautofill/test/unit/test_addressRecords.js new file mode 100644 index 0000000000..a2d7ce23b5 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/test_addressRecords.js @@ -0,0 +1,392 @@ +/** + * Tests FormAutofillStorage object with addresses records. + */ + +"use strict"; + +const TEST_STORE_FILE_NAME = "test-profile.json"; +const COLLECTION_NAME = "addresses"; + +const TEST_ADDRESS_1 = { + name: "Timothy John Berners-Lee", + organization: "World Wide Web Consortium", + "street-address": "32 Vassar Street\nMIT Room 32-G524", + "address-level2": "Cambridge", + "address-level1": "MA", + "postal-code": "02139", + country: "US", + tel: "+16172535702", + email: "timbl@w3.org", + "unknown-1": "an unknown field from another client", +}; + +const TEST_ADDRESS_2 = { + "street-address": "Some Address", + country: "US", +}; + +const TEST_ADDRESS_3 = { + name: "Timothy Berners-Lee", + "street-address": "Other Address", + "postal-code": "12345", +}; + +const TEST_ADDRESS_WITH_EMPTY_FIELD = { + name: "Tim Berners", + "street-address": "", +}; + +const TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD = { + "given-name": "", + "additional-name": "", + "family-name": "", + "address-line1": "", + "address-line2": "", + "address-line3": "", + "country-name": "", + "tel-country-code": "", + "tel-national": "", + "tel-area-code": "", + "tel-local": "", + "tel-local-prefix": "", + "tel-local-suffix": "", + email: "timbl@w3.org", +}; + +const TEST_ADDRESS_WITH_INVALID_FIELD = { + "street-address": "Another Address", + email: { email: "invalidemail" }, +}; + +const TEST_ADDRESS_EMPTY_AFTER_NORMALIZE = { + country: "XXXXXX", +}; + +ChromeUtils.defineESModuleGetters(this, { + Preferences: "resource://gre/modules/Preferences.sys.mjs", +}); + +let do_check_record_matches = (recordWithMeta, record) => { + for (let key in record) { + Assert.equal(recordWithMeta[key], record[key]); + } +}; + +add_task(async function test_initialize() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME); + + Assert.equal(profileStorage._store.data.version, 1); + Assert.equal(profileStorage._store.data.addresses.length, 0); + + let data = profileStorage._store.data; + Assert.deepEqual(data.addresses, []); + + await profileStorage._saveImmediately(); + + profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME); + + Assert.deepEqual(profileStorage._store.data, data); + for (let { _sync } of profileStorage._store.data.addresses) { + Assert.ok(_sync); + Assert.equal(_sync.changeCounter, 1); + } +}); + +add_task(async function test_getAll() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + + Assert.equal(addresses.length, 2); + do_check_record_matches(addresses[0], TEST_ADDRESS_1); + do_check_record_matches(addresses[1], TEST_ADDRESS_2); + + // Check computed fields. + Assert.equal(addresses[0]["given-name"], "Timothy"); + Assert.equal(addresses[0]["additional-name"], "John"); + Assert.equal(addresses[0]["family-name"], "Berners-Lee"); + Assert.equal(addresses[0]["address-line1"], "32 Vassar Street"); + Assert.equal(addresses[0]["address-line2"], "MIT Room 32-G524"); + + // Test with rawData set. + addresses = await profileStorage.addresses.getAll({ rawData: true }); + // For backward-compatibility, we keep *-name fields when `rawData` is true + Assert.equal(addresses[0]["given-name"], "Timothy"); + Assert.equal(addresses[0]["additional-name"], "John"); + Assert.equal(addresses[0]["family-name"], "Berners-Lee"); + Assert.equal(addresses[0]["address-line1"], undefined); + Assert.equal(addresses[0]["address-line2"], undefined); + + // Modifying output shouldn't affect the storage. + addresses[0].organization = "test"; + do_check_record_matches( + (await profileStorage.addresses.getAll())[0], + TEST_ADDRESS_1 + ); +}); + +add_task(async function test_get() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + let guid = addresses[0].guid; + + let address = await profileStorage.addresses.get(guid); + do_check_record_matches(address, TEST_ADDRESS_1); + + // Test with rawData set. + address = await profileStorage.addresses.get(guid, { rawData: true }); + // For backward-compatibility, we keep *-name fields when `rawData` is true + Assert.equal(address["given-name"], "Timothy"); + Assert.equal(address["additional-name"], "John"); + Assert.equal(address["family-name"], "Berners-Lee"); + Assert.equal(address["address-line1"], undefined); + Assert.equal(address["address-line2"], undefined); + + // Modifying output shouldn't affect the storage. + address.organization = "test"; + do_check_record_matches( + await profileStorage.addresses.get(guid), + TEST_ADDRESS_1 + ); + + Assert.equal(await profileStorage.addresses.get("INVALID_GUID"), null); +}); + +add_task(async function test_add() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + + Assert.equal(addresses.length, 2); + + do_check_record_matches(addresses[0], TEST_ADDRESS_1); + do_check_record_matches(addresses[1], TEST_ADDRESS_2); + + Assert.notEqual(addresses[0].guid, undefined); + Assert.equal(addresses[0].version, 1); + Assert.notEqual(addresses[0].timeCreated, undefined); + Assert.equal(addresses[0].timeLastModified, addresses[0].timeCreated); + Assert.equal(addresses[0].timeLastUsed, 0); + Assert.equal(addresses[0].timesUsed, 0); + + // Empty string should be deleted before saving. + await profileStorage.addresses.add(TEST_ADDRESS_WITH_EMPTY_FIELD); + let address = profileStorage.addresses._data[2]; + Assert.equal(address.name, TEST_ADDRESS_WITH_EMPTY_FIELD.name); + Assert.equal(address["street-address"], undefined); + + // Empty computed fields shouldn't cause any problem. + await profileStorage.addresses.add(TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD); + address = profileStorage.addresses._data[3]; + Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email); + + await Assert.rejects( + profileStorage.addresses.add(TEST_ADDRESS_WITH_INVALID_FIELD), + /"email" contains invalid data type: object/ + ); + + await Assert.rejects( + profileStorage.addresses.add({}), + /Record contains no valid field\./ + ); + + await Assert.rejects( + profileStorage.addresses.add(TEST_ADDRESS_EMPTY_AFTER_NORMALIZE), + /Record contains no valid field\./ + ); +}); + +add_task(async function test_update() { + // Test assumes that when an entry is saved a second time, it's last modified date will + // be different from the first. With high values of precision reduction, we execute too + // fast for that to be true. + let timerPrecision = Preferences.get("privacy.reduceTimerPrecision"); + Preferences.set("privacy.reduceTimerPrecision", false); + + registerCleanupFunction(function () { + Preferences.set("privacy.reduceTimerPrecision", timerPrecision); + }); + + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + let guid = addresses[1].guid; + // We need to cheat a little due to race conditions of Date.now() when + // we're running these tests, so we subtract one and test accordingly + // in the times Date.now() returns the same timestamp + let timeLastModified = addresses[1].timeLastModified - 1; + + let onChanged = TestUtils.topicObserved( + "formautofill-storage-changed", + (subject, data) => + data == "update" && + subject.wrappedJSObject.guid == guid && + subject.wrappedJSObject.collectionName == COLLECTION_NAME + ); + + Assert.notEqual(addresses[1].country, undefined); + + await profileStorage.addresses.update(guid, TEST_ADDRESS_3); + await onChanged; + await profileStorage._saveImmediately(); + + profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below. + + let address = await profileStorage.addresses.get(guid, { rawData: true }); + + Assert.equal(address.country, "US"); + Assert.ok(address.timeLastModified > timeLastModified); + do_check_record_matches(address, TEST_ADDRESS_3); + Assert.equal(getSyncChangeCounter(profileStorage.addresses, guid), 1); + + // Test preserveOldProperties parameter and field with empty string. + await profileStorage.addresses.update( + guid, + TEST_ADDRESS_WITH_EMPTY_FIELD, + true + ); + await onChanged; + await profileStorage._saveImmediately(); + + profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below. + + address = await profileStorage.addresses.get(guid, { rawData: true }); + + Assert.equal(address.name, "Tim Berners"); + Assert.equal(address["street-address"], undefined); + Assert.equal(address["postal-code"], "12345"); + Assert.notEqual(address.timeLastModified, timeLastModified); + Assert.equal(getSyncChangeCounter(profileStorage.addresses, guid), 2); + + // Empty string should be deleted while updating. + await profileStorage.addresses.update( + profileStorage.addresses._data[0].guid, + TEST_ADDRESS_WITH_EMPTY_FIELD + ); + address = profileStorage.addresses._data[0]; + Assert.equal(address.name, TEST_ADDRESS_WITH_EMPTY_FIELD.name); + Assert.equal(address["street-address"], undefined); + Assert.equal(address[("unknown-1", "an unknown field from another client")]); + + // Empty computed fields shouldn't cause any problem. + await profileStorage.addresses.update( + profileStorage.addresses._data[0].guid, + TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD, + false + ); + address = profileStorage.addresses._data[0]; + Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email); + await profileStorage.addresses.update( + profileStorage.addresses._data[1].guid, + TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD, + true + ); + address = profileStorage.addresses._data[1]; + Assert.equal(address.email, TEST_ADDRESS_WITH_EMPTY_COMPUTED_FIELD.email); + + await Assert.rejects( + profileStorage.addresses.update("INVALID_GUID", TEST_ADDRESS_3), + /No matching record\./ + ); + + await Assert.rejects( + profileStorage.addresses.update(guid, TEST_ADDRESS_WITH_INVALID_FIELD), + /"email" contains invalid data type: object/ + ); + + await Assert.rejects( + profileStorage.addresses.update(guid, {}), + /Record contains no valid field\./ + ); + + await Assert.rejects( + profileStorage.addresses.update(guid, TEST_ADDRESS_EMPTY_AFTER_NORMALIZE), + /Record contains no valid field\./ + ); + + profileStorage.addresses.update(guid, TEST_ADDRESS_2); +}); + +add_task(async function test_notifyUsed() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + let guid = addresses[1].guid; + let timeLastUsed = addresses[1].timeLastUsed; + let timesUsed = addresses[1].timesUsed; + + profileStorage.addresses.pullSyncChanges(); // force sync metadata, which we check below. + let changeCounter = getSyncChangeCounter(profileStorage.addresses, guid); + + let onChanged = TestUtils.topicObserved( + "formautofill-storage-changed", + (subject, data) => + data == "notifyUsed" && + subject.wrappedJSObject.guid == guid && + subject.wrappedJSObject.collectionName == COLLECTION_NAME + ); + + profileStorage.addresses.notifyUsed(guid); + await onChanged; + + let address = await profileStorage.addresses.get(guid); + + Assert.equal(address.timesUsed, timesUsed + 1); + Assert.notEqual(address.timeLastUsed, timeLastUsed); + + // Using a record should not bump its change counter. + Assert.equal( + getSyncChangeCounter(profileStorage.addresses, guid), + changeCounter + ); + + Assert.throws( + () => profileStorage.addresses.notifyUsed("INVALID_GUID"), + /No matching record\./ + ); +}); + +add_task(async function test_remove() { + let profileStorage = await initProfileStorage(TEST_STORE_FILE_NAME, [ + TEST_ADDRESS_1, + TEST_ADDRESS_2, + ]); + + let addresses = await profileStorage.addresses.getAll(); + let guid = addresses[1].guid; + + let onChanged = TestUtils.topicObserved( + "formautofill-storage-changed", + (subject, data) => + data == "remove" && + subject.wrappedJSObject.guid == guid && + subject.wrappedJSObject.collectionName == COLLECTION_NAME + ); + + Assert.equal(addresses.length, 2); + + profileStorage.addresses.remove(guid); + await onChanged; + + addresses = await profileStorage.addresses.getAll(); + + Assert.equal(addresses.length, 1); + + Assert.equal(await profileStorage.addresses.get(guid), null); +}); -- cgit v1.2.3