UNPKG

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