1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/contacts/tests/shared.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,504 @@ 1.4 +"use strict"; 1.5 + 1.6 +// Fix the environment to run Contacts tests 1.7 +if (SpecialPowers.isMainProcess()) { 1.8 + SpecialPowers.Cu.import("resource://gre/modules/ContactService.jsm"); 1.9 + SpecialPowers.Cu.import("resource://gre/modules/PermissionPromptHelper.jsm"); 1.10 +} 1.11 + 1.12 +SpecialPowers.addPermission("contacts-write", true, document); 1.13 +SpecialPowers.addPermission("contacts-read", true, document); 1.14 +SpecialPowers.addPermission("contacts-create", true, document); 1.15 + 1.16 +// Some helpful global vars 1.17 +var isAndroid = (navigator.userAgent.indexOf("Android") !== -1); 1.18 + 1.19 +var defaultOptions = { 1.20 + sortBy: "givenName", 1.21 +}; 1.22 + 1.23 +var mozContacts = navigator.mozContacts; 1.24 + 1.25 +// To test sorting 1.26 +var c1 = { 1.27 + name: ["a a"], 1.28 + familyName: ["a"], 1.29 + givenName: ["a"], 1.30 +}; 1.31 + 1.32 +var c2 = { 1.33 + name: ["b b"], 1.34 + familyName: ["b"], 1.35 + givenName: ["b"], 1.36 +}; 1.37 + 1.38 +var c3 = { 1.39 + name: ["c c", "a a", "b b"], 1.40 + familyName: ["c","a","b"], 1.41 + givenName: ["c","a","b"], 1.42 +}; 1.43 + 1.44 +var c4 = { 1.45 + name: ["c c", "a a", "c c"], 1.46 + familyName: ["c","a","c"], 1.47 + givenName: ["c","a","c"], 1.48 +}; 1.49 + 1.50 +var c5 = { 1.51 + familyName: [], 1.52 + givenName: [], 1.53 +}; 1.54 + 1.55 +var c6 = { 1.56 + name: ["e"], 1.57 + familyName: ["e","e","e"], 1.58 + givenName: ["e","e","e"], 1.59 +}; 1.60 + 1.61 +var c7 = { 1.62 + name: ["e"], 1.63 + familyName: ["e","e","e"], 1.64 + givenName: ["e","e","e"], 1.65 +}; 1.66 + 1.67 +var c8 = { 1.68 + name: ["e"], 1.69 + familyName: ["e","e","e"], 1.70 + givenName: ["e","e","e"], 1.71 +}; 1.72 + 1.73 +var adr1 = { 1.74 + type: ["work"], 1.75 + streetAddress: "street 1", 1.76 + locality: "locality 1", 1.77 + region: "region 1", 1.78 + postalCode: "postal code 1", 1.79 + countryName: "country 1" 1.80 +}; 1.81 + 1.82 +var adr2 = { 1.83 + type: ["home, fax"], 1.84 + streetAddress: "street2", 1.85 + locality: "locality2", 1.86 + region: "region2", 1.87 + postalCode: "postal code2", 1.88 + countryName: "country2" 1.89 +}; 1.90 + 1.91 +var properties1 = { 1.92 + // please keep capital letters at the start of these names 1.93 + name: ["Test1 TestFamilyName", "Test2 Wagner"], 1.94 + familyName: ["TestFamilyName","Wagner"], 1.95 + givenName: ["Test1","Test2"], 1.96 + phoneticFamilyName: ["TestphoneticFamilyName1","TestphoneticFamilyName2"], 1.97 + phoneticGivenName: ["TestphoneticGivenName1","TestphoneticGivenName2"], 1.98 + nickname: ["nicktest"], 1.99 + tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+55 (31) 9876-3456"}, {type: ["home"], value: "+49 451 491934"}], 1.100 + adr: [adr1], 1.101 + email: [{type: ["work"], value: "x@y.com"}], 1.102 +}; 1.103 + 1.104 +var properties2 = { 1.105 + name: ["dummyHonorificPrefix dummyGivenName dummyFamilyName dummyHonorificSuffix", "dummyHonorificPrefix2"], 1.106 + familyName: ["dummyFamilyName"], 1.107 + givenName: ["dummyGivenName"], 1.108 + phoneticFamilyName: ["dummyphoneticFamilyName"], 1.109 + phoneticGivenName: ["dummyphoneticGivenName"], 1.110 + honorificPrefix: ["dummyHonorificPrefix","dummyHonorificPrefix2"], 1.111 + honorificSuffix: ["dummyHonorificSuffix"], 1.112 + additionalName: ["dummyadditionalName"], 1.113 + nickname: ["dummyNickname"], 1.114 + tel: [{type: ["test"], value: "7932012345", carrier: "myCarrier", pref: 1},{type: ["home", "custom"], value: "7932012346", pref: 0}], 1.115 + email: [{type: ["test"], value: "a@b.c"}, {value: "b@c.d", pref: 1}], 1.116 + adr: [adr1, adr2], 1.117 + impp: [{type: ["aim"], value:"im1", pref: 1}, {value: "im2"}], 1.118 + org: ["org1", "org2"], 1.119 + jobTitle: ["boss", "superboss"], 1.120 + note: ["test note"], 1.121 + category: ["cat1", "cat2"], 1.122 + url: [{type: ["work", "work2"], value: "www.1.com", pref: 1}, {value:"www2.com"}], 1.123 + bday: new Date("1980, 12, 01"), 1.124 + anniversary: new Date("2000, 12, 01"), 1.125 + sex: "male", 1.126 + genderIdentity: "test", 1.127 + key: ["ERPJ394GJJWEVJ0349GJ09W3H4FG0WFW80VHW3408GH30WGH348G3H"] 1.128 +}; 1.129 + 1.130 +// To test sorting(CJK) 1.131 +var c9 = { 1.132 + phoneticFamilyName: ["a"], 1.133 + phoneticGivenName: ["a"], 1.134 +}; 1.135 + 1.136 +var c10 = { 1.137 + phoneticFamilyName: ["b"], 1.138 + phoneticGivenName: ["b"], 1.139 +}; 1.140 + 1.141 +var c11 = { 1.142 + phoneticFamilyName: ["c","a","b"], 1.143 + phoneticGivenName: ["c","a","b"], 1.144 +}; 1.145 + 1.146 +var c12 = { 1.147 + phoneticFamilyName: ["c","a","c"], 1.148 + phoneticGivenName: ["c","a","c"], 1.149 +}; 1.150 + 1.151 +var c13 = { 1.152 + phoneticFamilyName: [], 1.153 + phoneticGivenName: [], 1.154 +}; 1.155 + 1.156 +var c14 = { 1.157 + phoneticFamilyName: ["e","e","e"], 1.158 + phoneticGivenName: ["e","e","e"], 1.159 +}; 1.160 + 1.161 +var c15 = { 1.162 + phoneticFamilyName: ["e","e","e"], 1.163 + phoneticGivenName: ["e","e","e"], 1.164 +}; 1.165 + 1.166 +var c16 = { 1.167 + phoneticFamilyName: ["e","e","e"], 1.168 + phoneticGivenName: ["e","e","e"], 1.169 +}; 1.170 + 1.171 +var properties3 = { 1.172 + // please keep capital letters at the start of these names 1.173 + name: ["Taro Yamada", "Ichiro Suzuki"], 1.174 + familyName: ["Yamada","Suzuki"], 1.175 + givenName: ["Taro","Ichiro"], 1.176 + phoneticFamilyName: ["TestPhoneticFamilyYamada","TestPhoneticFamilySuzuki"], 1.177 + phoneticGivenName: ["TestPhoneticGivenTaro","TestPhoneticGivenIchiro"], 1.178 + nickname: ["phoneticNicktest"], 1.179 + tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+55 (31) 9876-3456"}, {type: ["home"], value: "+49 451 491934"}], 1.180 + adr: [adr1], 1.181 + email: [{type: ["work"], value: "x@y.com"}], 1.182 +}; 1.183 + 1.184 +var properties4 = { 1.185 + name: ["dummyHonorificPrefix dummyTaro dummyYamada dummyHonorificSuffix", "dummyHonorificPrefix2"], 1.186 + familyName: ["dummyYamada"], 1.187 + givenName: ["dummyTaro"], 1.188 + phoneticFamilyName: ["dummyTestPhoneticFamilyYamada"], 1.189 + phoneticGivenName: ["dummyTestPhoneticGivenTaro"], 1.190 + honorificPrefix: ["dummyPhoneticHonorificPrefix","dummyPhoneticHonorificPrefix2"], 1.191 + honorificSuffix: ["dummyPhoneticHonorificSuffix"], 1.192 + additionalName: ["dummyPhoneticAdditionalName"], 1.193 + nickname: ["dummyPhoneticNickname"], 1.194 + tel: [{type: ["test"], value: "7932012345", carrier: "myCarrier", pref: 1},{type: ["home", "custom"], value: "7932012346", pref: 0}], 1.195 + email: [{type: ["test"], value: "a@b.c"}, {value: "b@c.d", pref: 1}], 1.196 + adr: [adr1, adr2], 1.197 + impp: [{type: ["aim"], value:"im1", pref: 1}, {value: "im2"}], 1.198 + org: ["org1", "org2"], 1.199 + jobTitle: ["boss", "superboss"], 1.200 + note: ["test note"], 1.201 + category: ["cat1", "cat2"], 1.202 + url: [{type: ["work", "work2"], value: "www.1.com", pref: 1}, {value:"www2.com"}], 1.203 + bday: new Date("1980, 12, 01"), 1.204 + anniversary: new Date("2000, 12, 01"), 1.205 + sex: "male", 1.206 + genderIdentity: "test", 1.207 + key: ["ERPJ394GJJWEVJ0349GJ09W3H4FG0WFW80VHW3408GH30WGH348G3H"] 1.208 +}; 1.209 + 1.210 +var sample_id1; 1.211 +var sample_id2; 1.212 + 1.213 +var createResult1; 1.214 +var createResult2; 1.215 + 1.216 +var findResult1; 1.217 +var findResult2; 1.218 + 1.219 +// DOMRequest helper functions 1.220 +function onUnwantedSuccess() { 1.221 + ok(false, "onUnwantedSuccess: shouldn't get here"); 1.222 +} 1.223 + 1.224 +function onFailure() { 1.225 + ok(false, "in on Failure!"); 1.226 + next(); 1.227 +} 1.228 + 1.229 +// Validation helper functions 1.230 +function checkStr(str1, str2, msg) { 1.231 + if (str1 ^ str2) { 1.232 + ok(false, "Expected both strings to be either present or absent"); 1.233 + return; 1.234 + } 1.235 + if (!str1 || str1 == "null") { 1.236 + str1 = null; 1.237 + } 1.238 + if (!str2 || str2 == "null") { 1.239 + str2 = null; 1.240 + } 1.241 + is(str1, str2, msg); 1.242 +} 1.243 + 1.244 +function checkStrArray(str1, str2, msg) { 1.245 + function normalize_falsy(v) { 1.246 + if (!v || v == "null" || v == "undefined") { 1.247 + return ""; 1.248 + } 1.249 + return v; 1.250 + } 1.251 + function optArray(val) { 1.252 + return Array.isArray(val) ? val : [val]; 1.253 + } 1.254 + str1 = optArray(str1).map(normalize_falsy).filter(v => v != ""); 1.255 + str2 = optArray(str2).map(normalize_falsy).filter(v => v != ""); 1.256 + ise(JSON.stringify(str1), JSON.stringify(str2), msg); 1.257 +} 1.258 + 1.259 +function checkPref(pref1, pref2) { 1.260 + // If on Android treat one preference as 0 and the other as undefined as matching 1.261 + if (isAndroid) { 1.262 + if ((!pref1 && pref2 == undefined) || (pref1 == undefined && !pref2)) { 1.263 + pref1 = false; 1.264 + pref2 = false; 1.265 + } 1.266 + } 1.267 + ise(!!pref1, !!pref2, "Same pref"); 1.268 +} 1.269 + 1.270 +function checkAddress(adr1, adr2) { 1.271 + if (adr1 ^ adr2) { 1.272 + ok(false, "Expected both adrs to be either present or absent"); 1.273 + return; 1.274 + } 1.275 + checkStrArray(adr1.type, adr2.type, "Same type"); 1.276 + checkStr(adr1.streetAddress, adr2.streetAddress, "Same streetAddress"); 1.277 + checkStr(adr1.locality, adr2.locality, "Same locality"); 1.278 + checkStr(adr1.region, adr2.region, "Same region"); 1.279 + checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode"); 1.280 + checkStr(adr1.countryName, adr2.countryName, "Same countryName"); 1.281 + checkPref(adr1.pref, adr2.pref); 1.282 +} 1.283 + 1.284 +function checkField(field1, field2) { 1.285 + if (field1 ^ field2) { 1.286 + ok(false, "Expected both fields to be either present or absent"); 1.287 + return; 1.288 + } 1.289 + checkStrArray(field1.type, field2.type, "Same type"); 1.290 + checkStr(field1.value, field2.value, "Same value"); 1.291 + checkPref(field1.pref, field2.pref); 1.292 +} 1.293 + 1.294 +function checkTel(tel1, tel2) { 1.295 + if (tel1 ^ tel2) { 1.296 + ok(false, "Expected both tels to be either present or absent"); 1.297 + return; 1.298 + } 1.299 + checkField(tel1, tel2); 1.300 + checkStr(tel1.carrier, tel2.carrier, "Same carrier"); 1.301 +} 1.302 + 1.303 +function checkCategory(category1, category2) { 1.304 + // Android adds contacts to the a default category. This should be removed from the 1.305 + // results before comparing them 1.306 + if (isAndroid) { 1.307 + category1 = removeAndroidDefaultCategory(category1); 1.308 + category2 = removeAndroidDefaultCategory(category2); 1.309 + } 1.310 + checkStrArray(category1, category2, "Same Category") 1.311 +} 1.312 + 1.313 +function removeAndroidDefaultCategory(category) { 1.314 + if (!category) { 1.315 + return category; 1.316 + } 1.317 + 1.318 + var result = []; 1.319 + 1.320 + for (var i of category) { 1.321 + // Some devices may return the full group name (prefixed with "System Group: ") 1.322 + if (i != "My Contacts" && i != "System Group: My Contacts") { 1.323 + result.push(i); 1.324 + } 1.325 + } 1.326 + 1.327 + return result; 1.328 +} 1.329 + 1.330 +function checkArrayField(array1, array2, func, msg) { 1.331 + if (!!array1 ^ !!array2) { 1.332 + ok(false, "Expected both arrays to be either present or absent: " + JSON.stringify(array1) + " vs. " + JSON.stringify(array2) + ". (" + msg + ")"); 1.333 + return; 1.334 + } 1.335 + if (!array1 && !array2) { 1.336 + ok(true, msg); 1.337 + return; 1.338 + } 1.339 + ise(array1.length, array2.length, "Same length"); 1.340 + for (var i = 0; i < array1.length; ++i) { 1.341 + func(array1[i], array2[i], msg); 1.342 + } 1.343 +} 1.344 + 1.345 +function checkContacts(contact1, contact2) { 1.346 + if (!!contact1 ^ !!contact2) { 1.347 + ok(false, "Expected both contacts to be either present or absent"); 1.348 + return; 1.349 + } 1.350 + checkStrArray(contact1.name, contact2.name, "Same name"); 1.351 + checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix"); 1.352 + checkStrArray(contact1.givenName, contact2.givenName, "Same givenName"); 1.353 + checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName"); 1.354 + checkStrArray(contact1.familyName, contact2.familyName, "Same familyName"); 1.355 + checkStrArray(contact1.phoneticFamilyName, contact2.phoneticFamilyName, "Same phoneticFamilyName"); 1.356 + checkStrArray(contact1.phoneticGivenName, contact2.phoneticGivenName, "Same phoneticGivenName"); 1.357 + checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix"); 1.358 + checkStrArray(contact1.nickname, contact2.nickname, "Same nickname"); 1.359 + checkCategory(contact1.category, contact2.category); 1.360 + checkStrArray(contact1.org, contact2.org, "Same org"); 1.361 + checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle"); 1.362 + is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday"); 1.363 + checkStrArray(contact1.note, contact2.note, "Same note"); 1.364 + is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary"); 1.365 + checkStr(contact1.sex, contact2.sex, "Same sex"); 1.366 + checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity"); 1.367 + checkStrArray(contact1.key, contact2.key, "Same key"); 1.368 + 1.369 + checkArrayField(contact1.adr, contact2.adr, checkAddress, "Same adr"); 1.370 + checkArrayField(contact1.tel, contact2.tel, checkTel, "Same tel"); 1.371 + checkArrayField(contact1.email, contact2.email, checkField, "Same email"); 1.372 + checkArrayField(contact1.url, contact2.url, checkField, "Same url"); 1.373 + checkArrayField(contact1.impp, contact2.impp, checkField, "Same impp"); 1.374 +} 1.375 + 1.376 +function addContacts() { 1.377 + ok(true, "Adding 40 contacts"); 1.378 + let req; 1.379 + for (let i = 0; i < 39; ++i) { 1.380 + properties1.familyName[0] = "Testname" + (i < 10 ? "0" + i : i); 1.381 + properties1.name = [properties1.givenName[0] + " " + properties1.familyName[0]]; 1.382 + createResult1 = new mozContact(properties1); 1.383 + req = mozContacts.save(createResult1); 1.384 + req.onsuccess = function() { 1.385 + ok(createResult1.id, "The contact now has an ID."); 1.386 + }; 1.387 + req.onerror = onFailure; 1.388 + }; 1.389 + properties1.familyName[0] = "Testname39"; 1.390 + properties1.name = [properties1.givenName[0] + " Testname39"]; 1.391 + createResult1 = new mozContact(properties1); 1.392 + req = mozContacts.save(createResult1); 1.393 + req.onsuccess = function() { 1.394 + ok(createResult1.id, "The contact now has an ID."); 1.395 + checkStrArray(createResult1.name, properties1.name, "Same Name"); 1.396 + next(); 1.397 + }; 1.398 + req.onerror = onFailure; 1.399 +} 1.400 + 1.401 +function getOne(msg) { 1.402 + return function() { 1.403 + ok(true, msg || "Retrieving one contact with getAll"); 1.404 + let req = mozContacts.getAll({}); 1.405 + 1.406 + let count = 0; 1.407 + req.onsuccess = function(event) { 1.408 + ok(true, "on success"); 1.409 + if (req.result) { 1.410 + ok(true, "result is valid"); 1.411 + count++; 1.412 + req.continue(); 1.413 + } else { 1.414 + is(count, 1, "last contact - only one contact returned"); 1.415 + next(); 1.416 + } 1.417 + }; 1.418 + req.onerror = onFailure; 1.419 + }; 1.420 +} 1.421 + 1.422 +function getAll(msg) { 1.423 + return function() { 1.424 + ok(true, msg || "Retrieving 40 contacts with getAll"); 1.425 + let req = mozContacts.getAll({ 1.426 + sortBy: "familyName", 1.427 + sortOrder: "ascending" 1.428 + }); 1.429 + let count = 0; 1.430 + let result; 1.431 + let props; 1.432 + req.onsuccess = function(event) { 1.433 + if (req.result) { 1.434 + ok(true, "result is valid"); 1.435 + result = req.result; 1.436 + properties1.familyName[0] = "Testname" + (count < 10 ? "0" + count : count); 1.437 + is(result.familyName[0], properties1.familyName[0], "Same familyName"); 1.438 + count++; 1.439 + req.continue(); 1.440 + } else { 1.441 + is(count, 40, "last contact - 40 contacts returned"); 1.442 + next(); 1.443 + } 1.444 + }; 1.445 + req.onerror = onFailure; 1.446 + }; 1.447 +} 1.448 + 1.449 +function clearTemps() { 1.450 + sample_id1 = null; 1.451 + sample_id2 = null; 1.452 + createResult1 = null; 1.453 + createResult2 = null; 1.454 + findResult1 = null; 1.455 + findResult2 = null; 1.456 +} 1.457 + 1.458 +function clearDatabase() { 1.459 + ok(true, "Deleting database"); 1.460 + let req = mozContacts.clear() 1.461 + req.onsuccess = function () { 1.462 + ok(true, "Deleted the database"); 1.463 + next(); 1.464 + } 1.465 + req.onerror = onFailure; 1.466 +} 1.467 + 1.468 +function checkCount(count, msg, then) { 1.469 + var request = mozContacts.getCount(); 1.470 + request.onsuccess = function(e) { 1.471 + is(e.target.result, count, msg); 1.472 + then(); 1.473 + }; 1.474 + request.onerror = onFailure; 1.475 +} 1.476 + 1.477 +// Helper functions to run tests 1.478 +var index = 0; 1.479 + 1.480 +function next() { 1.481 + info("Step " + index); 1.482 + if (index >= steps.length) { 1.483 + ok(false, "Shouldn't get here!"); 1.484 + return; 1.485 + } 1.486 + try { 1.487 + var i = index++; 1.488 + steps[i](); 1.489 + } catch(ex) { 1.490 + ok(false, "Caught exception", ex); 1.491 + } 1.492 +} 1.493 + 1.494 +SimpleTest.waitForExplicitFinish(); 1.495 + 1.496 +function start_tests() { 1.497 + // Skip tests on Android < 4.0 due to test failures on tbpl (see bugs 897924 & 888891) 1.498 + let androidVersion = SpecialPowers.Cc['@mozilla.org/system-info;1'] 1.499 + .getService(SpecialPowers.Ci.nsIPropertyBag2) 1.500 + .getProperty('version'); 1.501 + if (!isAndroid || androidVersion >= 14) { 1.502 + next(); 1.503 + } else { 1.504 + ok(true, "Skip tests on Android < 4.0 (bugs 897924 & 888891"); 1.505 + SimpleTest.finish(); 1.506 + } 1.507 +}