dom/contacts/tests/test_migration_chrome.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/contacts/tests/test_migration_chrome.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,336 @@
     1.4 +/* global
     1.5 +    sendAsyncMessage,
     1.6 +    addMessageListener,
     1.7 +    indexedDB
     1.8 + */
     1.9 +"use strict";
    1.10 +
    1.11 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    1.12 +
    1.13 +let imports = {};
    1.14 +
    1.15 +Cu.import("resource://gre/modules/ContactDB.jsm", imports);
    1.16 +Cu.import("resource://gre/modules/ContactService.jsm", imports);
    1.17 +Cu.import("resource://gre/modules/Promise.jsm", imports);
    1.18 +Cu.importGlobalProperties(["indexedDB"]);
    1.19 +
    1.20 +const {
    1.21 +  STORE_NAME,
    1.22 +  SAVED_GETALL_STORE_NAME,
    1.23 +  REVISION_STORE,
    1.24 +  DB_NAME,
    1.25 +  ContactService,
    1.26 +} = imports;
    1.27 +// |const| will not work because
    1.28 +// it will make the Promise object immutable before assigning.
    1.29 +// Using Object.defineProperty() instead.
    1.30 +Object.defineProperty(this, "Promise", {
    1.31 +  value: imports.Promise, writable: false, configurable: false
    1.32 +});
    1.33 +
    1.34 +let DEBUG = false;
    1.35 +function debug(str) {
    1.36 +  if (DEBUG){
    1.37 +    dump("-*- TestMigrationChromeScript: " + str + "\n");
    1.38 +  }
    1.39 +}
    1.40 +
    1.41 +const DATA = {
    1.42 +  12: {
    1.43 +    SCHEMA: function createSchema12(db, transaction) {
    1.44 +      let objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
    1.45 +      objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
    1.46 +      objectStore.createIndex("givenName",  "properties.givenName",  { multiEntry: true });
    1.47 +      objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
    1.48 +      objectStore.createIndex("givenNameLowerCase",  "search.givenName",  { multiEntry: true });
    1.49 +      objectStore.createIndex("telLowerCase",        "search.tel",        { multiEntry: true });
    1.50 +      objectStore.createIndex("emailLowerCase",      "search.email",      { multiEntry: true });
    1.51 +      objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
    1.52 +      objectStore.createIndex("category", "properties.category", { multiEntry: true });
    1.53 +      objectStore.createIndex("email", "search.email", { multiEntry: true });
    1.54 +      objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
    1.55 +      db.createObjectStore(SAVED_GETALL_STORE_NAME);
    1.56 +      db.createObjectStore(REVISION_STORE).put(0, "revision");
    1.57 +    },
    1.58 +    BAD: [
    1.59 +      {
    1.60 +        // this contact is bad because its "name" property is not an array and
    1.61 +        // is the empty string (upgrade 16 to 17)
    1.62 +        "properties": {
    1.63 +          "name": "",
    1.64 +          "email": [],
    1.65 +          "url": [{
    1.66 +            "type": ["source"],
    1.67 +            "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
    1.68 +          }],
    1.69 +          "category": ["gmail"],
    1.70 +          "adr": [],
    1.71 +          "tel": [{
    1.72 +            "type": ["mobile"],
    1.73 +            "value": "+7 123 456-78-90"
    1.74 +          }],
    1.75 +          "sex": "undefined",
    1.76 +          "genderIdentity": "undefined"
    1.77 +        },
    1.78 +        "search": {
    1.79 +          "givenName": [],
    1.80 +          "familyName": [],
    1.81 +          "email": [],
    1.82 +          "category": ["gmail"],
    1.83 +          "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
    1.84 +            "4567890","567890","67890","7890","890","90","0","81234567890"],
    1.85 +          "exactTel": ["+71234567890"],
    1.86 +          "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
    1.87 +        },
    1.88 +        "updated": new Date("2013-07-27T16:47:40.974Z"),
    1.89 +        "published": new Date("2013-07-27T16:47:40.974Z"),
    1.90 +        "id": "bad-1"
    1.91 +      },
    1.92 +      {
    1.93 +        // This contact is bad because its "name" property is not an array
    1.94 +        // (upgrade 14 to 15)
    1.95 +        "properties": {
    1.96 +          "name": "name-bad-2",
    1.97 +          "email": [],
    1.98 +          "url": [{
    1.99 +            "type": ["source"],
   1.100 +            "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
   1.101 +          }],
   1.102 +          "category": ["gmail"],
   1.103 +          "adr": [],
   1.104 +          "tel": [{
   1.105 +            "type": ["mobile"],
   1.106 +            "value": "+7 123 456-78-90"
   1.107 +          }],
   1.108 +          "sex": "undefined",
   1.109 +          "genderIdentity": "undefined"
   1.110 +        },
   1.111 +        "search": {
   1.112 +          "givenName": [],
   1.113 +          "familyName": [],
   1.114 +          "email": [],
   1.115 +          "category": ["gmail"],
   1.116 +          "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
   1.117 +            "4567890","567890","67890","7890","890","90","0","81234567890"],
   1.118 +          "exactTel": ["+71234567890"],
   1.119 +          "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
   1.120 +        },
   1.121 +        "updated": new Date("2013-07-27T16:47:40.974Z"),
   1.122 +        "published": new Date("2013-07-27T16:47:40.974Z"),
   1.123 +        "id": "bad-2"
   1.124 +      },
   1.125 +      {
   1.126 +        // This contact is bad because its bday property is a String (upgrade 15
   1.127 +        // to 16), and its anniversary property is an empty string (upgrade 16
   1.128 +        // to 17)
   1.129 +        "properties": {
   1.130 +          "name": ["name-bad-3"],
   1.131 +          "email": [],
   1.132 +          "url": [{
   1.133 +            "type": ["source"],
   1.134 +            "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
   1.135 +          }],
   1.136 +          "category": ["gmail"],
   1.137 +          "adr": [],
   1.138 +          "tel": [{
   1.139 +            "type": ["mobile"],
   1.140 +            "value": "+7 123 456-78-90"
   1.141 +          }],
   1.142 +          "sex": "undefined",
   1.143 +          "genderIdentity": "undefined",
   1.144 +          "bday": "2013-07-27T16:47:40.974Z",
   1.145 +          "anniversary": ""
   1.146 +        },
   1.147 +        "search": {
   1.148 +          "givenName": [],
   1.149 +          "familyName": [],
   1.150 +          "email": [],
   1.151 +          "category": ["gmail"],
   1.152 +          "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
   1.153 +            "4567890","567890","67890","7890","890","90","0","81234567890"],
   1.154 +          "exactTel": ["+71234567890"],
   1.155 +          "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
   1.156 +        },
   1.157 +        "updated": new Date("2013-07-27T16:47:40.974Z"),
   1.158 +        "published": new Date("2013-07-27T16:47:40.974Z"),
   1.159 +        "id": "bad-3"
   1.160 +      },
   1.161 +      {
   1.162 +        // This contact is bad because its tel property has a tel.type null
   1.163 +        // value (upgrade 16 to 17), and email.type not array value (upgrade 14
   1.164 +        // to 15)
   1.165 +        "properties": {
   1.166 +          "name": ["name-bad-4"],
   1.167 +          "email": [{
   1.168 +            "value": "toto@toto.com",
   1.169 +            "type": "home"
   1.170 +          }],
   1.171 +          "url": [{
   1.172 +            "type": ["source"],
   1.173 +            "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
   1.174 +          }],
   1.175 +          "category": ["gmail"],
   1.176 +          "adr": [],
   1.177 +          "tel": [{
   1.178 +            "type": null,
   1.179 +            "value": "+7 123 456-78-90"
   1.180 +          }],
   1.181 +          "sex": "undefined",
   1.182 +          "genderIdentity": "undefined"
   1.183 +        },
   1.184 +        "search": {
   1.185 +          "givenName": [],
   1.186 +          "familyName": [],
   1.187 +          "email": [],
   1.188 +          "category": ["gmail"],
   1.189 +          "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
   1.190 +            "4567890","567890","67890","7890","890","90","0","81234567890"],
   1.191 +          "exactTel": ["+71234567890"],
   1.192 +          "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
   1.193 +        },
   1.194 +        "updated": new Date("2013-07-27T16:47:40.974Z"),
   1.195 +        "published": new Date("2013-07-27T16:47:40.974Z"),
   1.196 +        "id": "bad-4"
   1.197 +      }
   1.198 +    ],
   1.199 +    GOOD: [
   1.200 +      {
   1.201 +        "properties": {
   1.202 +          "name": ["name-good-1"],
   1.203 +          "email": [],
   1.204 +          "url": [{
   1.205 +            "type": ["source"],
   1.206 +            "value": "urn:service:gmail:uid:http://www.google.com/m8/feeds/contacts/XXX/base/4567894654"
   1.207 +          }],
   1.208 +          "category": ["gmail"],
   1.209 +          "adr": [],
   1.210 +          "tel": [{
   1.211 +            "type": ["mobile"],
   1.212 +            "value": "+7 123 456-78-90"
   1.213 +          }],
   1.214 +          "sex": "undefined",
   1.215 +          "genderIdentity": "undefined"
   1.216 +        },
   1.217 +        "search": {
   1.218 +          "givenName": [],
   1.219 +          "familyName": [],
   1.220 +          "email": [],
   1.221 +          "category": ["gmail"],
   1.222 +          "tel": ["+71234567890","71234567890","1234567890","234567890","34567890",
   1.223 +            "4567890","567890","67890","7890","890","90","0","81234567890"],
   1.224 +          "exactTel": ["+71234567890"],
   1.225 +          "parsedTel": ["+71234567890","1234567890","81234567890","34567890"]
   1.226 +        },
   1.227 +        "updated": new Date("2013-07-27T16:47:40.974Z"),
   1.228 +        "published": new Date("2013-07-27T16:47:40.974Z"),
   1.229 +        "id": "good-1"
   1.230 +      }
   1.231 +    ]
   1.232 +  }
   1.233 +};
   1.234 +
   1.235 +function DataManager(version) {
   1.236 +  if (!(version in DATA)) {
   1.237 +    throw new Error("Version " + version + " can't be found in our test datas.");
   1.238 +  }
   1.239 +
   1.240 +  this.version = version;
   1.241 +  this.data = DATA[version];
   1.242 +}
   1.243 +
   1.244 +DataManager.prototype = {
   1.245 +  open: function() {
   1.246 +    debug("opening for version " + this.version);
   1.247 +    var deferred = Promise.defer();
   1.248 +
   1.249 +    let req = indexedDB.open(DB_NAME, this.version);
   1.250 +    req.onupgradeneeded = function() {
   1.251 +      let db = req.result;
   1.252 +      let transaction = req.transaction;
   1.253 +      this.createSchema(db, transaction);
   1.254 +      this.addContacts(db, transaction);
   1.255 +    }.bind(this);
   1.256 +
   1.257 +    req.onsuccess = function() {
   1.258 +      debug("succeeded opening the db, let's close it now");
   1.259 +      req.result.close();
   1.260 +      deferred.resolve(this.contactsCount());
   1.261 +    }.bind(this);
   1.262 +
   1.263 +    req.onerror = function() {
   1.264 +      deferred.reject(this.error);
   1.265 +    };
   1.266 +
   1.267 +    return deferred.promise;
   1.268 +  },
   1.269 +
   1.270 +  createSchema: function(db, transaction) {
   1.271 +    debug("createSchema for version " + this.version);
   1.272 +    this.data.SCHEMA(db, transaction);
   1.273 +  },
   1.274 +
   1.275 +  addContacts: function(db, transaction) {
   1.276 +    debug("adding contacts for version " + this.version);
   1.277 +    var os = transaction.objectStore(STORE_NAME);
   1.278 +
   1.279 +    this.data.GOOD.forEach(function(contact) {
   1.280 +      os.put(contact);
   1.281 +    });
   1.282 +    this.data.BAD.forEach(function(contact) {
   1.283 +      os.put(contact);
   1.284 +    });
   1.285 +  },
   1.286 +
   1.287 +  contactsCount: function() {
   1.288 +    return this.data.BAD.length + this.data.GOOD.length;
   1.289 +  }
   1.290 +};
   1.291 +
   1.292 +DataManager.delete = function() {
   1.293 +  debug("Deleting the database");
   1.294 +  var deferred = Promise.defer();
   1.295 +
   1.296 +  /* forcibly close the db before deleting it */
   1.297 +  ContactService._db.close();
   1.298 +
   1.299 +  var req = indexedDB.deleteDatabase(DB_NAME);
   1.300 +  req.onsuccess = function() {
   1.301 +    debug("Successfully deleted!");
   1.302 +    deferred.resolve();
   1.303 +  };
   1.304 +
   1.305 +  req.onerror = function() {
   1.306 +    debug("Not deleted, error is " + this.error.name);
   1.307 +    deferred.reject(this.error);
   1.308 +  };
   1.309 +
   1.310 +  req.onblocked = function() {
   1.311 +    debug("Waiting for the current users");
   1.312 +  };
   1.313 +
   1.314 +  return deferred.promise;
   1.315 +};
   1.316 +
   1.317 +addMessageListener("createDB", function(version) {
   1.318 +  // Promises help handling gracefully exceptions
   1.319 +  Promise.resolve().then(function() {
   1.320 +    return new DataManager(version);
   1.321 +  }).then(function(manager) {
   1.322 +    return manager.open();
   1.323 +  }).then(function onSuccess(count) {
   1.324 +    sendAsyncMessage("createDB.success", count);
   1.325 +  }, function onError(err) {
   1.326 +    sendAsyncMessage("createDB.error", "Failed to create the DB: " +
   1.327 +      "(" + err.name + ") " + err.message);
   1.328 +  });
   1.329 +});
   1.330 +
   1.331 +addMessageListener("deleteDB", function() {
   1.332 +  Promise.resolve().then(
   1.333 +    DataManager.delete
   1.334 +  ).then(function onSuccess() {
   1.335 +    sendAsyncMessage("deleteDB.success");
   1.336 +  }, function onError(err) {
   1.337 +    sendAsyncMessage("deleteDB.error", "Failed to delete the DB:" + err.name);
   1.338 +  });
   1.339 +});

mercurial