/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /* jshint jasmine: true */ /* global WinJS */ exports.defineAutoTests = function() { var isWindowsPhone8 = cordova.platformId == 'windowsphone'; var isWindows = (cordova.platformId === "windows") || (cordova.platformId === "windows8"); var isWindowsPhone81 = isWindows && WinJS.Utilities.isPhone; // Error callback spies should not be called var errorCallbacks = {}; errorCallbacks[ContactError.UNKNOWN_ERROR] = jasmine.createSpy('unknownErrorCallback'); errorCallbacks[ContactError.INVALID_ARGUMENT_ERROR] = jasmine.createSpy('invalidArgumentErrorCallback'); errorCallbacks[ContactError.TIMEOUT_ERROR] = jasmine.createSpy('timeoutErrorCallback'); errorCallbacks[ContactError.PENDING_OPERATION_ERROR] = jasmine.createSpy('pendingOperationErrorCallback'); errorCallbacks[ContactError.IO_ERROR] = jasmine.createSpy('ioErrorCallback'); errorCallbacks[ContactError.NOT_SUPPORTED_ERROR] = jasmine.createSpy('notSupportedErrorCallback'); errorCallbacks[ContactError.OPERATION_CANCELLED_ERROR] = jasmine.createSpy('operationCancelledErrorCallback'); errorCallbacks[ContactError.PERMISSION_DENIED_ERROR] = jasmine.createSpy('permissionDeniedErrorCallback'); var isIOSPermissionBlocked = false; var fail = function(done) { expect(true).toBe(false); done(); }; var MEDIUM_TIMEOUT = 30000; var HIGH_TIMEOUT = 120000; var removeContact = function(done, contactObj) { if (!contactObj) { done(); return; } contactObj.remove(function() { done(); }, function(contactError) { if (contactError) { if (errorCallbacks[contactError.code]) { errorCallbacks[contactError.code](); } else { fail(done); } } for (var error in errorCallbacks) { expect(errorCallbacks[error]).not.toHaveBeenCalled(); } done(); }); }; function removeContactsByFields(fields, filter, done) { var obj = new ContactFindOptions(); obj.filter = filter; obj.multiple = true; navigator.contacts.find(fields, function(contacts) { var removes = []; contacts.forEach(function(contact) { removes.push(contact); }); if (removes.length === 0) { done(); return; } var nextToRemove; if (removes.length > 0) { nextToRemove = removes.shift(); } function removeNext(item) { if (typeof item === 'undefined') { done(); return; } if (removes.length > 0) { nextToRemove = removes.shift(); } else { nextToRemove = undefined; } item.remove(function removeSucceeded() { removeNext(nextToRemove); }, function removeFailed() { removeNext(nextToRemove); }); } removeNext(nextToRemove); }, done, obj); } describe("Contacts (navigator.contacts)", function() { this.contactObj = null; it("contacts.spec.1 should exist", function() { expect(navigator.contacts).toBeDefined(); }); it("contacts.spec.2 should contain a find function", function() { expect(navigator.contacts.find).toBeDefined(); expect(typeof navigator.contacts.find).toBe('function'); }); describe("find method", function() { it("contacts.spec.3 success callback should be called with an array", function(done) { // Find method is not supported on Windows platform if (isWindows && !isWindowsPhone81) { pending(); return; } var win = function(result) { expect(result).toBeDefined(); expect(result instanceof Array).toBe(true); done(); }, obj = new ContactFindOptions(); obj.filter = ""; obj.multiple = true; function failed(err) { if (err.code == ContactError.PERMISSION_DENIED_ERROR) { isIOSPermissionBlocked = true; done(); } } navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, failed, obj); }, HIGH_TIMEOUT); // give permission buster or a user a chance to accept the permission alert it("contacts.spec.4 success callback should be called with an array, even if partial ContactFindOptions specified", function(done) { // Find method is not supported on Windows platform if ((isWindows && !isWindowsPhone81) || isIOSPermissionBlocked) { pending(); return; } var win = function(result) { expect(result).toBeDefined(); expect(result instanceof Array).toBe(true); done(); }; navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, fail.bind(null, done), { multiple: true }); }); it("contacts.spec.5 should throw an exception if success callback is empty", function() { var obj = new ContactFindOptions(); obj.filter = ""; obj.multiple = true; expect(function() { navigator.contacts.find(["displayName", "name", "emails", "phoneNumbers"], null, function (err) { expect(err).toBeUndefined(); }, obj); }).toThrow(); }); it("contacts.spec.6 error callback should be called when no fields are specified", function(done) { var win = fail, // we don't want this to be called error = function(result) { expect(result).toBeDefined(); expect(result.code).toBe(ContactError.INVALID_ARGUMENT_ERROR); done(); }, obj = new ContactFindOptions(); obj.filter = ""; obj.multiple = true; navigator.contacts.find([], win, error, obj); }); describe("with newly-created contact", function() { afterEach(function (done) { removeContact(done, this.contactObj); }); it("contacts.spec.7 should be able to find a contact by name", function(done) { // Find method is not supported on Windows Store apps. // also this test will be skipped for Windows Phone 8.1 because function "save" not supported on WP8.1 if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var specContext = this; specContext.contactObj = new Contact(); specContext.contactObj.name = new ContactName(); specContext.contactObj.name.familyName = "Delete"; var foundName = function(result) { var bFound = false; try { for (var i = 0; i < result.length; i++) { if (result[i].name.familyName == "Delete") { bFound = true; break; } } } catch (e) { return false; } return bFound; }; var test = function(savedContact) { // update so contact will get removed specContext.contactObj = savedContact; // ---- // Find asserts // --- var findWin = function(object) { expect(object instanceof Array).toBe(true); expect(object.length >= 1).toBe(true); expect(foundName(object)).toBe(true); done(); }, findFail = fail, obj = new ContactFindOptions(); obj.filter = "Delete"; obj.multiple = true; navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail.bind(null, done), obj); }; specContext.contactObj.save(test, fail.bind(null, done)); }); it("contacts.spec.7.1 should contain displayName if specified in desiredFields", function(done) { if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var testDisplayName = "testContact"; var specContext = this; specContext.contactObj = new Contact(); specContext.contactObj.displayName = testDisplayName; var win = function(contactResult) { expect(contactResult.length > 0).toBe(true); var namesDisplayed = contactResult.every(function(contact, index) { return contact.displayName !== null; }); expect(namesDisplayed).toBe(true); done(); }; var onSuccessSave = function(savedContact) { specContext.contactObj = savedContact; var options = new ContactFindOptions(); options.filter = testDisplayName; options.multiple = true; options.desiredFields = [navigator.contacts.fieldType.displayName]; navigator.contacts.find(["displayName", "nickname"], win, fail.bind(null, done), options); }; specContext.contactObj.save(onSuccessSave, fail.bind(null, done)); }); it("contacts.spec.7.2 should find contact despite id isn't string ", function(done) { if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var testDisplayName = "testContact"; var specContext = this; specContext.contactObj = new Contact(); specContext.contactObj.displayName = testDisplayName; var win = function(contactResult) { expect(contactResult.length > 0).toBe(true); done(); }; var onSuccessSave = function(savedContact) { specContext.contactObj = savedContact; var options = new ContactFindOptions(); options.filter = savedContact.id; options.multiple = true; navigator.contacts.find(["id"], win, fail.bind(null, done), options); }; specContext.contactObj.save(onSuccessSave, fail.bind(null, done)); }); it("contacts.spec.7.3 should contain custom label in type", function(done) { if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var testDisplayName = "testContact"; var customLabel = "myType"; var testContactDetail = new ContactField(customLabel, "a", true); var contactFields = ["phoneNumbers", "emails", "urls", "ims"]; var specContext = this; specContext.contactObj = new Contact(); specContext.contactObj.nickname = testDisplayName; specContext.contactObj.displayName = testDisplayName; contactFields.forEach(function(contactField) { specContext.contactObj[contactField] = []; specContext.contactObj[contactField][0] = testContactDetail; }); specContext.contactObj.addresses = []; specContext.contactObj.addresses[0] = new ContactAddress(true, customLabel, "a", "b", "c", "d", "e", "f"); var checkTypes = function(contact) { var allFieldsWithCustomLabel = contactFields.concat(["addresses"]); return allFieldsWithCustomLabel.every(function(contactField) { return contact[contactField] && contact[contactField][0].type === customLabel; }); }; var win = function(contactResult) { expect(contactResult.length > 0).toBe(true); var typesCustomized = contactResult.every(function(contact) { return checkTypes(contact); }); expect(typesCustomized).toBe(true); done(); }; var onSuccessSave = function(savedContact) { expect(checkTypes(savedContact)).toBe(true); specContext.contactObj = savedContact; var options = new ContactFindOptions(); options.filter = testDisplayName; options.multiple = true; navigator.contacts.find(["displayName", "nickname"], win, fail.bind(null, done), options); }; specContext.contactObj.save(onSuccessSave, fail.bind(null, done)); }); it('spec 7.4 contact detail type should equal default label', function(done) { if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var specContext = this; specContext.contactObj = navigator.contacts.create({ "displayName": "test name", "ims": [{ "type": "SKYPE", "value": "000" }] }); specContext.contactObj.save(onSuccessSave, fail.bind(null, done)); function onSuccessSave(savedContact) { specContext.contactObj = savedContact; var imsType = savedContact.ims[0].type; var expectedType = (cordova.platformId == 'android') ? "Skype" : "skype"; expect(imsType).toBe(expectedType); done(); } }); }); }); describe('create method', function() { it("contacts.spec.8 should exist", function() { expect(navigator.contacts.create).toBeDefined(); expect(typeof navigator.contacts.create).toBe('function'); }); it("contacts.spec.9 should return a Contact object", function() { var bDay = new Date(1976, 7, 4); var obj = navigator.contacts.create({ "displayName": "test name", "gender": "male", "note": "my note", "name": { "formatted": "Mr. Test Name" }, "emails": [{ "value": "here@there.com" }, { "value": "there@here.com" }], "birthday": bDay }); expect(obj).toBeDefined(); expect(obj.displayName).toBe('test name'); expect(obj.note).toBe('my note'); expect(obj.name.formatted).toBe('Mr. Test Name'); expect(obj.emails.length).toBe(2); expect(obj.emails[0].value).toBe('here@there.com'); expect(obj.emails[1].value).toBe('there@here.com'); expect(obj.nickname).toBe(null); expect(obj.birthday).toBe(bDay); }); }); describe("Contact object", function() { it("contacts.spec.10 should be able to create instance", function() { var contact = new Contact("a", "b", new ContactName("a", "b", "c", "d", "e", "f"), "c", [], [], [], [], [], "f", "i", [], [], []); expect(contact).toBeDefined(); expect(contact.id).toBe("a"); expect(contact.displayName).toBe("b"); expect(contact.name.formatted).toBe("a"); expect(contact.nickname).toBe("c"); expect(contact.phoneNumbers).toBeDefined(); expect(contact.emails).toBeDefined(); expect(contact.addresses).toBeDefined(); expect(contact.ims).toBeDefined(); expect(contact.organizations).toBeDefined(); expect(contact.birthday).toBe("f"); expect(contact.note).toBe("i"); expect(contact.photos).toBeDefined(); expect(contact.categories).toBeDefined(); expect(contact.urls).toBeDefined(); }); it("contacts.spec.11 should be able to define a ContactName object", function() { var contactName = new ContactName("Dr. First Last Jr.", "Last", "First", "Middle", "Dr.", "Jr."); expect(contactName).toBeDefined(); expect(contactName.formatted).toBe("Dr. First Last Jr."); expect(contactName.familyName).toBe("Last"); expect(contactName.givenName).toBe("First"); expect(contactName.middleName).toBe("Middle"); expect(contactName.honorificPrefix).toBe("Dr."); expect(contactName.honorificSuffix).toBe("Jr."); }); it("contacts.spec.12 should be able to define a ContactField object", function() { var contactField = new ContactField("home", "8005551212", true); expect(contactField).toBeDefined(); expect(contactField.type).toBe("home"); expect(contactField.value).toBe("8005551212"); expect(contactField.pref).toBe(true); }); it("contacts.spec.13 ContactField object should coerce type and value properties to strings", function() { var contactField = new ContactField(12345678, 12345678, true); expect(contactField.type).toBe("12345678"); expect(contactField.value).toBe("12345678"); }); it("contacts.spec.14 should be able to define a ContactAddress object", function() { var contactAddress = new ContactAddress(true, "home", "a", "b", "c", "d", "e", "f"); expect(contactAddress).toBeDefined(); expect(contactAddress.pref).toBe(true); expect(contactAddress.type).toBe("home"); expect(contactAddress.formatted).toBe("a"); expect(contactAddress.streetAddress).toBe("b"); expect(contactAddress.locality).toBe("c"); expect(contactAddress.region).toBe("d"); expect(contactAddress.postalCode).toBe("e"); expect(contactAddress.country).toBe("f"); }); it("contacts.spec.15 should be able to define a ContactOrganization object", function() { var contactOrg = new ContactOrganization(true, "home", "a", "b", "c", "d", "e", "f", "g"); expect(contactOrg).toBeDefined(); expect(contactOrg.pref).toBe(true); expect(contactOrg.type).toBe("home"); expect(contactOrg.name).toBe("a"); expect(contactOrg.department).toBe("b"); expect(contactOrg.title).toBe("c"); }); it("contacts.spec.16 should be able to define a ContactFindOptions object", function() { var contactFindOptions = new ContactFindOptions("a", true, "b"); expect(contactFindOptions).toBeDefined(); expect(contactFindOptions.filter).toBe("a"); expect(contactFindOptions.multiple).toBe(true); }); it("contacts.spec.17 should contain a clone function", function() { var contact = new Contact(); expect(contact.clone).toBeDefined(); expect(typeof contact.clone).toBe('function'); }); it("contacts.spec.18 clone function should make deep copy of Contact Object", function() { var contact = new Contact(); contact.id = 1; contact.displayName = "Test Name"; contact.nickname = "Testy"; contact.gender = "male"; contact.note = "note to be cloned"; contact.name = new ContactName("Mr. Test Name"); var clonedContact = contact.clone(); expect(contact.id).toBe(1); expect(clonedContact.id).toBe(null); expect(clonedContact.displayName).toBe(contact.displayName); expect(clonedContact.nickname).toBe(contact.nickname); expect(clonedContact.gender).toBe(contact.gender); expect(clonedContact.note).toBe(contact.note); expect(clonedContact.name.formatted).toBe(contact.name.formatted); expect(clonedContact.connected).toBe(contact.connected); }); it("contacts.spec.19 should contain a save function", function() { var contact = new Contact(); expect(contact.save).toBeDefined(); expect(typeof contact.save).toBe('function'); }); it("contacts.spec.20 should contain a remove function", function() { var contact = new Contact(); expect(contact.remove).toBeDefined(); expect(typeof contact.remove).toBe('function'); }); }); describe('save method', function() { afterEach(function (done) { removeContact(done, this.contactObj); }); it("contacts.spec.21 should be able to save a contact", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var specContext = this; var bDay = new Date(1976, 6, 4); var obj = { "gender": "male", "note": "my note", "name": { "familyName": "Delete", "givenName": "Test" }, "emails": [{ "value": "here@there.com" }, { "value": "there@here.com" }], "birthday": bDay }; var saveSuccess = function(obj) { specContext.contactObj = obj; expect(obj).toBeDefined(); expect(obj.note).toBe('my note'); expect(obj.name.familyName).toBe('Delete'); expect(obj.name.givenName).toBe('Test'); expect(obj.emails.length).toBe(2); expect(obj.emails[0].value).toBe('here@there.com'); expect(obj.emails[1].value).toBe('there@here.com'); expect(obj.birthday.toDateString()).toBe(bDay.toDateString()); expect(obj.addresses).toBe(null); done(); }; var saveFail = fail.bind(null, done); navigator.contacts .create(obj) .save(saveSuccess, saveFail); }); it("contacts.spec.22 update a contact", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var specContext = this; var aDay = new Date(1976, 6, 4); var bDay; var noteText = "an UPDATED note"; var savedContact; var contact = { "gender": "male", "note": "my note", "name": { "familyName": "Delete", "givenName": "Test" }, "emails": [{ "value": "here@there.com" }, { "value": "there@here.com" }], "birthday": aDay }; var saveFail = fail.bind(null, done); function updateSuccess(obj) { specContext.contactObj = obj; expect(obj).toBeDefined(); expect(obj.id).toBe(savedContact.id); expect(obj.note).toBe(noteText); expect(obj.birthday.toDateString()).toBe(bDay.toDateString()); expect(obj.emails.length).toBe(1); expect(obj.emails[0].value).toBe('here@there.com'); done(); } var saveSuccess = function(newContact) { specContext.contactObj = newContact; savedContact = newContact; newContact.emails[1].value = ""; bDay = new Date(1975, 5, 4); newContact.birthday = bDay; newContact.note = noteText; newContact.save(updateSuccess, saveFail); }; navigator.contacts .create(contact) .save(saveSuccess, saveFail); }, HIGH_TIMEOUT); }); describe('Contact.remove method', function() { afterEach(function (done) { removeContact(done, this.contactObj); }); it("contacts.spec.23 calling remove on a contact that has an id of null should return ContactError.UNKNOWN_ERROR", function(done) { var expectedFail = function(result) { expect(result.code).toBe(ContactError.UNKNOWN_ERROR); done(); }; var rmContact = new Contact(); rmContact.remove(fail.bind(null, done), expectedFail); }); it("contacts.spec.24 calling remove on a contact that does not exist should return ContactError.UNKNOWN_ERROR", function(done) { // remove method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var rmWin = fail.bind(null, done); var rmFail = function(result) { expect(result.code).toBe(ContactError.UNKNOWN_ERROR); done(); }; // this is a bit risky as some devices may have contact ids that large var contact = new Contact("this string is supposed to be a unique identifier that will never show up on a device"); contact.remove(rmWin, rmFail); }, MEDIUM_TIMEOUT); }); describe("Round trip Contact tests (creating + save + delete + find)", function() { var saveAndFindBy = function (contact, fields, filter, callback, specContext) { removeContactsByFields(["note"], "DeleteMe", function() { contact.save(function(c_obj) { specContext.contactObj = c_obj; var findWin = function(cs) { expect(cs.length).toBe(1); specContext.contactObj = cs[0]; callback(cs[0]); }; var findFail = fail; var obj = new ContactFindOptions(); obj.filter = filter; obj.multiple = true; navigator.contacts.find(fields, findWin, findFail, obj); }, fail); }); }; afterEach(function (done) { removeContact(done, this.contactObj); }); it("contacts.spec.25 Creating, saving, finding a contact should work", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var contactName = "DeleteMe"; var contact = new Contact(); contact.name = new ContactName(); contact.name.familyName = contactName; contact.note = "DeleteMe"; saveAndFindBy(contact, ["displayName", "name"], contactName, function() { done(); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.26 Creating, saving, finding a contact should work, removing it should work", function(done) { // Save method is not supported on Windows platform var specContext = this; if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var contactName = "DeleteMe"; var contact = new Contact(); contact.name = new ContactName(); contact.name.familyName = contactName; contact.note = "DeleteMe"; saveAndFindBy(contact, ["displayName", "name"], contactName, function(savedContact) { savedContact.remove(function() { specContext.contactObj = null; done(); }, function(e) { throw ("Newly created contact's remove function invoked error callback. Test failed: " + JSON.stringify(e)); }); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.27 Should not be able to delete the same contact twice", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var specContext = this; var contactName = "DeleteMe2"; var contact = new Contact(); contact.name = new ContactName(); contact.name.familyName = contactName; contact.note = "DeleteMe2"; saveAndFindBy(contact, ["displayName", "name"], contactName, function(savedContact) { savedContact.remove(function() { specContext.contactObj = null; var findWin = function(seas) { expect(seas.length).toBe(0); savedContact.remove(function(e) { throw ("Success callback called after non-existent Contact object called remove(). Test failed: " + JSON.stringify(e)); }, function(e) { expect(e.code).toBe(ContactError.UNKNOWN_ERROR); done(); }); }; var obj = new ContactFindOptions(); obj.filter = contactName; obj.multiple = true; navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, fail, obj); }, fail); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.28 should find a contact with unicode name", function (done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8) { pending(); } var contactName = "\u2602"; var contact = new Contact(); contact.note = "DeleteMe"; contact.name = new ContactName(); contact.name.familyName = contactName; saveAndFindBy(contact, ["displayName", "name"], contactName, function() { done(); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.29 should find a contact without a name", function (done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8) { pending(); } var contact = new Contact(); var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('work', '555-555-1234', true); contact.phoneNumbers = phoneNumbers; saveAndFindBy(contact, ["phoneNumbers"], "555-555-1234", function() { done(); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.31 Find should return a contact with correct birthday field type", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var contactName = "DeleteMe"; var bDay = new Date(1976, 7, 4); var contact = new Contact(); contact.name = new ContactName(); contact.name.familyName = contactName; contact.note = "DeleteMe"; contact.birthday = bDay; saveAndFindBy(contact, ["displayName", "name"], contactName, function(found) { expect(found.birthday).toEqual(jasmine.any(Date)); expect(found.birthday).toEqual(bDay); done(); }, this); }, MEDIUM_TIMEOUT); it("contacts.spec.32 Find should return a contact with correct IM field", function(done) { // Save method is not supported on Windows platform if (isWindows || isWindowsPhone8 || isIOSPermissionBlocked) { pending(); } var contactName = "DeleteMe"; var ims = [{ type: "Skype", value: "imValue" }]; var contact = new Contact(); contact.name = new ContactName(); contact.name.familyName = contactName; contact.note = "DeleteMe"; contact.ims = ims; saveAndFindBy(contact, ["displayName", "name"], contactName, function(found) { expect(found.ims).toEqual(jasmine.any(Array)); expect(found.ims[0]).toBeDefined(); if (found.ims[0]) { expect(found.ims[0].type).toEqual(cordova.platformId == 'android' ? ims[0].type : ims[0].type.toLowerCase()); expect(found.ims[0].value).toEqual(ims[0].value); } done(); }, this); }, MEDIUM_TIMEOUT); }); describe('ContactError interface', function() { it("contacts.spec.30 ContactError constants should be defined", function() { expect(ContactError.UNKNOWN_ERROR).toBe(0); expect(ContactError.INVALID_ARGUMENT_ERROR).toBe(1); expect(ContactError.TIMEOUT_ERROR).toBe(2); expect(ContactError.PENDING_OPERATION_ERROR).toBe(3); expect(ContactError.IO_ERROR).toBe(4); expect(ContactError.NOT_SUPPORTED_ERROR).toBe(5); expect(ContactError.OPERATION_CANCELLED_ERROR).toBe(6); expect(ContactError.PERMISSION_DENIED_ERROR).toBe(20); }); }); }); }; /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ exports.defineManualTests = function(contentEl, createActionButton) { function getContacts(filter) { var results = document.getElementById('contact_results'); var obj = new ContactFindOptions(); if (filter) { obj.filter = filter; } obj.multiple = true; navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails", "urls", "note"], function(contacts) { var s = ""; if (contacts.length === 0) { s = "No contacts found"; } else { s = "Number of contacts: " + contacts.length + "<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>"; for (var i = 0; i < contacts.length; i++) { var contact = contacts[i]; var contactNameTag = contact.name ? "<tr><td>" + contact.name.formatted + "</td><td>" : "<tr><td>(No Name)</td><td>"; s = s + contactNameTag; if (contact.phoneNumbers && contact.phoneNumbers.length > 0) { s = s + contact.phoneNumbers[0].value; } s = s + "</td><td>"; if (contact.emails && contact.emails.length > 0) { s = s + contact.emails[0].value; } s = s + "</td></tr>"; } s = s + "</table>"; } results.innerHTML = s; }, function(e) { if (e.code === ContactError.NOT_SUPPORTED_ERROR) { results.innerHTML = "Searching for contacts is not supported."; } else { results.innerHTML = "Search failed: error " + e.code; } }, obj); } function filterContacts() { var filter = document.getElementById('searchstring'); getContacts(filter.value); } function pickContact() { var results = document.getElementById('contact_results'); navigator.contacts.pickContact( function (contact) { results.innerHTML = contact ? "Picked contact: <pre>" + JSON.stringify(contact, null, 4) + "</pre>" : "No contacts found"; }, function (e) { results.innerHTML = (e && e.code === ContactError.NOT_SUPPORTED_ERROR) ? "Searching for contacts is not supported." : (e && e.code === ContactError.OPERATION_CANCELLED_ERROR) ? "Pick cancelled" : "Pick failed: error " + (e && e.code); } ); } function addContact(displayName, name, phoneNumber, birthday) { try { var results = document.getElementById('contact_results'); var contact = navigator.contacts.create({ "displayName": displayName, "name": name, "birthday": birthday, "note": "DeleteMe" }); var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('work', phoneNumber, true); contact.phoneNumbers = phoneNumbers; contact.save(function() { results.innerHTML = (displayName || "Nameless contact") + " saved."; }, function(e) { if (e.code === ContactError.NOT_SUPPORTED_ERROR) { results.innerHTML = "Saving contacts not supported."; } else { results.innerHTML = "Contact save failed: error " + e.code; } }); } catch (e) { console.error(e.message); } } function addDooneyEvans() { var displayName = "Dooney Evans"; var contactName = { formatted: "Dooney Evans", familyName: "Evans", givenName: "Dooney", middleName: "" }; var phoneNumber = '512-555-1234'; var birthday = new Date(1985, 0, 23); addContact(displayName, contactName, phoneNumber, birthday); } function addNamelessContact() { addContact(); } function addUnicodeContact() { var displayName = "Н€йромонах \nФеофаЊ"; var contactName = { formatted: "Н€йромонах \nФеофаЊ", familyName: "\nФеофаЊ", givenName: "Н€йромонах", middleName: "" }; addContact(displayName, contactName); } function renameDooneyEvans() { var results = document.getElementById('contact_results'); var obj = new ContactFindOptions(); obj.filter = 'Dooney Evans'; obj.multiple = false; navigator.contacts.find(['displayName', 'name'], function(contacts) { if (contacts.length === 0) { results.innerHTML = 'No contacts to update.'; return; } var contact = contacts[0]; contact.displayName = "Urist McContact"; var name = new ContactName(); name.givenName = "Urist"; name.familyName = "McContact"; contact.name = name; contact.save(function(updated) { results.innerHTML = 'Contact updated.'; },function(e) { results.innerHTML = 'Update failed: error ' + e.code; }); }, function(e) { if (e.code === ContactError.NOT_SUPPORTED_ERROR) { results.innerHTML = 'Searching for contacts is not supported.'; } else { results.innerHTML = 'Search failed: error ' + e.code; } }, obj); } function removeTestContacts() { var results = document.getElementById('contact_results'); results.innerHTML = ""; var obj = new ContactFindOptions(); obj.filter = 'DeleteMe'; obj.multiple = true; navigator.contacts.find(['note'], function(contacts) { var removes = []; contacts.forEach(function(contact) { removes.push(contact); }); if (removes.length === 0) { results.innerHTML = "No contacts to remove"; return; } var nextToRemove; if (removes.length > 0) { nextToRemove = removes.shift(); } function removeNext(item) { if (typeof item === 'undefined') { return; } if (removes.length > 0) { nextToRemove = removes.shift(); } else { nextToRemove = undefined; } item.remove(function removeSucceeded() { results.innerHTML += "Removed a contact with ID " + item.id + "<br/>"; removeNext(nextToRemove); }, function removeFailed() { results.innerHTML += "Failed to remove a contact with ID " + item.id + "<br/>"; removeNext(nextToRemove); }); } removeNext(nextToRemove); }, function(e) { if (e.code === ContactError.NOT_SUPPORTED_ERROR) { results.innerHTML = 'Searching for contacts is not supported.'; } else { results.innerHTML = 'Search failed: error ' + e.code; } }, obj); } /******************************************************************************/ contentEl.innerHTML = '<div id="info">' + '<b>Results:</b><br>' + '<div id="contact_results"></div>' + '</div>' + '<div id="get_contacts"></div>' + '<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>' + '<div id="filter_contacts">Search: <input type="text" id="searchstring"></div>' + '<p>Expected result: Will return only contacts which contain specified string</p>' + '<div id="pick_contact"></div>' + '<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>' + '<div id="add_contact"></div>' + '<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>' + '<div id="update_contact"></div>' + '<p>Expected result: Will rename "Dooney Evans" to "Urist McContact".</p>' + '<div id="remove_contacts"></div>' + '<p>Expected result: Will remove all contacts created by these tests. Log will output success or failure and ID of the deleted contacts.</p>'; createActionButton("Get phone's contacts", function() { getContacts(); }, 'get_contacts'); createActionButton("Filter contacts", function() { filterContacts(); }, 'filter_contacts'); createActionButton("Pick contact", function() { pickContact(); }, 'pick_contact'); createActionButton("Add a new contact 'Dooney Evans'", function() { addDooneyEvans(); }, 'add_contact'); createActionButton("Add new nameless contact", function() { addNamelessContact(); }, 'add_contact'); createActionButton("Add new unicode contact", function() { addUnicodeContact(); }, 'add_contact'); createActionButton("Rename 'Dooney Evans'", function() { renameDooneyEvans(); }, 'update_contact'); createActionButton("Delete all test contacts", function() { removeTestContacts(); }, 'remove_contacts'); };