summaryrefslogtreecommitdiffstats
path: root/browser/extensions/formautofill/test/unit/test_storage_tombstones.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/extensions/formautofill/test/unit/test_storage_tombstones.js')
-rw-r--r--browser/extensions/formautofill/test/unit/test_storage_tombstones.js190
1 files changed, 190 insertions, 0 deletions
diff --git a/browser/extensions/formautofill/test/unit/test_storage_tombstones.js b/browser/extensions/formautofill/test/unit/test_storage_tombstones.js
new file mode 100644
index 0000000000..584dac8043
--- /dev/null
+++ b/browser/extensions/formautofill/test/unit/test_storage_tombstones.js
@@ -0,0 +1,190 @@
+/**
+ * Tests tombstones in address/creditcard records.
+ */
+
+"use strict";
+
+let FormAutofillStorage;
+add_setup(async () => {
+ ({ FormAutofillStorage } = ChromeUtils.importESModule(
+ "resource://autofill/FormAutofillStorage.sys.mjs"
+ ));
+});
+
+const TEST_STORE_FILE_NAME = "test-tombstones.json";
+
+const TEST_ADDRESS_1 = {
+ "given-name": "Timothy",
+ "additional-name": "John",
+ "family-name": "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: "+1 617 253 5702",
+ email: "timbl@w3.org",
+};
+
+const TEST_CC_1 = {
+ "cc-name": "John Doe",
+ "cc-number": "4111111111111111",
+ "cc-exp-month": 4,
+ "cc-exp-year": 2017,
+};
+
+let do_check_tombstone_record = profile => {
+ Assert.ok(profile.deleted);
+ Assert.deepEqual(
+ Object.keys(profile).sort(),
+ ["guid", "timeLastModified", "deleted"].sort()
+ );
+};
+
+// Like add_task, but actually adds 2 - one for addresses and one for cards.
+function add_storage_task(test_function) {
+ add_task(async function () {
+ let path = getTempFile(TEST_STORE_FILE_NAME).path;
+ let profileStorage = new FormAutofillStorage(path);
+ let testCC1 = Object.assign({}, TEST_CC_1);
+ await profileStorage.initialize();
+
+ for (let [storage, record] of [
+ [profileStorage.addresses, TEST_ADDRESS_1],
+ [profileStorage.creditCards, testCC1],
+ ]) {
+ await test_function(storage, record);
+ }
+ });
+}
+
+add_storage_task(async function test_simple_tombstone(storage, record) {
+ info("check simple tombstone semantics");
+
+ let guid = await storage.add(record);
+ Assert.equal((await storage.getAll()).length, 1);
+
+ storage.remove(guid);
+
+ // should be unable to get it normally.
+ Assert.equal(await storage.get(guid), null);
+ // and getAll should also not return it.
+ Assert.equal((await storage.getAll()).length, 0);
+
+ // but getAll allows us to access deleted items - but we didn't create
+ // a tombstone here, so even that will not get it.
+ let all = await storage.getAll({ includeDeleted: true });
+ Assert.equal(all.length, 0);
+});
+
+add_storage_task(async function test_simple_synctombstone(storage, record) {
+ info("check simple tombstone semantics for synced records");
+
+ let guid = await storage.add(record);
+ Assert.equal((await storage.getAll()).length, 1);
+
+ storage.pullSyncChanges(); // force sync metadata, which triggers tombstone behaviour.
+
+ storage.remove(guid);
+
+ // should be unable to get it normally.
+ Assert.equal(await storage.get(guid), null);
+ // and getAll should also not return it.
+ Assert.equal((await storage.getAll()).length, 0);
+
+ // but getAll allows us to access deleted items.
+ let all = await storage.getAll({ includeDeleted: true });
+ Assert.equal(all.length, 1);
+
+ do_check_tombstone_record(all[0]);
+
+ // a tombstone got from API should look exactly the same as it got from the
+ // disk (besides "_sync").
+ let tombstoneInDisk = Object.assign(
+ {},
+ storage._store.data[storage._collectionName][0]
+ );
+ delete tombstoneInDisk._sync;
+ do_check_tombstone_record(tombstoneInDisk);
+});
+
+add_storage_task(async function test_add_tombstone(storage, record) {
+ info("Should be able to add a new tombstone");
+ let guid = await storage.add({ guid: "test-guid-1", deleted: true });
+
+ // should be unable to get it normally.
+ Assert.equal(await storage.get(guid), null);
+ // and getAll should also not return it.
+ Assert.equal((await storage.getAll()).length, 0);
+
+ // but getAll allows us to access deleted items.
+ let all = await storage.getAll({ rawData: true, includeDeleted: true });
+ Assert.equal(all.length, 1);
+
+ do_check_tombstone_record(all[0]);
+
+ // a tombstone got from API should look exactly the same as it got from the
+ // disk (besides "_sync").
+ let tombstoneInDisk = Object.assign(
+ {},
+ storage._store.data[storage._collectionName][0]
+ );
+ delete tombstoneInDisk._sync;
+ do_check_tombstone_record(tombstoneInDisk);
+});
+
+add_storage_task(async function test_add_tombstone_without_guid(
+ storage,
+ record
+) {
+ info("Should not be able to add a new tombstone without specifying the guid");
+ await Assert.rejects(storage.add({ deleted: true }), /Record missing GUID/);
+ Assert.equal((await storage.getAll({ includeDeleted: true })).length, 0);
+});
+
+add_storage_task(async function test_add_tombstone_existing_guid(
+ storage,
+ record
+) {
+ info(
+ "Should not be able to add a new tombstone when a record with that ID exists"
+ );
+ let guid = await storage.add(record);
+ await Assert.rejects(
+ storage.add({ guid, deleted: true }),
+ /a record with this GUID already exists/
+ );
+
+ // same if the existing item is already a tombstone.
+ await storage.add({ guid: "test-guid-1", deleted: true });
+ await Assert.rejects(
+ storage.add({ guid: "test-guid-1", deleted: true }),
+ /a record with this GUID already exists/
+ );
+});
+
+add_storage_task(async function test_update_tombstone(storage, record) {
+ info("Updating a tombstone should fail");
+ let guid = await storage.add({ guid: "test-guid-1", deleted: true });
+ await Assert.rejects(storage.update(guid, {}), /No matching record./);
+});
+
+add_storage_task(async function test_remove_existing_tombstone(
+ storage,
+ record
+) {
+ info("Removing a record that's already a tombstone should be a no-op");
+ let guid = await storage.add({
+ guid: "test-guid-1",
+ deleted: true,
+ timeLastModified: 1234,
+ });
+
+ storage.remove(guid);
+ let all = await storage.getAll({ rawData: true, includeDeleted: true });
+ Assert.equal(all.length, 1);
+
+ do_check_tombstone_record(all[0]);
+ equal(all[0].timeLastModified, 1234); // should not be updated to now().
+});