gecko-dev/dom/contacts/tests/test_migration_chrome.js

337 lines
11 KiB
JavaScript

/* global
sendAsyncMessage,
addMessageListener,
indexedDB
*/
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
let imports = {};
Cu.import("resource://gre/modules/ContactDB.jsm", imports);
Cu.import("resource://gre/modules/ContactService.jsm", imports);
Cu.import("resource://gre/modules/Promise.jsm", imports);
Cu.importGlobalProperties(["indexedDB"]);
const {
STORE_NAME,
SAVED_GETALL_STORE_NAME,
REVISION_STORE,
DB_NAME,
ContactService,
} = imports;
// |const| will not work because
// it will make the Promise object immutable before assigning.
// Using Object.defineProperty() instead.
Object.defineProperty(this, "Promise", {
value: imports.Promise, writable: false, configurable: false
});
let DEBUG = false;
function debug(str) {
if (DEBUG){
dump("-*- TestMigrationChromeScript: " + str + "\n");
}
}
const DATA = {
12: {
SCHEMA: function createSchema12(db, transaction) {
let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
objectStore.createIndex("givenName", "properties.givenName", { multiEntry: true });
objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
objectStore.createIndex("givenNameLowerCase", "search.givenName", { multiEntry: true });
objectStore.createIndex("telLowerCase", "search.tel", { multiEntry: true });
objectStore.createIndex("emailLowerCase", "search.email", { multiEntry: true });
objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
objectStore.createIndex("category", "properties.category", { multiEntry: true });
objectStore.createIndex("email", "search.email", { multiEntry: true });
objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
db.createObjectStore(SAVED_GETALL_STORE_NAME);
db.createObjectStore(REVISION_STORE).put(0, "revision");
},
BAD: [
{
// this contact is bad because its "name" property is not an array and
// is the empty string (upgrade 16 to 17)
"properties": {
"name": "",
"email": [],
"url": [{
"type": ["source"],
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
}],
"category": ["gmail"],
"adr": [],
"tel": [{
"type": ["mobile"],
"value": "+7 123 456-78-90"
}],
"sex": "undefined",
"genderIdentity": "undefined"
},
"search": {
"givenName": [],
"familyName": [],
"email": [],
"category": ["gmail"],
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
"4567890","567890","67890","7890","890","90","0","81234567890"],
"exactTel": ["+71234567890"],
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
},
"updated": new Date("2013-07-27T16:47:40.974Z"),
"published": new Date("2013-07-27T16:47:40.974Z"),
"id": "bad-1"
},
{
// This contact is bad because its "name" property is not an array
// (upgrade 14 to 15)
"properties": {
"name": "name-bad-2",
"email": [],
"url": [{
"type": ["source"],
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
}],
"category": ["gmail"],
"adr": [],
"tel": [{
"type": ["mobile"],
"value": "+7 123 456-78-90"
}],
"sex": "undefined",
"genderIdentity": "undefined"
},
"search": {
"givenName": [],
"familyName": [],
"email": [],
"category": ["gmail"],
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
"4567890","567890","67890","7890","890","90","0","81234567890"],
"exactTel": ["+71234567890"],
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
},
"updated": new Date("2013-07-27T16:47:40.974Z"),
"published": new Date("2013-07-27T16:47:40.974Z"),
"id": "bad-2"
},
{
// This contact is bad because its bday property is a String (upgrade 15
// to 16), and its anniversary property is an empty string (upgrade 16
// to 17)
"properties": {
"name": ["name-bad-3"],
"email": [],
"url": [{
"type": ["source"],
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
}],
"category": ["gmail"],
"adr": [],
"tel": [{
"type": ["mobile"],
"value": "+7 123 456-78-90"
}],
"sex": "undefined",
"genderIdentity": "undefined",
"bday": "2013-07-27T16:47:40.974Z",
"anniversary": ""
},
"search": {
"givenName": [],
"familyName": [],
"email": [],
"category": ["gmail"],
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
"4567890","567890","67890","7890","890","90","0","81234567890"],
"exactTel": ["+71234567890"],
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
},
"updated": new Date("2013-07-27T16:47:40.974Z"),
"published": new Date("2013-07-27T16:47:40.974Z"),
"id": "bad-3"
},
{
// This contact is bad because its tel property has a tel.type null
// value (upgrade 16 to 17), and email.type not array value (upgrade 14
// to 15)
"properties": {
"name": ["name-bad-4"],
"email": [{
"value": "toto@toto.com",
"type": "home"
}],
"url": [{
"type": ["source"],
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
}],
"category": ["gmail"],
"adr": [],
"tel": [{
"type": null,
"value": "+7 123 456-78-90"
}],
"sex": "undefined",
"genderIdentity": "undefined"
},
"search": {
"givenName": [],
"familyName": [],
"email": [],
"category": ["gmail"],
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
"4567890","567890","67890","7890","890","90","0","81234567890"],
"exactTel": ["+71234567890"],
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
},
"updated": new Date("2013-07-27T16:47:40.974Z"),
"published": new Date("2013-07-27T16:47:40.974Z"),
"id": "bad-4"
}
],
GOOD: [
{
"properties": {
"name": ["name-good-1"],
"email": [],
"url": [{
"type": ["source"],
"value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
}],
"category": ["gmail"],
"adr": [],
"tel": [{
"type": ["mobile"],
"value": "+7 123 456-78-90"
}],
"sex": "undefined",
"genderIdentity": "undefined"
},
"search": {
"givenName": [],
"familyName": [],
"email": [],
"category": ["gmail"],
"tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
"4567890","567890","67890","7890","890","90","0","81234567890"],
"exactTel": ["+71234567890"],
"parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
},
"updated": new Date("2013-07-27T16:47:40.974Z"),
"published": new Date("2013-07-27T16:47:40.974Z"),
"id": "good-1"
}
]
}
};
function DataManager(version) {
if (!(version in DATA)) {
throw new Error("Version " + version + " can't be found in our test datas.");
}
this.version = version;
this.data = DATA[version];
}
DataManager.prototype = {
open: function() {
debug("opening for version " + this.version);
var deferred = Promise.defer();
let req = indexedDB.open(DB_NAME, this.version);
req.onupgradeneeded = function() {
let db = req.result;
let transaction = req.transaction;
this.createSchema(db, transaction);
this.addContacts(db, transaction);
}.bind(this);
req.onsuccess = function() {
debug("succeeded opening the db, let's close it now");
req.result.close();
deferred.resolve(this.contactsCount());
}.bind(this);
req.onerror = function() {
deferred.reject(this.error);
};
return deferred.promise;
},
createSchema: function(db, transaction) {
debug("createSchema for version " + this.version);
this.data.SCHEMA(db, transaction);
},
addContacts: function(db, transaction) {
debug("adding contacts for version " + this.version);
var os = transaction.objectStore(STORE_NAME);
this.data.GOOD.forEach(function(contact) {
os.put(contact);
});
this.data.BAD.forEach(function(contact) {
os.put(contact);
});
},
contactsCount: function() {
return this.data.BAD.length + this.data.GOOD.length;
}
};
DataManager.delete = function() {
debug("Deleting the database");
var deferred = Promise.defer();
/* forcibly close the db before deleting it */
ContactService._db.close();
var req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = function() {
debug("Successfully deleted!");
deferred.resolve();
};
req.onerror = function() {
debug("Not deleted, error is " + this.error.name);
deferred.reject(this.error);
};
req.onblocked = function() {
debug("Waiting for the current users");
};
return deferred.promise;
};
addMessageListener("createDB", function(version) {
// Promises help handling gracefully exceptions
Promise.resolve().then(function() {
return new DataManager(version);
}).then(function(manager) {
return manager.open();
}).then(function onSuccess(count) {
sendAsyncMessage("createDB.success", count);
}, function onError(err) {
sendAsyncMessage("createDB.error", "Failed to create the DB: " +
"(" + err.name + ") " + err.message);
});
});
addMessageListener("deleteDB", function() {
Promise.resolve().then(
DataManager.delete
).then(function onSuccess() {
sendAsyncMessage("deleteDB.success");
}, function onError(err) {
sendAsyncMessage("deleteDB.error", "Failed to delete the DB:" + err.name);
});
});