Repositorio del curso CCOM4030 el semestre B91 del proyecto kilometro0

tests.js 47KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. /* jshint jasmine: true */
  22. /* global WinJS */
  23. exports.defineAutoTests = function() {
  24. var isWindowsPhone8 = cordova.platformId == 'windowsphone';
  25. var isWindows = (cordova.platformId === "windows") || (cordova.platformId === "windows8");
  26. var isWindowsPhone81 = isWindows && WinJS.Utilities.isPhone;
  27. // Error callback spies should not be called
  28. var errorCallbacks = {};
  29. errorCallbacks[ContactError.UNKNOWN_ERROR] = jasmine.createSpy('unknownErrorCallback');
  30. errorCallbacks[ContactError.INVALID_ARGUMENT_ERROR] = jasmine.createSpy('invalidArgumentErrorCallback');
  31. errorCallbacks[ContactError.TIMEOUT_ERROR] = jasmine.createSpy('timeoutErrorCallback');
  32. errorCallbacks[ContactError.PENDING_OPERATION_ERROR] = jasmine.createSpy('pendingOperationErrorCallback');
  33. errorCallbacks[ContactError.IO_ERROR] = jasmine.createSpy('ioErrorCallback');
  34. errorCallbacks[ContactError.NOT_SUPPORTED_ERROR] = jasmine.createSpy('notSupportedErrorCallback');
  35. errorCallbacks[ContactError.OPERATION_CANCELLED_ERROR] = jasmine.createSpy('operationCancelledErrorCallback');
  36. errorCallbacks[ContactError.PERMISSION_DENIED_ERROR] = jasmine.createSpy('permissionDeniedErrorCallback');
  37. var isIOSPermissionBlocked = false;
  38. var fail = function(done) {
  39. expect(true).toBe(false);
  40. done();
  41. };
  42. var MEDIUM_TIMEOUT = 30000;
  43. var HIGH_TIMEOUT = 120000;
  44. var removeContact = function(done, contactObj) {
  45. if (!contactObj) {
  46. done();
  47. return;
  48. }
  49. contactObj.remove(function() {
  50. done();
  51. }, function(contactError) {
  52. if (contactError) {
  53. if (errorCallbacks[contactError.code]) {
  54. errorCallbacks[contactError.code]();
  55. } else {
  56. fail(done);
  57. }
  58. }
  59. for (var error in errorCallbacks) {
  60. expect(errorCallbacks[error]).not.toHaveBeenCalled();
  61. }
  62. done();
  63. });
  64. };
  65. function removeContactsByFields(fields, filter, done) {
  66. var obj = new ContactFindOptions();
  67. obj.filter = filter;
  68. obj.multiple = true;
  69. navigator.contacts.find(fields, function(contacts) {
  70. var removes = [];
  71. contacts.forEach(function(contact) {
  72. removes.push(contact);
  73. });
  74. if (removes.length === 0) {
  75. done();
  76. return;
  77. }
  78. var nextToRemove;
  79. if (removes.length > 0) {
  80. nextToRemove = removes.shift();
  81. }
  82. function removeNext(item) {
  83. if (typeof item === 'undefined') {
  84. done();
  85. return;
  86. }
  87. if (removes.length > 0) {
  88. nextToRemove = removes.shift();
  89. } else {
  90. nextToRemove = undefined;
  91. }
  92. item.remove(function removeSucceeded() {
  93. removeNext(nextToRemove);
  94. }, function removeFailed() {
  95. removeNext(nextToRemove);
  96. });
  97. }
  98. removeNext(nextToRemove);
  99. }, done, obj);
  100. }
  101. describe("Contacts (navigator.contacts)", function() {
  102. this.contactObj = null;
  103. it("contacts.spec.1 should exist", function() {
  104. expect(navigator.contacts).toBeDefined();
  105. });
  106. it("contacts.spec.2 should contain a find function", function() {
  107. expect(navigator.contacts.find).toBeDefined();
  108. expect(typeof navigator.contacts.find).toBe('function');
  109. });
  110. describe("find method", function() {
  111. it("contacts.spec.3 success callback should be called with an array", function(done) {
  112. // Find method is not supported on Windows platform
  113. if (isWindows && !isWindowsPhone81) {
  114. pending();
  115. return;
  116. }
  117. var win = function(result) {
  118. expect(result).toBeDefined();
  119. expect(result instanceof Array).toBe(true);
  120. done();
  121. },
  122. obj = new ContactFindOptions();
  123. obj.filter = "";
  124. obj.multiple = true;
  125. function failed(err) {
  126. if (err.code == ContactError.PERMISSION_DENIED_ERROR) {
  127. isIOSPermissionBlocked = true;
  128. done();
  129. }
  130. }
  131. navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, failed, obj);
  132. }, HIGH_TIMEOUT); // give permission buster or a user a chance to accept the permission alert
  133. it("contacts.spec.4 success callback should be called with an array, even if partial ContactFindOptions specified", function(done) {
  134. // Find method is not supported on Windows platform
  135. if ((isWindows && !isWindowsPhone81) || isIOSPermissionBlocked) {
  136. pending();
  137. return;
  138. }
  139. var win = function(result) {
  140. expect(result).toBeDefined();
  141. expect(result instanceof Array).toBe(true);
  142. done();
  143. };
  144. navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, fail.bind(null, done), {
  145. multiple: true
  146. });
  147. });
  148. it("contacts.spec.5 should throw an exception if success callback is empty", function() {
  149. var obj = new ContactFindOptions();
  150. obj.filter = "";
  151. obj.multiple = true;
  152. expect(function() {
  153. navigator.contacts.find(["displayName", "name", "emails", "phoneNumbers"], null, function (err) {
  154. expect(err).toBeUndefined();
  155. }, obj);
  156. }).toThrow();
  157. });
  158. it("contacts.spec.6 error callback should be called when no fields are specified", function(done) {
  159. var win = fail,
  160. // we don't want this to be called
  161. error = function(result) {
  162. expect(result).toBeDefined();
  163. expect(result.code).toBe(ContactError.INVALID_ARGUMENT_ERROR);
  164. done();
  165. },
  166. obj = new ContactFindOptions();
  167. obj.filter = "";
  168. obj.multiple = true;
  169. navigator.contacts.find([], win, error, obj);
  170. });
  171. describe("with newly-created contact", function() {
  172. afterEach(function (done) {
  173. removeContact(done, this.contactObj);
  174. });
  175. it("contacts.spec.7 should be able to find a contact by name", function(done) {
  176. // Find method is not supported on Windows Store apps.
  177. // also this test will be skipped for Windows Phone 8.1 because function "save" not supported on WP8.1
  178. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  179. pending();
  180. }
  181. var specContext = this;
  182. specContext.contactObj = new Contact();
  183. specContext.contactObj.name = new ContactName();
  184. specContext.contactObj.name.familyName = "Delete";
  185. var foundName = function(result) {
  186. var bFound = false;
  187. try {
  188. for (var i = 0; i < result.length; i++) {
  189. if (result[i].name.familyName == "Delete") {
  190. bFound = true;
  191. break;
  192. }
  193. }
  194. } catch (e) {
  195. return false;
  196. }
  197. return bFound;
  198. };
  199. var test = function(savedContact) {
  200. // update so contact will get removed
  201. specContext.contactObj = savedContact;
  202. // ----
  203. // Find asserts
  204. // ---
  205. var findWin = function(object) {
  206. expect(object instanceof Array).toBe(true);
  207. expect(object.length >= 1).toBe(true);
  208. expect(foundName(object)).toBe(true);
  209. done();
  210. },
  211. findFail = fail,
  212. obj = new ContactFindOptions();
  213. obj.filter = "Delete";
  214. obj.multiple = true;
  215. navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail.bind(null, done), obj);
  216. };
  217. specContext.contactObj.save(test, fail.bind(null, done));
  218. });
  219. it("contacts.spec.7.1 should contain displayName if specified in desiredFields", function(done) {
  220. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  221. pending();
  222. }
  223. var testDisplayName = "testContact";
  224. var specContext = this;
  225. specContext.contactObj = new Contact();
  226. specContext.contactObj.displayName = testDisplayName;
  227. var win = function(contactResult) {
  228. expect(contactResult.length > 0).toBe(true);
  229. var namesDisplayed = contactResult.every(function(contact, index) {
  230. return contact.displayName !== null;
  231. });
  232. expect(namesDisplayed).toBe(true);
  233. done();
  234. };
  235. var onSuccessSave = function(savedContact) {
  236. specContext.contactObj = savedContact;
  237. var options = new ContactFindOptions();
  238. options.filter = testDisplayName;
  239. options.multiple = true;
  240. options.desiredFields = [navigator.contacts.fieldType.displayName];
  241. navigator.contacts.find(["displayName", "nickname"], win, fail.bind(null, done), options);
  242. };
  243. specContext.contactObj.save(onSuccessSave, fail.bind(null, done));
  244. });
  245. it("contacts.spec.7.2 should find contact despite id isn't string ", function(done) {
  246. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  247. pending();
  248. }
  249. var testDisplayName = "testContact";
  250. var specContext = this;
  251. specContext.contactObj = new Contact();
  252. specContext.contactObj.displayName = testDisplayName;
  253. var win = function(contactResult) {
  254. expect(contactResult.length > 0).toBe(true);
  255. done();
  256. };
  257. var onSuccessSave = function(savedContact) {
  258. specContext.contactObj = savedContact;
  259. var options = new ContactFindOptions();
  260. options.filter = savedContact.id;
  261. options.multiple = true;
  262. navigator.contacts.find(["id"], win, fail.bind(null, done), options);
  263. };
  264. specContext.contactObj.save(onSuccessSave, fail.bind(null, done));
  265. });
  266. it("contacts.spec.7.3 should contain custom label in type", function(done) {
  267. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  268. pending();
  269. }
  270. var testDisplayName = "testContact";
  271. var customLabel = "myType";
  272. var testContactDetail = new ContactField(customLabel, "a", true);
  273. var contactFields = ["phoneNumbers", "emails", "urls", "ims"];
  274. var specContext = this;
  275. specContext.contactObj = new Contact();
  276. specContext.contactObj.nickname = testDisplayName;
  277. specContext.contactObj.displayName = testDisplayName;
  278. contactFields.forEach(function(contactField) {
  279. specContext.contactObj[contactField] = [];
  280. specContext.contactObj[contactField][0] = testContactDetail;
  281. });
  282. specContext.contactObj.addresses = [];
  283. specContext.contactObj.addresses[0] = new ContactAddress(true, customLabel, "a", "b", "c", "d", "e", "f");
  284. var checkTypes = function(contact) {
  285. var allFieldsWithCustomLabel = contactFields.concat(["addresses"]);
  286. return allFieldsWithCustomLabel.every(function(contactField) {
  287. return contact[contactField] && contact[contactField][0].type === customLabel;
  288. });
  289. };
  290. var win = function(contactResult) {
  291. expect(contactResult.length > 0).toBe(true);
  292. var typesCustomized = contactResult.every(function(contact) {
  293. return checkTypes(contact);
  294. });
  295. expect(typesCustomized).toBe(true);
  296. done();
  297. };
  298. var onSuccessSave = function(savedContact) {
  299. expect(checkTypes(savedContact)).toBe(true);
  300. specContext.contactObj = savedContact;
  301. var options = new ContactFindOptions();
  302. options.filter = testDisplayName;
  303. options.multiple = true;
  304. navigator.contacts.find(["displayName", "nickname"], win, fail.bind(null, done), options);
  305. };
  306. specContext.contactObj.save(onSuccessSave, fail.bind(null, done));
  307. });
  308. it('spec 7.4 contact detail type should equal default label', function(done) {
  309. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  310. pending();
  311. }
  312. var specContext = this;
  313. specContext.contactObj = navigator.contacts.create({
  314. "displayName": "test name",
  315. "ims": [{
  316. "type": "SKYPE",
  317. "value": "000"
  318. }]
  319. });
  320. specContext.contactObj.save(onSuccessSave, fail.bind(null, done));
  321. function onSuccessSave(savedContact) {
  322. specContext.contactObj = savedContact;
  323. var imsType = savedContact.ims[0].type;
  324. var expectedType = (cordova.platformId == 'android') ? "Skype" : "skype";
  325. expect(imsType).toBe(expectedType);
  326. done();
  327. }
  328. });
  329. });
  330. });
  331. describe('create method', function() {
  332. it("contacts.spec.8 should exist", function() {
  333. expect(navigator.contacts.create).toBeDefined();
  334. expect(typeof navigator.contacts.create).toBe('function');
  335. });
  336. it("contacts.spec.9 should return a Contact object", function() {
  337. var bDay = new Date(1976, 7, 4);
  338. var obj = navigator.contacts.create({
  339. "displayName": "test name",
  340. "gender": "male",
  341. "note": "my note",
  342. "name": {
  343. "formatted": "Mr. Test Name"
  344. },
  345. "emails": [{
  346. "value": "here@there.com"
  347. }, {
  348. "value": "there@here.com"
  349. }],
  350. "birthday": bDay
  351. });
  352. expect(obj).toBeDefined();
  353. expect(obj.displayName).toBe('test name');
  354. expect(obj.note).toBe('my note');
  355. expect(obj.name.formatted).toBe('Mr. Test Name');
  356. expect(obj.emails.length).toBe(2);
  357. expect(obj.emails[0].value).toBe('here@there.com');
  358. expect(obj.emails[1].value).toBe('there@here.com');
  359. expect(obj.nickname).toBe(null);
  360. expect(obj.birthday).toBe(bDay);
  361. });
  362. });
  363. describe("Contact object", function() {
  364. it("contacts.spec.10 should be able to create instance", function() {
  365. var contact = new Contact("a", "b", new ContactName("a", "b", "c", "d", "e", "f"), "c", [], [], [], [], [], "f", "i", [], [], []);
  366. expect(contact).toBeDefined();
  367. expect(contact.id).toBe("a");
  368. expect(contact.displayName).toBe("b");
  369. expect(contact.name.formatted).toBe("a");
  370. expect(contact.nickname).toBe("c");
  371. expect(contact.phoneNumbers).toBeDefined();
  372. expect(contact.emails).toBeDefined();
  373. expect(contact.addresses).toBeDefined();
  374. expect(contact.ims).toBeDefined();
  375. expect(contact.organizations).toBeDefined();
  376. expect(contact.birthday).toBe("f");
  377. expect(contact.note).toBe("i");
  378. expect(contact.photos).toBeDefined();
  379. expect(contact.categories).toBeDefined();
  380. expect(contact.urls).toBeDefined();
  381. });
  382. it("contacts.spec.11 should be able to define a ContactName object", function() {
  383. var contactName = new ContactName("Dr. First Last Jr.", "Last", "First", "Middle", "Dr.", "Jr.");
  384. expect(contactName).toBeDefined();
  385. expect(contactName.formatted).toBe("Dr. First Last Jr.");
  386. expect(contactName.familyName).toBe("Last");
  387. expect(contactName.givenName).toBe("First");
  388. expect(contactName.middleName).toBe("Middle");
  389. expect(contactName.honorificPrefix).toBe("Dr.");
  390. expect(contactName.honorificSuffix).toBe("Jr.");
  391. });
  392. it("contacts.spec.12 should be able to define a ContactField object", function() {
  393. var contactField = new ContactField("home", "8005551212", true);
  394. expect(contactField).toBeDefined();
  395. expect(contactField.type).toBe("home");
  396. expect(contactField.value).toBe("8005551212");
  397. expect(contactField.pref).toBe(true);
  398. });
  399. it("contacts.spec.13 ContactField object should coerce type and value properties to strings", function() {
  400. var contactField = new ContactField(12345678, 12345678, true);
  401. expect(contactField.type).toBe("12345678");
  402. expect(contactField.value).toBe("12345678");
  403. });
  404. it("contacts.spec.14 should be able to define a ContactAddress object", function() {
  405. var contactAddress = new ContactAddress(true, "home", "a", "b", "c", "d", "e", "f");
  406. expect(contactAddress).toBeDefined();
  407. expect(contactAddress.pref).toBe(true);
  408. expect(contactAddress.type).toBe("home");
  409. expect(contactAddress.formatted).toBe("a");
  410. expect(contactAddress.streetAddress).toBe("b");
  411. expect(contactAddress.locality).toBe("c");
  412. expect(contactAddress.region).toBe("d");
  413. expect(contactAddress.postalCode).toBe("e");
  414. expect(contactAddress.country).toBe("f");
  415. });
  416. it("contacts.spec.15 should be able to define a ContactOrganization object", function() {
  417. var contactOrg = new ContactOrganization(true, "home", "a", "b", "c", "d", "e", "f", "g");
  418. expect(contactOrg).toBeDefined();
  419. expect(contactOrg.pref).toBe(true);
  420. expect(contactOrg.type).toBe("home");
  421. expect(contactOrg.name).toBe("a");
  422. expect(contactOrg.department).toBe("b");
  423. expect(contactOrg.title).toBe("c");
  424. });
  425. it("contacts.spec.16 should be able to define a ContactFindOptions object", function() {
  426. var contactFindOptions = new ContactFindOptions("a", true, "b");
  427. expect(contactFindOptions).toBeDefined();
  428. expect(contactFindOptions.filter).toBe("a");
  429. expect(contactFindOptions.multiple).toBe(true);
  430. });
  431. it("contacts.spec.17 should contain a clone function", function() {
  432. var contact = new Contact();
  433. expect(contact.clone).toBeDefined();
  434. expect(typeof contact.clone).toBe('function');
  435. });
  436. it("contacts.spec.18 clone function should make deep copy of Contact Object", function() {
  437. var contact = new Contact();
  438. contact.id = 1;
  439. contact.displayName = "Test Name";
  440. contact.nickname = "Testy";
  441. contact.gender = "male";
  442. contact.note = "note to be cloned";
  443. contact.name = new ContactName("Mr. Test Name");
  444. var clonedContact = contact.clone();
  445. expect(contact.id).toBe(1);
  446. expect(clonedContact.id).toBe(null);
  447. expect(clonedContact.displayName).toBe(contact.displayName);
  448. expect(clonedContact.nickname).toBe(contact.nickname);
  449. expect(clonedContact.gender).toBe(contact.gender);
  450. expect(clonedContact.note).toBe(contact.note);
  451. expect(clonedContact.name.formatted).toBe(contact.name.formatted);
  452. expect(clonedContact.connected).toBe(contact.connected);
  453. });
  454. it("contacts.spec.19 should contain a save function", function() {
  455. var contact = new Contact();
  456. expect(contact.save).toBeDefined();
  457. expect(typeof contact.save).toBe('function');
  458. });
  459. it("contacts.spec.20 should contain a remove function", function() {
  460. var contact = new Contact();
  461. expect(contact.remove).toBeDefined();
  462. expect(typeof contact.remove).toBe('function');
  463. });
  464. });
  465. describe('save method', function() {
  466. afterEach(function (done) {
  467. removeContact(done, this.contactObj);
  468. });
  469. it("contacts.spec.21 should be able to save a contact", function(done) {
  470. // Save method is not supported on Windows platform
  471. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  472. pending();
  473. }
  474. var specContext = this;
  475. var bDay = new Date(1976, 6, 4);
  476. var obj = {
  477. "gender": "male",
  478. "note": "my note",
  479. "name": {
  480. "familyName": "Delete",
  481. "givenName": "Test"
  482. },
  483. "emails": [{
  484. "value": "here@there.com"
  485. }, {
  486. "value": "there@here.com"
  487. }],
  488. "birthday": bDay
  489. };
  490. var saveSuccess = function(obj) {
  491. specContext.contactObj = obj;
  492. expect(obj).toBeDefined();
  493. expect(obj.note).toBe('my note');
  494. expect(obj.name.familyName).toBe('Delete');
  495. expect(obj.name.givenName).toBe('Test');
  496. expect(obj.emails.length).toBe(2);
  497. expect(obj.emails[0].value).toBe('here@there.com');
  498. expect(obj.emails[1].value).toBe('there@here.com');
  499. expect(obj.birthday.toDateString()).toBe(bDay.toDateString());
  500. expect(obj.addresses).toBe(null);
  501. done();
  502. };
  503. var saveFail = fail.bind(null, done);
  504. navigator.contacts
  505. .create(obj)
  506. .save(saveSuccess, saveFail);
  507. });
  508. it("contacts.spec.22 update a contact", function(done) {
  509. // Save method is not supported on Windows platform
  510. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  511. pending();
  512. }
  513. var specContext = this;
  514. var aDay = new Date(1976, 6, 4);
  515. var bDay;
  516. var noteText = "an UPDATED note";
  517. var savedContact;
  518. var contact = {
  519. "gender": "male",
  520. "note": "my note",
  521. "name": {
  522. "familyName": "Delete",
  523. "givenName": "Test"
  524. },
  525. "emails": [{
  526. "value": "here@there.com"
  527. }, {
  528. "value": "there@here.com"
  529. }],
  530. "birthday": aDay
  531. };
  532. var saveFail = fail.bind(null, done);
  533. function updateSuccess(obj) {
  534. specContext.contactObj = obj;
  535. expect(obj).toBeDefined();
  536. expect(obj.id).toBe(savedContact.id);
  537. expect(obj.note).toBe(noteText);
  538. expect(obj.birthday.toDateString()).toBe(bDay.toDateString());
  539. expect(obj.emails.length).toBe(1);
  540. expect(obj.emails[0].value).toBe('here@there.com');
  541. done();
  542. }
  543. var saveSuccess = function(newContact) {
  544. specContext.contactObj = newContact;
  545. savedContact = newContact;
  546. newContact.emails[1].value = "";
  547. bDay = new Date(1975, 5, 4);
  548. newContact.birthday = bDay;
  549. newContact.note = noteText;
  550. newContact.save(updateSuccess, saveFail);
  551. };
  552. navigator.contacts
  553. .create(contact)
  554. .save(saveSuccess, saveFail);
  555. }, HIGH_TIMEOUT);
  556. });
  557. describe('Contact.remove method', function() {
  558. afterEach(function (done) {
  559. removeContact(done, this.contactObj);
  560. });
  561. it("contacts.spec.23 calling remove on a contact that has an id of null should return ContactError.UNKNOWN_ERROR", function(done) {
  562. var expectedFail = function(result) {
  563. expect(result.code).toBe(ContactError.UNKNOWN_ERROR);
  564. done();
  565. };
  566. var rmContact = new Contact();
  567. rmContact.remove(fail.bind(null, done), expectedFail);
  568. });
  569. it("contacts.spec.24 calling remove on a contact that does not exist should return ContactError.UNKNOWN_ERROR", function(done) {
  570. // remove method is not supported on Windows platform
  571. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  572. pending();
  573. }
  574. var rmWin = fail.bind(null, done);
  575. var rmFail = function(result) {
  576. expect(result.code).toBe(ContactError.UNKNOWN_ERROR);
  577. done();
  578. };
  579. // this is a bit risky as some devices may have contact ids that large
  580. var contact = new Contact("this string is supposed to be a unique identifier that will never show up on a device");
  581. contact.remove(rmWin, rmFail);
  582. }, MEDIUM_TIMEOUT);
  583. });
  584. describe("Round trip Contact tests (creating + save + delete + find)", function() {
  585. var saveAndFindBy = function (contact, fields, filter, callback, specContext) {
  586. removeContactsByFields(["note"], "DeleteMe", function() {
  587. contact.save(function(c_obj) {
  588. specContext.contactObj = c_obj;
  589. var findWin = function(cs) {
  590. expect(cs.length).toBe(1);
  591. specContext.contactObj = cs[0];
  592. callback(cs[0]);
  593. };
  594. var findFail = fail;
  595. var obj = new ContactFindOptions();
  596. obj.filter = filter;
  597. obj.multiple = true;
  598. navigator.contacts.find(fields, findWin, findFail, obj);
  599. }, fail);
  600. });
  601. };
  602. afterEach(function (done) {
  603. removeContact(done, this.contactObj);
  604. });
  605. it("contacts.spec.25 Creating, saving, finding a contact should work", function(done) {
  606. // Save method is not supported on Windows platform
  607. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  608. pending();
  609. }
  610. var contactName = "DeleteMe";
  611. var contact = new Contact();
  612. contact.name = new ContactName();
  613. contact.name.familyName = contactName;
  614. contact.note = "DeleteMe";
  615. saveAndFindBy(contact, ["displayName", "name"], contactName, function() {
  616. done();
  617. }, this);
  618. }, MEDIUM_TIMEOUT);
  619. it("contacts.spec.26 Creating, saving, finding a contact should work, removing it should work", function(done) {
  620. // Save method is not supported on Windows platform
  621. var specContext = this;
  622. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  623. pending();
  624. }
  625. var contactName = "DeleteMe";
  626. var contact = new Contact();
  627. contact.name = new ContactName();
  628. contact.name.familyName = contactName;
  629. contact.note = "DeleteMe";
  630. saveAndFindBy(contact, ["displayName", "name"], contactName, function(savedContact) {
  631. savedContact.remove(function() {
  632. specContext.contactObj = null;
  633. done();
  634. }, function(e) {
  635. throw ("Newly created contact's remove function invoked error callback. Test failed: " + JSON.stringify(e));
  636. });
  637. }, this);
  638. }, MEDIUM_TIMEOUT);
  639. it("contacts.spec.27 Should not be able to delete the same contact twice", function(done) {
  640. // Save method is not supported on Windows platform
  641. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  642. pending();
  643. }
  644. var specContext = this;
  645. var contactName = "DeleteMe2";
  646. var contact = new Contact();
  647. contact.name = new ContactName();
  648. contact.name.familyName = contactName;
  649. contact.note = "DeleteMe2";
  650. saveAndFindBy(contact, ["displayName", "name"], contactName, function(savedContact) {
  651. savedContact.remove(function() {
  652. specContext.contactObj = null;
  653. var findWin = function(seas) {
  654. expect(seas.length).toBe(0);
  655. savedContact.remove(function(e) {
  656. throw ("Success callback called after non-existent Contact object called remove(). Test failed: " + JSON.stringify(e));
  657. }, function(e) {
  658. expect(e.code).toBe(ContactError.UNKNOWN_ERROR);
  659. done();
  660. });
  661. };
  662. var obj = new ContactFindOptions();
  663. obj.filter = contactName;
  664. obj.multiple = true;
  665. navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, fail, obj);
  666. }, fail);
  667. }, this);
  668. }, MEDIUM_TIMEOUT);
  669. it("contacts.spec.28 should find a contact with unicode name", function (done) {
  670. // Save method is not supported on Windows platform
  671. if (isWindows || isWindowsPhone8) {
  672. pending();
  673. }
  674. var contactName = "\u2602";
  675. var contact = new Contact();
  676. contact.note = "DeleteMe";
  677. contact.name = new ContactName();
  678. contact.name.familyName = contactName;
  679. saveAndFindBy(contact, ["displayName", "name"], contactName, function() {
  680. done();
  681. }, this);
  682. }, MEDIUM_TIMEOUT);
  683. it("contacts.spec.29 should find a contact without a name", function (done) {
  684. // Save method is not supported on Windows platform
  685. if (isWindows || isWindowsPhone8) {
  686. pending();
  687. }
  688. var contact = new Contact();
  689. var phoneNumbers = [1];
  690. phoneNumbers[0] = new ContactField('work', '555-555-1234', true);
  691. contact.phoneNumbers = phoneNumbers;
  692. saveAndFindBy(contact, ["phoneNumbers"], "555-555-1234", function() {
  693. done();
  694. }, this);
  695. }, MEDIUM_TIMEOUT);
  696. it("contacts.spec.31 Find should return a contact with correct birthday field type", function(done) {
  697. // Save method is not supported on Windows platform
  698. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  699. pending();
  700. }
  701. var contactName = "DeleteMe";
  702. var bDay = new Date(1976, 7, 4);
  703. var contact = new Contact();
  704. contact.name = new ContactName();
  705. contact.name.familyName = contactName;
  706. contact.note = "DeleteMe";
  707. contact.birthday = bDay;
  708. saveAndFindBy(contact, ["displayName", "name"], contactName, function(found) {
  709. expect(found.birthday).toEqual(jasmine.any(Date));
  710. expect(found.birthday).toEqual(bDay);
  711. done();
  712. }, this);
  713. }, MEDIUM_TIMEOUT);
  714. it("contacts.spec.32 Find should return a contact with correct IM field", function(done) {
  715. // Save method is not supported on Windows platform
  716. if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) {
  717. pending();
  718. }
  719. var contactName = "DeleteMe";
  720. var ims = [{
  721. type: "Skype",
  722. value: "imValue"
  723. }];
  724. var contact = new Contact();
  725. contact.name = new ContactName();
  726. contact.name.familyName = contactName;
  727. contact.note = "DeleteMe";
  728. contact.ims = ims;
  729. saveAndFindBy(contact, ["displayName", "name"], contactName, function(found) {
  730. expect(found.ims).toEqual(jasmine.any(Array));
  731. expect(found.ims[0]).toBeDefined();
  732. if (found.ims[0]) {
  733. expect(found.ims[0].type).toEqual(cordova.platformId == 'android' ? ims[0].type : ims[0].type.toLowerCase());
  734. expect(found.ims[0].value).toEqual(ims[0].value);
  735. }
  736. done();
  737. }, this);
  738. }, MEDIUM_TIMEOUT);
  739. });
  740. describe('ContactError interface', function() {
  741. it("contacts.spec.30 ContactError constants should be defined", function() {
  742. expect(ContactError.UNKNOWN_ERROR).toBe(0);
  743. expect(ContactError.INVALID_ARGUMENT_ERROR).toBe(1);
  744. expect(ContactError.TIMEOUT_ERROR).toBe(2);
  745. expect(ContactError.PENDING_OPERATION_ERROR).toBe(3);
  746. expect(ContactError.IO_ERROR).toBe(4);
  747. expect(ContactError.NOT_SUPPORTED_ERROR).toBe(5);
  748. expect(ContactError.OPERATION_CANCELLED_ERROR).toBe(6);
  749. expect(ContactError.PERMISSION_DENIED_ERROR).toBe(20);
  750. });
  751. });
  752. });
  753. };
  754. /******************************************************************************/
  755. /******************************************************************************/
  756. /******************************************************************************/
  757. exports.defineManualTests = function(contentEl, createActionButton) {
  758. function getContacts(filter) {
  759. var results = document.getElementById('contact_results');
  760. var obj = new ContactFindOptions();
  761. if (filter) {
  762. obj.filter = filter;
  763. }
  764. obj.multiple = true;
  765. navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails", "urls", "note"], function(contacts) {
  766. var s = "";
  767. if (contacts.length === 0) {
  768. s = "No contacts found";
  769. } else {
  770. s = "Number of contacts: " + contacts.length + "<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
  771. for (var i = 0; i < contacts.length; i++) {
  772. var contact = contacts[i];
  773. var contactNameTag = contact.name ? "<tr><td>" + contact.name.formatted + "</td><td>" : "<tr><td>(No Name)</td><td>";
  774. s = s + contactNameTag;
  775. if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
  776. s = s + contact.phoneNumbers[0].value;
  777. }
  778. s = s + "</td><td>";
  779. if (contact.emails && contact.emails.length > 0) {
  780. s = s + contact.emails[0].value;
  781. }
  782. s = s + "</td></tr>";
  783. }
  784. s = s + "</table>";
  785. }
  786. results.innerHTML = s;
  787. }, function(e) {
  788. if (e.code === ContactError.NOT_SUPPORTED_ERROR) {
  789. results.innerHTML = "Searching for contacts is not supported.";
  790. } else {
  791. results.innerHTML = "Search failed: error " + e.code;
  792. }
  793. }, obj);
  794. }
  795. function filterContacts() {
  796. var filter = document.getElementById('searchstring');
  797. getContacts(filter.value);
  798. }
  799. function pickContact() {
  800. var results = document.getElementById('contact_results');
  801. navigator.contacts.pickContact(
  802. function (contact) {
  803. results.innerHTML = contact ?
  804. "Picked contact: <pre>" + JSON.stringify(contact, null, 4) + "</pre>" :
  805. "No contacts found";
  806. },
  807. function (e) {
  808. results.innerHTML = (e && e.code === ContactError.NOT_SUPPORTED_ERROR) ?
  809. "Searching for contacts is not supported." :
  810. (e && e.code === ContactError.OPERATION_CANCELLED_ERROR) ?
  811. "Pick cancelled" :
  812. "Pick failed: error " + (e && e.code);
  813. }
  814. );
  815. }
  816. function addContact(displayName, name, phoneNumber, birthday) {
  817. try {
  818. var results = document.getElementById('contact_results');
  819. var contact = navigator.contacts.create({ "displayName": displayName, "name": name, "birthday": birthday, "note": "DeleteMe" });
  820. var phoneNumbers = [1];
  821. phoneNumbers[0] = new ContactField('work', phoneNumber, true);
  822. contact.phoneNumbers = phoneNumbers;
  823. contact.save(function() {
  824. results.innerHTML = (displayName || "Nameless contact") + " saved.";
  825. }, function(e) {
  826. if (e.code === ContactError.NOT_SUPPORTED_ERROR) {
  827. results.innerHTML = "Saving contacts not supported.";
  828. } else {
  829. results.innerHTML = "Contact save failed: error " + e.code;
  830. }
  831. });
  832. } catch (e) {
  833. console.error(e.message);
  834. }
  835. }
  836. function addDooneyEvans() {
  837. var displayName = "Dooney Evans";
  838. var contactName = {
  839. formatted: "Dooney Evans",
  840. familyName: "Evans",
  841. givenName: "Dooney",
  842. middleName: ""
  843. };
  844. var phoneNumber = '512-555-1234';
  845. var birthday = new Date(1985, 0, 23);
  846. addContact(displayName, contactName, phoneNumber, birthday);
  847. }
  848. function addNamelessContact() {
  849. addContact();
  850. }
  851. function addUnicodeContact() {
  852. var displayName = "Н€йромонах \nФеофаЊ";
  853. var contactName = {
  854. formatted: "Н€йромонах \nФеофаЊ",
  855. familyName: "\nФеофаЊ",
  856. givenName: "Н€йромонах",
  857. middleName: ""
  858. };
  859. addContact(displayName, contactName);
  860. }
  861. function renameDooneyEvans() {
  862. var results = document.getElementById('contact_results');
  863. var obj = new ContactFindOptions();
  864. obj.filter = 'Dooney Evans';
  865. obj.multiple = false;
  866. navigator.contacts.find(['displayName', 'name'], function(contacts) {
  867. if (contacts.length === 0) {
  868. results.innerHTML = 'No contacts to update.';
  869. return;
  870. }
  871. var contact = contacts[0];
  872. contact.displayName = "Urist McContact";
  873. var name = new ContactName();
  874. name.givenName = "Urist";
  875. name.familyName = "McContact";
  876. contact.name = name;
  877. contact.save(function(updated) {
  878. results.innerHTML = 'Contact updated.';
  879. },function(e) {
  880. results.innerHTML = 'Update failed: error ' + e.code;
  881. });
  882. }, function(e) {
  883. if (e.code === ContactError.NOT_SUPPORTED_ERROR) {
  884. results.innerHTML = 'Searching for contacts is not supported.';
  885. } else {
  886. results.innerHTML = 'Search failed: error ' + e.code;
  887. }
  888. }, obj);
  889. }
  890. function removeTestContacts() {
  891. var results = document.getElementById('contact_results');
  892. results.innerHTML = "";
  893. var obj = new ContactFindOptions();
  894. obj.filter = 'DeleteMe';
  895. obj.multiple = true;
  896. navigator.contacts.find(['note'], function(contacts) {
  897. var removes = [];
  898. contacts.forEach(function(contact) {
  899. removes.push(contact);
  900. });
  901. if (removes.length === 0) {
  902. results.innerHTML = "No contacts to remove";
  903. return;
  904. }
  905. var nextToRemove;
  906. if (removes.length > 0) {
  907. nextToRemove = removes.shift();
  908. }
  909. function removeNext(item) {
  910. if (typeof item === 'undefined') {
  911. return;
  912. }
  913. if (removes.length > 0) {
  914. nextToRemove = removes.shift();
  915. } else {
  916. nextToRemove = undefined;
  917. }
  918. item.remove(function removeSucceeded() {
  919. results.innerHTML += "Removed a contact with ID " + item.id + "<br/>";
  920. removeNext(nextToRemove);
  921. }, function removeFailed() {
  922. results.innerHTML += "Failed to remove a contact with ID " + item.id + "<br/>";
  923. removeNext(nextToRemove);
  924. });
  925. }
  926. removeNext(nextToRemove);
  927. }, function(e) {
  928. if (e.code === ContactError.NOT_SUPPORTED_ERROR) {
  929. results.innerHTML = 'Searching for contacts is not supported.';
  930. } else {
  931. results.innerHTML = 'Search failed: error ' + e.code;
  932. }
  933. }, obj);
  934. }
  935. /******************************************************************************/
  936. contentEl.innerHTML = '<div id="info">' +
  937. '<b>Results:</b><br>' +
  938. '<div id="contact_results"></div>' +
  939. '</div>' +
  940. '<div id="get_contacts"></div>' +
  941. '<p>Expected result: Status box will show number of contacts and list them. May be empty on a fresh device until you click Add.</p>' +
  942. '<div id="filter_contacts">Search: <input type="text" id="searchstring"></div>' +
  943. '<p>Expected result: Will return only contacts which contain specified string</p>' +
  944. '<div id="pick_contact"></div>' +
  945. '<p>Expected result: Device\'s address book will be shown. After picking a contact status box will show Contact object, passed to success callback</p>' +
  946. '<div id="add_contact"></div>' +
  947. '<p>Expected result: Will add a new contact. Log will say "Contact saved." or "Saving contacts not supported." if not supported on current platform. Verify by running Get phone contacts again</p>' +
  948. '<div id="update_contact"></div>' +
  949. '<p>Expected result: Will rename "Dooney Evans" to "Urist McContact".</p>' +
  950. '<div id="remove_contacts"></div>' +
  951. '<p>Expected result: Will remove all contacts created by these tests. Log will output success or failure and ID of the deleted contacts.</p>';
  952. createActionButton("Get phone's contacts", function() {
  953. getContacts();
  954. }, 'get_contacts');
  955. createActionButton("Filter contacts", function() {
  956. filterContacts();
  957. }, 'filter_contacts');
  958. createActionButton("Pick contact", function() {
  959. pickContact();
  960. }, 'pick_contact');
  961. createActionButton("Add a new contact 'Dooney Evans'", function() {
  962. addDooneyEvans();
  963. }, 'add_contact');
  964. createActionButton("Add new nameless contact", function() {
  965. addNamelessContact();
  966. }, 'add_contact');
  967. createActionButton("Add new unicode contact", function() {
  968. addUnicodeContact();
  969. }, 'add_contact');
  970. createActionButton("Rename 'Dooney Evans'", function() {
  971. renameDooneyEvans();
  972. }, 'update_contact');
  973. createActionButton("Delete all test contacts", function() {
  974. removeTestContacts();
  975. }, 'remove_contacts');
  976. };