Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
19
gaia/apps/communications/contacts/test/marionette/.jshintrc
Executable file
19
gaia/apps/communications/contacts/test/marionette/.jshintrc
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../../../../../.jshintrc",
|
||||
"nonew": false,
|
||||
"predef": [
|
||||
"__dirname",
|
||||
"module",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"marionette",
|
||||
"marionetteScriptFinished",
|
||||
"require",
|
||||
"define",
|
||||
"requireApp"
|
||||
]
|
||||
}
|
||||
253
gaia/apps/communications/contacts/test/marionette/activities_test.js
Executable file
253
gaia/apps/communications/contacts/test/marionette/activities_test.js
Executable file
|
|
@ -0,0 +1,253 @@
|
|||
'use strict';
|
||||
/* global MozActivity */
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var Dialer = require('../../../dialer/test/marionette/lib/dialer');
|
||||
var Sms = require('./lib/sms');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
marionette('Contacts > Activities', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
|
||||
var dialerSubject;
|
||||
|
||||
var smsSubject;
|
||||
var smsSelectors;
|
||||
|
||||
var subject;
|
||||
var selectors;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
selectors = Contacts.Selectors;
|
||||
|
||||
dialerSubject = new Dialer(client);
|
||||
|
||||
smsSubject = new Sms(client);
|
||||
smsSelectors = Sms.Selectors;
|
||||
});
|
||||
|
||||
suite('open text/vcard activity', function() {
|
||||
|
||||
setup(function() {
|
||||
smsSubject.launch(); // We open some app to start a Marionette session.
|
||||
});
|
||||
|
||||
function getListItems() {
|
||||
return client.executeScript(function() {
|
||||
return document.querySelectorAll('#multiple-select-container li');
|
||||
});
|
||||
}
|
||||
|
||||
test('> with only one contact', function() {
|
||||
client.executeScript(function(vCardFile) {
|
||||
new MozActivity({
|
||||
name: 'open',
|
||||
data: {
|
||||
type: 'text/vcard',
|
||||
filename: 'vcard_4.vcf',
|
||||
blob: new Blob([vCardFile], {type: 'text/vcard'})
|
||||
}
|
||||
});
|
||||
}, [fs.readFileSync(__dirname + '/data/vcard_4.vcf', 'utf8')]);
|
||||
|
||||
var iframe = 'iframe[src="' + Contacts.URL +
|
||||
'/contacts/views/vcard_load/vcard_load.html"]';
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(client.findElement(iframe), {'focus': true});
|
||||
client.helper.waitForElement(selectors.multipleSelectSave);
|
||||
|
||||
assert.ok(getListItems().length === 1); // vcard has one element
|
||||
});
|
||||
|
||||
test('> with multiple contacts', function() {
|
||||
client.executeScript(function(vCardFile) {
|
||||
new MozActivity({
|
||||
name: 'open',
|
||||
data: {
|
||||
type: 'text/vcard',
|
||||
filename: 'vcard_21_multiple.vcf',
|
||||
blob: new Blob([vCardFile], {type: 'text/vcard'})
|
||||
}
|
||||
});
|
||||
}, [fs.readFileSync(__dirname + '/data/vcard_21_multiple.vcf', 'utf8')]);
|
||||
|
||||
var iframe = 'iframe[src="' + Contacts.URL +
|
||||
'/contacts/views/vcard_load/vcard_load.html"]';
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(client.findElement(iframe), {'focus': true});
|
||||
client.helper.waitForElement(selectors.multipleSelectSave);
|
||||
|
||||
assert.ok(getListItems().length === 2); // vcard has one element
|
||||
});
|
||||
});
|
||||
|
||||
suite('webcontacts/contact activity', function() {
|
||||
|
||||
// Disabling these tests by now due to we need a way to switch to an
|
||||
// activity instead of switching to an app, due to paths can differ.
|
||||
// More info in [1].
|
||||
// These test must be recovered once this bug will be landed.
|
||||
|
||||
// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1140344#c9
|
||||
|
||||
test.skip('a contact with duplicate number shows merge page', function() {
|
||||
|
||||
subject.launch();
|
||||
|
||||
subject.addContact({
|
||||
givenName: 'From Contacts App',
|
||||
tel: 1111
|
||||
});
|
||||
|
||||
client.apps.close(Contacts.URL, 'contacts');
|
||||
|
||||
dialerSubject.launch();
|
||||
|
||||
// Dialer keys don't work in b2g desktop for some reason yet,
|
||||
// So just manually fire off the activity
|
||||
client.executeScript(function() {
|
||||
new MozActivity({
|
||||
name: 'new',
|
||||
data: {
|
||||
type: 'webcontacts/contact',
|
||||
params: {
|
||||
'tel': 1111
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
|
||||
subject.enterContactDetails({
|
||||
givenName: 'From Dialer Activity'
|
||||
});
|
||||
this.waitForFormTransition();
|
||||
|
||||
client.switchToFrame(client.findElement(selectors.duplicateFrame));
|
||||
|
||||
var duplicateHeader = client.helper.
|
||||
waitForElement(selectors.duplicateHeader);
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.matching_contacts.en-US.json',
|
||||
'duplicatesFoundTitle');
|
||||
|
||||
assert.equal(duplicateHeader.text(), expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
suite('webcontacts/tel activity', function() {
|
||||
// Disabling these tests by now due to we need a way to switch to an
|
||||
// activity instead of switching to an app, due to paths can differ.
|
||||
// More info in [1].
|
||||
// These test must be recovered once this bug will be landed.
|
||||
|
||||
// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1140344#c9
|
||||
test.skip('Error message when no contacts', function() {
|
||||
|
||||
smsSubject.launch();
|
||||
|
||||
// Launch the activity directly as mozSms has problems
|
||||
// in b2g desktop.
|
||||
client.executeScript(function() {
|
||||
new MozActivity({
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'webcontacts/tel'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
|
||||
var confirmMsg = client.findElement(selectors.confirmBody);
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.index.en-US.json',
|
||||
'noContactsActivity2');
|
||||
assert.equal(confirmMsg.text(), expectedResult);
|
||||
});
|
||||
|
||||
test.skip('Error message selected contact has no number', function() {
|
||||
|
||||
subject.launch();
|
||||
|
||||
subject.addContact({
|
||||
givenName: 'No Phone Number'
|
||||
});
|
||||
|
||||
client.apps.close(Contacts.URL, 'contacts');
|
||||
|
||||
smsSubject.launch();
|
||||
|
||||
client.executeScript(function() {
|
||||
new MozActivity({
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'webcontacts/tel'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
client.helper.waitForElement(selectors.bodyReady);
|
||||
|
||||
client.helper.waitForElement(selectors.listContactFirst)
|
||||
.click();
|
||||
|
||||
var confirmText = client.helper.waitForElement(selectors.confirmBody)
|
||||
.text();
|
||||
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.index.en-US.json',
|
||||
'no_contact_phones');
|
||||
assert.equal(confirmText, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
suite('webcontacts/email activity', function() {
|
||||
test('Creates only one instance of action menu', function() {
|
||||
subject.launch();
|
||||
|
||||
subject.addContactMultipleEmails({
|
||||
givenName: 'From Contacts App',
|
||||
emailFirst: 'first@personal.com',
|
||||
emailSecond: 'second@personal.com'
|
||||
});
|
||||
|
||||
client.apps.close(Contacts.URL, 'contacts');
|
||||
|
||||
smsSubject.launch();
|
||||
|
||||
client.executeScript(function() {
|
||||
new MozActivity({
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'webcontacts/email'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
client.helper.waitForElement(selectors.bodyReady);
|
||||
|
||||
var contact = client.helper.waitForElement(selectors.listContactFirst);
|
||||
|
||||
// Simulate two clicks
|
||||
contact.click();
|
||||
contact.click();
|
||||
|
||||
var emailList = client.helper.waitForElement(selectors.actionMenuList);
|
||||
var emailChildren = emailList.findElements('button');
|
||||
assert.equal(emailChildren.length, 3);
|
||||
});
|
||||
});
|
||||
});
|
||||
82
gaia/apps/communications/contacts/test/marionette/contacts_shortcuts_test.js
Executable file
82
gaia/apps/communications/contacts/test/marionette/contacts_shortcuts_test.js
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts shortcuts > touch', function() {
|
||||
var client = marionette.client({ profile: Contacts.config });
|
||||
var subject;
|
||||
var selectors;
|
||||
var actions;
|
||||
var scrollbar;
|
||||
var overlay;
|
||||
|
||||
function overlayOpacity() {
|
||||
return subject.getElementStyle(selectors.overlay, 'opacity');
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
|
||||
selectors = Contacts.Selectors;
|
||||
subject.addContact();
|
||||
scrollbar = client.helper.waitForElement(selectors.scrollbar);
|
||||
});
|
||||
|
||||
// Disabled bug 1023908
|
||||
suite('touch on shortcuts', function() {
|
||||
test('press/release on scrollbar should show/hide shortcut', function() {
|
||||
var action = actions.press(scrollbar, 10, 100).perform();
|
||||
overlay = client.helper.waitForElement(selectors.overlay);
|
||||
assert.equal(overlay.text().length, 1);
|
||||
assert.equal(overlayOpacity(), '1');
|
||||
action.release().perform();
|
||||
assert.equal(overlay.text().length, 0);
|
||||
assert.equal(overlayOpacity(), '0');
|
||||
});
|
||||
|
||||
// Disabled bug 1005708
|
||||
test.skip('shortcut text should change after moving some distance',
|
||||
function() {
|
||||
var letter, nextLetter, lastLetter;
|
||||
|
||||
var action = actions.press(scrollbar, 10, 100).perform();
|
||||
overlay = client.helper.waitForElement(selectors.overlay);
|
||||
letter = overlay.text();
|
||||
assert.equal(letter.length, 1);
|
||||
|
||||
action.moveByOffset(0, 1).perform();
|
||||
nextLetter = overlay.text();
|
||||
assert.equal(nextLetter.length, 1);
|
||||
assert.equal(letter, nextLetter);
|
||||
|
||||
action.moveByOffset(0, 50).perform();
|
||||
lastLetter = overlay.text();
|
||||
assert.equal(nextLetter.length, 1);
|
||||
assert.notEqual(lastLetter, nextLetter);
|
||||
|
||||
action.release().perform();
|
||||
});
|
||||
|
||||
test('pressing near the last release position should show valid shortcut',
|
||||
function() {
|
||||
actions.press(scrollbar, 15, 100).release().perform();
|
||||
|
||||
var action = actions.press(scrollbar, 15, 100).perform();
|
||||
overlay = client.helper.waitForElement(selectors.overlay);
|
||||
assert.equal(overlay.text().length, 1);
|
||||
action.release().perform();
|
||||
});
|
||||
|
||||
test('pressing outside the scrollbar should not show shortcut',
|
||||
function() {
|
||||
var action = actions.press(scrollbar, -1, 200).perform();
|
||||
|
||||
assert.notEqual(overlayOpacity(), '1');
|
||||
action.release().perform();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
window.wrappedJSObject.data = window.wrappedJSObject.data || {};
|
||||
|
||||
window.wrappedJSObject.data.fbContactData = {
|
||||
'uid': '100007887283166',
|
||||
'name': 'Jander Klander',
|
||||
'pic_big': 'https://fbcdn-profile-a.akamaihd.net/static-ak/' +
|
||||
'fbrsrc.php/v2/yL/r/HsTZSDw4avx.gif',
|
||||
'current_location': null,
|
||||
'email': [{
|
||||
'type': ['other'],
|
||||
'value': 'gtorodelvalle@hotmail.com'
|
||||
}],
|
||||
'profile_update_time': 1393974966,
|
||||
'work': [],
|
||||
'hometown_location': null,
|
||||
'_idxFriendsArray': 124,
|
||||
'familyName': ['Klander'],
|
||||
'additionalName': '',
|
||||
'givenName': ['Jander'],
|
||||
'tel': [{
|
||||
'type': ['other'],
|
||||
'value': '+34666666666'
|
||||
}],
|
||||
'email1': 'gtorodelvalle@hotmail.com',
|
||||
'contactPictureUri': 'https://graph.facebook.com/100007887283166/' +
|
||||
'picture?type=square&width=120&height=120',
|
||||
'search': 'JanderKlandergtorodelvalle@hotmail.com',
|
||||
'picwidth': 120,
|
||||
'picheight': 120,
|
||||
'_idx_': 0,
|
||||
'fbInfo': {
|
||||
'org': [''],
|
||||
'adr': [],
|
||||
'shortTelephone': ['666666666'],
|
||||
'url': [{
|
||||
'type': ['fb_profile_photo'],
|
||||
'value': 'https://fbcdn-profile-a.akamaihd.net/static-ak/' +
|
||||
'rsrc.php/v2/yL/r/HsTZSDw4avx.gif'
|
||||
}]
|
||||
}
|
||||
};
|
||||
19
gaia/apps/communications/contacts/test/marionette/data/vcard_21_multiple.vcf
Executable file
19
gaia/apps/communications/contacts/test/marionette/data/vcard_21_multiple.vcf
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
BEGIN:VCARD
|
||||
VERSION:2.1
|
||||
N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Gump;F=C3=B3rrest
|
||||
TEL;PREF;VOICE;WORK:(111) 555-1212
|
||||
ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
|
||||
LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, LA 30314=0D=0AUnited States of America
|
||||
EMAIL;PREF;INTERNET:forrestgump@example.com
|
||||
END:VCARD
|
||||
BEGIN:VCARD
|
||||
VERSION:2.1
|
||||
N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Gump2;F=C3=B3rrest2
|
||||
TEL;PREF;VOICE;WORK:(111) 555-1213
|
||||
TEL;HOME;VOICE:(404) 555-1213
|
||||
ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;100 W=C3=A1ters Edge;Baytown;LA;30314;United States of America
|
||||
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, LA 30314=0D=0AUnited States of America
|
||||
ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
|
||||
LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, LA 30314=0D=0AUnited States of America
|
||||
EMAIL;PREF;INTERNET:forrestgump@example2.com
|
||||
END:VCARD
|
||||
20
gaia/apps/communications/contacts/test/marionette/data/vcard_4.vcf
Executable file
20
gaia/apps/communications/contacts/test/marionette/data/vcard_4.vcf
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
BEGIN:VCARD
|
||||
VERSION:4.0
|
||||
N:Gump;Forrest;;;
|
||||
FN:Forrest Gump
|
||||
ORG:Bubba Gump Shrimp Co.
|
||||
TITLE:Shrimp Man
|
||||
PHOTO:data:image/bmp;base64,Qk02BAAAAAAAADYAAAAoAAAAEAAAAPD///8BACAAAAAAAAAAAABiBwAAYgcAAAAAAAAAAAAA///////////////////////////////////////////////////+///////////////////////////////////////////////////////////////////////V0s3/b21l/1pbVf9ydHL/u8HB//D09f/29vb///////////////////////////////////////Lx8P9ycWv/EhEO/wAAAP8AAgD/Gh0Z/15mav+tt7z/6+zr/////////////v////////////////////////+IiYf/AgYF/wAAAP8AAAD/AAAA/x8iI/88Ojv/e3l6///+/v/////////////////////////////////p5+f/am5z/xoeI/8iKDH/HSIr/ztATP+wtL//sbfC/zI4P//Ky8r///////////////////////7+/f/s7O3/vcDH/2Fkbf8+Qk7/foSW/5Wcsv+5vtP/7ezz//////97g5P/j5Oh//f4+P//////+/v7//Py8v/z8vP/9/j5/8jL2/8zNkD/MDM4/3Nydf/X0+H/0cvZ/7Srrv/Hvrz/h4uX/2Vsf/+5vcP/5OXj//Tz8//5+fn///////7+/v+eoa3/NjxE/2Vnaf9vbGr/pqSt/+ro8v+xqrP/6ePi/4SLnP85QE//e4SQ/5CWmv////////////z8+//X1tf/kZWc/09UXP9hY2f/TEhL/62twP/o6vP/n5ij/9LM0f+WnbX/PkRS/4CFkv99gor//f39//j39//19PP/+Pj3//////+ysrj/cnqP/21viv/c2On/9PL3//Hv+v/l5/T/x8jd/7Cvv//Y0NX/5NzD//X19f/7+/v///////Py9v/W3uf/z9Xa/4WFm/9UVGn/tK3D/+/o8v/Y0uD/9fL8/+3q9f/w7fn/+/n+///////////////////////08/b/2eLo/8XT2P9zdYb/XFxy/8S80//68vz/urTE/9XU5//j4+//9vX6////////////7e/u/+Dk5v/a4OT/8vf5///////g5+n/kZKe/25of/9sa3D/ZGNn/2pndf/ExdP/0tTf/+nm4//+/Pr//////87V2v+KmKf/cYOV/3mMn/+NnK3/TVll/1dYZP9kYHn/ODBG/yAcMP9fXW//ubzK/9PW3/9JREX/OTIu/7OxsP//////y9HZ/4WSov9xfo//TVhx/x8nNP8ZGiH/Y2F//3Bphv9vZYj/mZm3/7C1yv/Ey9n/DREX/wYIDf9ZaYb//v7+/8vS2v+Hk6T/h4+c/2hxg/8iJi//AwQE/0pHYP9nX4f/kIuv/4WIo/+GjaT/doOb/wECBv8dIS3/VWWL/w==
|
||||
TEL;TYPE=work,voice;VALUE=uri:tel:+1-111-555-1212
|
||||
TEL;TYPE=home,voice;VALUE=uri:tel:+1-404-555-1212
|
||||
ADR;TYPE=work;LABEL="100 Waters Edge
|
||||
Baytown,LA 30314
|
||||
United States of America"
|
||||
:;;100 Waters Edge;Baytown;LA;30314;United States of America
|
||||
ADR;TYPE=home;LABEL="42 Plantation St.
|
||||
Baytown,LA 30314
|
||||
United States of America"
|
||||
:;;42 Plantation St.;Baytown;LA;30314;United States of America
|
||||
EMAIL:forrestgump@example.com
|
||||
REV:20080424T195243Z
|
||||
END:VCARD
|
||||
109
gaia/apps/communications/contacts/test/marionette/delete_contacts_test.js
Executable file
109
gaia/apps/communications/contacts/test/marionette/delete_contacts_test.js
Executable file
|
|
@ -0,0 +1,109 @@
|
|||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
|
||||
marionette('Contacts > Delete', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var subject;
|
||||
var selectors;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
function goToSelectMode() {
|
||||
// Click on settings button and wait for slide up animation
|
||||
client.helper.waitForElement(selectors.settingsButton).click();
|
||||
var settings = client.helper.waitForElement(selectors.settingsView);
|
||||
subject.waitForSlideUp(settings);
|
||||
|
||||
// Click on delete button and wait for slide down animation
|
||||
client.helper.waitForElement(selectors.bulkDelete).click();
|
||||
subject.waitForSlideDown(settings);
|
||||
}
|
||||
|
||||
function isDisabled(selector) {
|
||||
return client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).disabled;
|
||||
}, [selector]);
|
||||
}
|
||||
|
||||
test(' > Edit menu is not visible on search mode', function() {
|
||||
subject.addContact({
|
||||
givenName: 'Hello',
|
||||
tel: 1231231234
|
||||
});
|
||||
|
||||
goToSelectMode();
|
||||
|
||||
var editForm = client.findElement(selectors.editForm);
|
||||
editForm.displayed(function onDisplayed() {
|
||||
// Enter in search mode
|
||||
client.helper.waitForElement(selectors.searchLabel).click();
|
||||
|
||||
// Wait until the select-all view goes away
|
||||
client.helper.waitForElementToDisappear(selectors.editMenu);
|
||||
});
|
||||
});
|
||||
|
||||
// Moztrap: https://moztrap.mozilla.org/manage/case/15181/
|
||||
test(' > All contacts', function() {
|
||||
subject.addContact({
|
||||
givenName: 'Contact 1'
|
||||
});
|
||||
subject.addContact({
|
||||
givenName: 'Contact 2'
|
||||
});
|
||||
|
||||
goToSelectMode();
|
||||
// Check that the action now is not available
|
||||
assert.ok(isDisabled(selectors.selectAction));
|
||||
// Click in select all
|
||||
client.helper.waitForElement(selectors.selectAllButton).click();
|
||||
// Click on delete
|
||||
client.helper.waitForElement(selectors.selectAction).click();
|
||||
// Click on the confirmation
|
||||
client.helper.waitForElement(selectors.confirmDelete).click();
|
||||
// Wait until the list appear and check it's empty
|
||||
client.helper.waitForElement(selectors.noContacts);
|
||||
|
||||
// Wait for the status saying we removed contacts
|
||||
var status = client.helper.waitForElement(selectors.multipleSelectStatus);
|
||||
subject.waitForSlideDown(status);
|
||||
|
||||
client.executeScript(function() {
|
||||
return !document.querySelector('#no-contacts').classList.contains('hide');
|
||||
});
|
||||
});
|
||||
|
||||
test('> Deleting last contact', function() {
|
||||
subject.addContact({
|
||||
givenName: 'Contact 1'
|
||||
});
|
||||
|
||||
// Go to deatils
|
||||
client.helper.waitForElement(selectors.listContactFirstText).click();
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
// Get to the form
|
||||
var edit = client.helper.waitForElement(selectors.detailsEditContact);
|
||||
subject.clickOn(edit);
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.form));
|
||||
|
||||
// Click on delete
|
||||
client.helper.waitForElement(selectors.deleteContact).click();
|
||||
client.helper.waitForElement(selectors.confirmDelete).click();
|
||||
|
||||
// Check the list has 0 contacts
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
assert.equal(subject.getNumberOfContacts(), 0);
|
||||
});
|
||||
|
||||
});
|
||||
116
gaia/apps/communications/contacts/test/marionette/details_test.js
Executable file
116
gaia/apps/communications/contacts/test/marionette/details_test.js
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var ContactsData = require('./lib/contacts_data');
|
||||
var assert = require('assert');
|
||||
var ContactsListView = require('./lib/views/contact-list/view');
|
||||
|
||||
marionette('Contacts > Details', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var subject, actions;
|
||||
var selectors;
|
||||
var contactsData = new ContactsData(client);
|
||||
var testContact;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
actions = client.loader.getActions();
|
||||
subject.actions = actions;
|
||||
subject.launch();
|
||||
|
||||
selectors = Contacts.Selectors;
|
||||
|
||||
testContact = {
|
||||
tel: [{value: '1231231234', type: ['home']}],
|
||||
givenName: ['Hello'],
|
||||
familyName: ['World'],
|
||||
name: ['Hello World'],
|
||||
email: [{value: 'hello@example.com', type: ['home']}],
|
||||
adr: [{type: ['home'], pref: true, streetAddress: 'False Street 123'}],
|
||||
org: ['Mozilla'],
|
||||
note: ['This is a note about the contact.']
|
||||
};
|
||||
});
|
||||
|
||||
function assertContactData(mozContact) {
|
||||
var telNode = client.helper.waitForElement(selectors.detailsTelButtonFirst);
|
||||
assert.equal(telNode.text(), mozContact.tel[0].value);
|
||||
|
||||
var nameNode = client.helper.waitForElement(selectors.detailsContactName);
|
||||
assert.equal(nameNode.text(), mozContact.name[0]);
|
||||
|
||||
var emailNode = client.helper.waitForElement(selectors.detailsEmail);
|
||||
assert.equal(emailNode.text(), mozContact.email[0].value);
|
||||
|
||||
var addressNode = client.helper.waitForElement(selectors.detailsAddress);
|
||||
assert.equal(addressNode.text(), mozContact.adr[0].streetAddress);
|
||||
|
||||
var orgNode = client.helper.waitForElement(selectors.detailsOrg);
|
||||
assert.equal(orgNode.text(), mozContact.org[0]);
|
||||
|
||||
var noteNode = client.helper.waitForElement(selectors.detailsNote);
|
||||
assert.equal(noteNode.text(), mozContact.note[0]);
|
||||
}
|
||||
|
||||
test('Regular contact is displayed correctly', function() {
|
||||
contactsData.createMozContact(testContact);
|
||||
client.helper.waitForElement(selectors.listContactFirstText).click();
|
||||
subject.waitSlideLeft('details');
|
||||
assertContactData(testContact);
|
||||
});
|
||||
|
||||
test('Show contact with picture', function() {
|
||||
contactsData.createMozContact(testContact, true);
|
||||
client.helper.waitForElement(selectors.listContactFirstText).click();
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
assertContactData(testContact);
|
||||
|
||||
var coverImg = client.helper.waitForElement(selectors.detailsCoverImage);
|
||||
assert.ok(coverImg, 'Element should exist.');
|
||||
client.waitFor(function() {
|
||||
return coverImg.getAttribute('style').indexOf('background-image') != -1;
|
||||
});
|
||||
});
|
||||
|
||||
test('Share Contact', function() {
|
||||
contactsData.createMozContact(testContact);
|
||||
|
||||
client.helper.waitForElement(selectors.listContactFirstText).click();
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
// Click on share button
|
||||
client.helper.waitForElement(selectors.detailsShareButton).click();
|
||||
|
||||
var sysMenu = subject.systemMenu;
|
||||
|
||||
// In the sysMenu they should appear at least the Messages and email apps
|
||||
var menuOptions = sysMenu.findElements('button');
|
||||
assert.ok(menuOptions.length >= 2);
|
||||
});
|
||||
|
||||
suite('Favorite contact', function() {
|
||||
setup(function(){
|
||||
contactsData.createMozContact(testContact);
|
||||
});
|
||||
test('Mark contact as favorite', function() {
|
||||
var contactsListView = new ContactsListView(client);
|
||||
var contactDetailsView = contactsListView.goToContact();
|
||||
contactDetailsView.makeFavorited();
|
||||
assertContactData(testContact);
|
||||
});
|
||||
|
||||
test('Favorite contact should appear in' +
|
||||
' favorite and regular lists', function() {
|
||||
var contactsListView = new ContactsListView(client);
|
||||
var contactDetailsView = contactsListView.goToContact();
|
||||
contactDetailsView.makeFavorited();
|
||||
contactsListView = contactDetailsView.backtoContactsList();
|
||||
assert.ok(contactsListView.firstContact.displayed());
|
||||
assert.ok(contactsListView.firstFavorite.displayed());
|
||||
});
|
||||
});
|
||||
});
|
||||
65
gaia/apps/communications/contacts/test/marionette/export_sdcard_test.js
Executable file
65
gaia/apps/communications/contacts/test/marionette/export_sdcard_test.js
Executable file
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
marionette('Export to SDCARD', function() {
|
||||
var profile = Contacts.config;
|
||||
// Enable device storage
|
||||
var prefs = ['device.storage.enabled',
|
||||
'device.storage.testing',
|
||||
'device.storage.prompt.testing'];
|
||||
prefs.forEach(pref => {
|
||||
profile[pref] = true;
|
||||
});
|
||||
var client = marionette.client({
|
||||
profile: profile,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var actions, subject, selectors;
|
||||
|
||||
setup(function() {
|
||||
// Remove all files in temp device storage.
|
||||
client.fileManager.removeAllFiles();
|
||||
|
||||
subject = new Contacts(client);
|
||||
actions = client.loader.getActions();
|
||||
subject.actions = actions;
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
test('> export one contact', function() {
|
||||
// Create a contact first
|
||||
subject.addContact({
|
||||
givenName: 'John',
|
||||
tel: 1231231234
|
||||
});
|
||||
|
||||
// Go to settings
|
||||
client.helper.waitForElement(selectors.settingsButton).click();
|
||||
|
||||
// Now click on import contacts button
|
||||
client.helper.waitForElement(selectors.exportButton).click();
|
||||
client.helper.waitForElement(selectors.exportSDCard).click();
|
||||
|
||||
// Select all and export
|
||||
client.helper.waitForElement(selectors.selectAllButton).click();
|
||||
client.helper.waitForElement(selectors.selectAction).click();
|
||||
|
||||
// Check the string on the status
|
||||
var status = client.helper.waitForElement(selectors.multipleSelectStatus);
|
||||
assert.equal('1/1 contacts exported', status.text());
|
||||
|
||||
// Check we have a file in the sdcard
|
||||
var path = client.fileManager.deviceStorage.getDeviceStoragePath();
|
||||
console.log('path is ' + path);
|
||||
assert.ok(fs.existsSync(path));
|
||||
|
||||
var files = fs.readdirSync(path);
|
||||
assert.equal(files.length, 1);
|
||||
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
});
|
||||
});
|
||||
390
gaia/apps/communications/contacts/test/marionette/form_test.js
Executable file
390
gaia/apps/communications/contacts/test/marionette/form_test.js
Executable file
|
|
@ -0,0 +1,390 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts'),
|
||||
ContactsData = require('./lib/contacts_data'),
|
||||
Dialer = require('../../../dialer/test/marionette/lib/dialer'),
|
||||
assert = require('assert'),
|
||||
/*jshint -W079 */
|
||||
System = require('../../../../system/test/marionette/lib/system');
|
||||
|
||||
// XXX Bug 1139799 - Enable test for Bug 1116889
|
||||
// Gallery = require('../../../../gallery/test/marionette/lib/gallery');
|
||||
|
||||
marionette('Contacts > Form', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
}),
|
||||
subject,
|
||||
contactsData,
|
||||
dialerSubject,
|
||||
dialerSelectors,
|
||||
selectors,
|
||||
system;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
contactsData = new ContactsData(client);
|
||||
selectors = Contacts.Selectors;
|
||||
dialerSubject = new Dialer(client);
|
||||
dialerSelectors = Dialer.Selectors;
|
||||
subject.launch();
|
||||
system = new System(client);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject = null;
|
||||
contactsData = null;
|
||||
selectors = null;
|
||||
dialerSubject = null;
|
||||
dialerSelectors = null;
|
||||
system = null;
|
||||
});
|
||||
|
||||
var contactData = {
|
||||
givenName: ['Jose'],
|
||||
familyName: ['Cantera'],
|
||||
org: ['EDM'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '637654321'
|
||||
}]
|
||||
};
|
||||
|
||||
function editFirstContact() {
|
||||
var firstContact = client.helper.waitForElement(selectors.listContactFirst);
|
||||
subject.clickOn(firstContact);
|
||||
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
var edit = client.helper.waitForElement(selectors.detailsEditContact);
|
||||
subject.clickOn(edit);
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.form));
|
||||
}
|
||||
|
||||
function editContactPhoto() {
|
||||
editFirstContact();
|
||||
|
||||
var photoChangeButton = client.helper.waitForElement(
|
||||
selectors.formPhotoButton);
|
||||
subject.clickOn(photoChangeButton);
|
||||
}
|
||||
|
||||
suite('> Add Contact', function() {
|
||||
test('Add a simple contact', function() {
|
||||
var givenName = 'Hello';
|
||||
var familyName = 'World';
|
||||
|
||||
subject.addContact({
|
||||
givenName: givenName,
|
||||
familyName: familyName
|
||||
});
|
||||
|
||||
var listView = client.helper.waitForElement(selectors.list);
|
||||
assert.ok(listView.displayed(), 'List view is shown.');
|
||||
|
||||
var listElementText = client.helper.waitForElement(
|
||||
selectors.listContactFirst).text();
|
||||
|
||||
assert.notEqual(listElementText.indexOf(givenName), -1);
|
||||
assert.notEqual(listElementText.indexOf(familyName), -1);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> Edit Contact', function() {
|
||||
test('Simple edition of contact details. ORG field', function() {
|
||||
contactsData.createMozContact(contactData);
|
||||
|
||||
editFirstContact();
|
||||
|
||||
client.helper.waitForElement(selectors.formOrg).sendKeys('v2');
|
||||
client.helper.waitForElement(selectors.formSave).click();
|
||||
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.details));
|
||||
var edit = client.helper.waitForElement(selectors.detailsEditContact);
|
||||
subject.clickOn(edit);
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.form));
|
||||
|
||||
var orgField = client.helper.waitForElement(selectors.formOrg);
|
||||
var orgFieldValue = orgField.getAttribute('value');
|
||||
|
||||
assert.ok(orgFieldValue.trim() === 'v2EDM');
|
||||
});
|
||||
|
||||
test('Can create custom label', function() {
|
||||
contactsData.createMozContact(contactData);
|
||||
editFirstContact();
|
||||
|
||||
client.helper.waitForElement(selectors.formTelLabelFirst).click();
|
||||
subject.waitSlideLeft('formCustomTagPage');
|
||||
|
||||
client.helper.waitForElement(selectors.formCustomTag).sendKeys('BFF');
|
||||
client.helper.waitForElement(selectors.formCustomTagDone).click();
|
||||
|
||||
// Wait for the custom tag page to disappear
|
||||
var bodyWidth = client.findElement(selectors.body).size().width;
|
||||
client.waitFor(function waiting() {
|
||||
var tagPage = client.findElement(selectors.formCustomTagPage);
|
||||
var location = tagPage.location();
|
||||
return location.x >= bodyWidth;
|
||||
});
|
||||
|
||||
client.findElement(selectors.formSave).click();
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.details));
|
||||
|
||||
client.helper.waitForElement(selectors.detailsTelLabelFirst);
|
||||
client.waitFor(function waiting() {
|
||||
var label = client.helper.
|
||||
waitForElement(selectors.detailsTelLabelFirst);
|
||||
return label.text() === 'BFF';
|
||||
});
|
||||
assert.ok(true, 'custom label is updated.');
|
||||
});
|
||||
|
||||
suite('> Edit Contact Photo', function() {
|
||||
setup(function() {
|
||||
// We create a mozContact with a photo
|
||||
contactsData.createMozContact(contactData, true);
|
||||
});
|
||||
|
||||
function areRemoveAndChangePresent() {
|
||||
return client.executeScript(function(selector) {
|
||||
var buttons = document.querySelectorAll(selector);
|
||||
var out = 0;
|
||||
for(var j = 0; j < buttons.length; j++) {
|
||||
if (buttons[j].textContent === 'Remove photo') {
|
||||
out++;
|
||||
}
|
||||
if (buttons[j].textContent === 'Change photo') {
|
||||
out++;
|
||||
}
|
||||
}
|
||||
return out === 2;
|
||||
}, ['#value-menu button']);
|
||||
}
|
||||
|
||||
test('Edit regular Contact with image', function() {
|
||||
editContactPhoto();
|
||||
|
||||
client.helper.waitForElement(selectors.actionMenu);
|
||||
|
||||
assert.ok(areRemoveAndChangePresent());
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('> Adding and removing', function() {
|
||||
test('Template ids unique', function() {
|
||||
var data = {
|
||||
givenName: ['John'],
|
||||
familyName: ['Doe'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '1111111'
|
||||
}, {
|
||||
type: ['mobile'],
|
||||
value: '222222'
|
||||
}]
|
||||
};
|
||||
|
||||
contactsData.createMozContact(data);
|
||||
editFirstContact();
|
||||
|
||||
// Delete the first phone and click on add a new phone
|
||||
client.helper.waitForElement(selectors.formDelFirstTel).click();
|
||||
client.helper.waitForElement(selectors.formAddNewTel).click();
|
||||
client.helper.waitForElement(selectors.formSave).click();
|
||||
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.details));
|
||||
|
||||
var phoneList = client.findElements(selectors.formTel);
|
||||
assert.equal(phoneList.length, 2);
|
||||
assert.equal(phoneList[1].getAttribute('id'), 'number_2');
|
||||
});
|
||||
});
|
||||
|
||||
/* XXX Bug 1139799 - Enable test for Bug 1116889
|
||||
suite('> Discard edited contact photo', function() {
|
||||
setup(function() {
|
||||
// Create a contact without photo
|
||||
contactsData.createMozContact(contactData, false);
|
||||
|
||||
client.switchToFrame();
|
||||
|
||||
// This test makes use of gallery images, so we need to populate
|
||||
// the pictures folder with test images and launch the gallery app
|
||||
// to make sure that it scans the images properly.
|
||||
client.fileManager.add({
|
||||
type: 'pictures',
|
||||
filePath: 'test_media/Pictures/firefoxOS.png'
|
||||
});
|
||||
|
||||
var gallery = new Gallery(client);
|
||||
gallery.launch();
|
||||
client.apps.close(Gallery.ORIGIN);
|
||||
|
||||
client.switchToFrame();
|
||||
subject.launch();
|
||||
});
|
||||
|
||||
test('Select photo and discard it', function() {
|
||||
// Select first contact and click on the edit button.
|
||||
editFirstContact();
|
||||
|
||||
// Check that we have no photo for this contact.
|
||||
var photoBeforeEdit =
|
||||
client.helper.waitForElement(selectors.formPhotoImg);
|
||||
assert.ok(photoBeforeEdit.getAttribute('style') === '');
|
||||
|
||||
// Click on the photo button to edit it. This triggers an activity
|
||||
// selection menu.
|
||||
var photoChangeButton =
|
||||
client.helper.waitForElement(selectors.formPhotoButton);
|
||||
subject.clickOn(photoChangeButton);
|
||||
|
||||
// Switch to system frame.
|
||||
client.switchToFrame();
|
||||
|
||||
// Select gallery option on activity selector.
|
||||
var gallery = system.getActivityOptionMatching('gallery');
|
||||
subject.clickOn(gallery);
|
||||
|
||||
// Choose an image.
|
||||
client.apps.switchToApp('app://gallery.gaiamobile.org');
|
||||
var thumbnail = client.helper.waitForElement(selectors.galleryImage);
|
||||
subject.clickOn(thumbnail);
|
||||
var done =
|
||||
client.helper.waitForElement(selectors.galleryDone);
|
||||
subject.clickOn(done);
|
||||
|
||||
// Get back to contacts app.
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
|
||||
// Discard changes.
|
||||
var formHeader =
|
||||
client.helper.waitForElement(selectors.formHeader);
|
||||
formHeader.tap(10, 10);
|
||||
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
// Edit again.
|
||||
var edit =
|
||||
client.helper.waitForElement(selectors.detailsEditContact);
|
||||
subject.clickOn(edit);
|
||||
client.helper.waitForElement(selectors.form);
|
||||
|
||||
// Check that we have no photo after discarding the selection.
|
||||
var photoAfterEdit =
|
||||
client.helper.waitForElement(selectors.formPhotoImg);
|
||||
assert.ok(photoAfterEdit.getAttribute('style') === '');
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
suite('> Facebook contacts', function() {
|
||||
var fbContactData;
|
||||
|
||||
setup(function() {
|
||||
fbContactData = contactsData.createFbContact();
|
||||
});
|
||||
|
||||
function isGalleryButtonPresent() {
|
||||
return client.executeScript(function(selector) {
|
||||
var buttons = document.querySelectorAll(selector);
|
||||
var out = false;
|
||||
for(var j = 0; j < buttons.length; j++) {
|
||||
if (buttons[j].textContent === 'Gallery') {
|
||||
out = true;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}, [selectors.buttonActivityChooser]);
|
||||
}
|
||||
|
||||
test('Add phone number from Dialer to existing Facebook contact',
|
||||
function() {
|
||||
client.apps.close(Contacts.URL, 'contacts');
|
||||
|
||||
dialerSubject.launch();
|
||||
|
||||
var one = client.findElement(dialerSelectors.one),
|
||||
two = client.findElement(dialerSelectors.two),
|
||||
three = client.findElement(dialerSelectors.three);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
one.tap();
|
||||
two.tap();
|
||||
three.tap();
|
||||
}
|
||||
var phoneNumber = dialerSubject.client.findElement(
|
||||
dialerSelectors.phoneNumber);
|
||||
client.waitFor(function() {
|
||||
return (phoneNumber.getAttribute('value').length === 9);
|
||||
});
|
||||
|
||||
var addContact = dialerSubject.client.findElement(
|
||||
dialerSelectors.keypadCallBarAddContact);
|
||||
addContact.tap();
|
||||
|
||||
var addToExistingContact = dialerSubject.client.helper.waitForElement(
|
||||
dialerSelectors.addToExistingContactMenuItem);
|
||||
addToExistingContact.tap();
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
|
||||
client.findElement(selectors.listContactFirst).tap();
|
||||
|
||||
subject.waitForFormShown();
|
||||
|
||||
var formTelNumberSecond = client.helper.waitForElement(
|
||||
selectors.formTelNumberSecond);
|
||||
var formEmailFirst = client.helper.waitForElement(
|
||||
selectors.formEmailFirst);
|
||||
|
||||
assert.equal(formTelNumberSecond.getAttribute('value'),
|
||||
fbContactData.tel[0].value);
|
||||
assert.equal(formEmailFirst.getAttribute('value'),
|
||||
fbContactData.email[0].value);
|
||||
});
|
||||
|
||||
test('Contact Photo cannot be removed', function() {
|
||||
editContactPhoto();
|
||||
|
||||
// As it is a Facebook contact it should appear the activity window
|
||||
// to choose the source for the image
|
||||
client.switchToFrame();
|
||||
client.helper.waitForElement(selectors.activityChooser);
|
||||
|
||||
assert.ok(isGalleryButtonPresent());
|
||||
});
|
||||
}); // Facebook Contacts
|
||||
|
||||
suite('> Input buttons', function() {
|
||||
function assertClear(inputSelector) {
|
||||
var input = client.helper.waitForElement(inputSelector);
|
||||
input.tap();
|
||||
input.sendKeys('1234');
|
||||
client.findElement(inputSelector + ' + button[type="reset"]').tap();
|
||||
assert.strictEqual(input.getAttribute('value'), '');
|
||||
}
|
||||
|
||||
test('Clear buttons work as expected', function() {
|
||||
contactsData.createMozContact(contactData);
|
||||
editFirstContact();
|
||||
|
||||
var fieldSelectors = [
|
||||
selectors.formGivenName,
|
||||
selectors.formTelNumberFirst,
|
||||
selectors.formFamilyName,
|
||||
selectors.formOrg,
|
||||
selectors.formEmailFirst
|
||||
];
|
||||
|
||||
for (var i = 0, len = fieldSelectors.length; i < len; i++){
|
||||
assertClear(fieldSelectors[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
563
gaia/apps/communications/contacts/test/marionette/ice_test.js
Executable file
563
gaia/apps/communications/contacts/test/marionette/ice_test.js
Executable file
|
|
@ -0,0 +1,563 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var ContactsData = require('./lib/contacts_data');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts > ICE contacts', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var contactsData = new ContactsData(client);
|
||||
var actions, subject, selectors;
|
||||
|
||||
var testContactTelNumber = '655555555';
|
||||
|
||||
var testContact = {
|
||||
givenName: ['Hello'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: testContactTelNumber
|
||||
}]
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
actions = client.loader.getActions();
|
||||
subject.actions = actions;
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
function setFirstContactAsICE() {
|
||||
openICESettings();
|
||||
clickICESwitch(1);
|
||||
|
||||
var listContactFirstText =
|
||||
client.helper.waitForElement(selectors.listContactFirstText);
|
||||
subject.clickOn(listContactFirstText);
|
||||
}
|
||||
|
||||
function clickICESwitch(switchNumber){
|
||||
var iceSwitch =
|
||||
client.helper.waitForElement(selectors['iceSwitch' + switchNumber]);
|
||||
subject.clickOn(iceSwitch);
|
||||
|
||||
var iceButton =
|
||||
client.helper.waitForElement(selectors['iceButton' + switchNumber]);
|
||||
subject.clickOn(iceButton);
|
||||
}
|
||||
|
||||
function openICESettings() {
|
||||
var settingsBtn = client.helper.waitForElement(selectors.settingsButton);
|
||||
subject.clickOn(settingsBtn);
|
||||
|
||||
var settings = client.helper.waitForElement(selectors.settingsView);
|
||||
subject.waitForFadeIn(settings);
|
||||
|
||||
client.helper.waitForElement(selectors.setIceButton).click();
|
||||
}
|
||||
|
||||
function addTestContact(addTelephone) {
|
||||
var tel = addTelephone ? testContactTelNumber : undefined;
|
||||
subject.addContact({
|
||||
givenName: 'Hello',
|
||||
tel: tel
|
||||
});
|
||||
}
|
||||
|
||||
function clickBackArrow() {
|
||||
var contactsHeader =
|
||||
client.helper.waitForElement(selectors.iceSettingsHeader);
|
||||
|
||||
actions.wait(0.5).tap(contactsHeader, 10, 10).perform();
|
||||
}
|
||||
|
||||
function isIceContactsGroupHidden() {
|
||||
return client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).classList.contains('hide');
|
||||
}, [selectors.iceGroupOpen]);
|
||||
}
|
||||
|
||||
function assertICEContact(position, name) {
|
||||
var iceContact = client.helper.waitForElement(
|
||||
selectors['iceButton' + position]);
|
||||
assert.equal(iceContact.text(), name);
|
||||
|
||||
var checked = client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).checked;
|
||||
}, [selectors['iceInputSwitch' + position]]);
|
||||
assert.ok(checked);
|
||||
}
|
||||
|
||||
function assertICEContactNotSet(position) {
|
||||
var checked = client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).checked;
|
||||
}, [selectors['iceInputSwitch' + position]]);
|
||||
|
||||
assert.ok(!checked);
|
||||
}
|
||||
|
||||
// Creates a mozContact by calling the mozContacts API
|
||||
function createMozContact(contactData) {
|
||||
return contactsData.createMozContact(contactData);
|
||||
}
|
||||
|
||||
function setICEContacts(iceContactsList) {
|
||||
var doSetICEContacts = function(iceContactsList) {
|
||||
var LazyLoader = window.wrappedJSObject.LazyLoader;
|
||||
|
||||
LazyLoader.load([
|
||||
'/shared/js/contacts/utilities/ice_store.js',
|
||||
'/contacts/js/utilities/ice_data.js',
|
||||
'/shared/js/async_storage.js'
|
||||
], function() {
|
||||
var ICEData = window.wrappedJSObject.ICEData;
|
||||
ICEData.setICEContacts(iceContactsList).then(function() {
|
||||
marionetteScriptFinished(true);
|
||||
}, function(error) {
|
||||
console.error('Error while setting ICE ', error);
|
||||
marionetteScriptFinished(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var iceContactsSet = false;
|
||||
client.executeAsyncScript(doSetICEContacts, [iceContactsList],
|
||||
function(err, val) {
|
||||
iceContactsSet = val;
|
||||
});
|
||||
|
||||
client.waitFor(function() {
|
||||
return iceContactsSet;
|
||||
});
|
||||
}
|
||||
|
||||
function setICEContact(position, contact) {
|
||||
var contactId = createMozContact(contact || testContact);
|
||||
var iceContacts = [null, null];
|
||||
iceContacts[position - 1] = contactId;
|
||||
|
||||
setICEContacts(iceContacts);
|
||||
}
|
||||
|
||||
function createAndSetICEContacts(contactList) {
|
||||
var iceList = [];
|
||||
contactList.forEach(function(aContact) {
|
||||
var contactId = createMozContact(aContact);
|
||||
iceList.push(contactId);
|
||||
});
|
||||
|
||||
setICEContacts(iceList);
|
||||
}
|
||||
|
||||
suite('ICE settings', function() {
|
||||
test('Check ICE settings transition', function() {
|
||||
addTestContact();
|
||||
openICESettings();
|
||||
clickICESwitch(1);
|
||||
clickBackArrow();
|
||||
clickICESwitch(2);
|
||||
clickBackArrow();
|
||||
});
|
||||
|
||||
test('Clicking on ICE button does not toggle the switch', function() {
|
||||
addTestContact();
|
||||
openICESettings();
|
||||
|
||||
var iceButton1 = client.helper.waitForElement(selectors.iceButton1);
|
||||
subject.clickOn(iceButton1);
|
||||
|
||||
var checked = client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).checked;
|
||||
}, [selectors.iceInputSwitch1]);
|
||||
|
||||
assert.ok(!checked);
|
||||
});
|
||||
|
||||
test('Select ICE contact from search, go back to ICE settings', function() {
|
||||
addTestContact(true);
|
||||
openICESettings();
|
||||
clickICESwitch(1);
|
||||
|
||||
var searchLabel = client.helper.waitForElement(selectors.searchLabel);
|
||||
subject.clickOn(searchLabel);
|
||||
|
||||
// We search for the first letter of givenName in addTestContact()
|
||||
client.helper.waitForElement(selectors.searchInput).sendKeys('H');
|
||||
client.helper.waitForElement(selectors.searchResultFirst).click();
|
||||
|
||||
clickBackArrow();
|
||||
|
||||
var settingsClose = client.helper.waitForElement(selectors.settingsClose);
|
||||
subject.clickOn(settingsClose);
|
||||
|
||||
var openIce = client.helper.waitForElement(selectors.iceGroupOpen);
|
||||
subject.clickOn(openIce);
|
||||
|
||||
var iceContact = client.helper.waitForElement(selectors.iceContact);
|
||||
// 'Hello' is givenName in addTestContact()
|
||||
assert.ok(iceContact.text().indexOf('Hello') >= 0,
|
||||
'The name of the contact should appear as ICE contact');
|
||||
});
|
||||
|
||||
|
||||
test('ICE contacts can\'t be repeated', function() {
|
||||
addTestContact(true);
|
||||
setFirstContactAsICE();
|
||||
clickICESwitch(2);
|
||||
|
||||
var listContactFirstText =
|
||||
client.helper.waitForElement(selectors.listContactFirstText);
|
||||
|
||||
subject.clickOn(listContactFirstText);
|
||||
|
||||
var confirmText = client.helper.waitForElement(selectors.confirmBody)
|
||||
.text();
|
||||
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.index.en-US.json',
|
||||
'ICERepeatedContact');
|
||||
assert.equal(confirmText, expectedResult);
|
||||
});
|
||||
|
||||
test('Contact must have a phone number', function() {
|
||||
addTestContact(false); // Added contact without phone
|
||||
setFirstContactAsICE();
|
||||
|
||||
var confirmText = client.helper.waitForElement(selectors.confirmBody)
|
||||
.text();
|
||||
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.index.en-US.json',
|
||||
'ICEContactNoNumber');
|
||||
|
||||
assert.equal(confirmText, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ICE contacts edition', function() {
|
||||
function dismissAndGoBack() {
|
||||
client.helper.waitForElement(selectors.confirmDismiss).click();
|
||||
|
||||
var header = client.helper.waitForElement(selectors.detailsHeader);
|
||||
actions.wait(0.5).tap(header, 10, 10).perform();
|
||||
}
|
||||
|
||||
function deleteFirstContactFirstTel() {
|
||||
var firstContact =
|
||||
client.helper.waitForElement(selectors.listContactFirst);
|
||||
subject.clickOn(firstContact);
|
||||
|
||||
var edit = client.helper.waitForElement(selectors.detailsEditContact);
|
||||
subject.clickOn(edit);
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.form));
|
||||
client.findElement(selectors.formDelFirstTel).click();
|
||||
|
||||
var save = client.findElement(selectors.formSave);
|
||||
save.enabled();
|
||||
save.click();
|
||||
}
|
||||
|
||||
function closeSettings() {
|
||||
var close = client.helper.waitForElement(selectors.settingsClose);
|
||||
subject.clickOn(close);
|
||||
}
|
||||
|
||||
suite('With one phone number', function() {
|
||||
setup(function() {
|
||||
addTestContact(true);
|
||||
setFirstContactAsICE();
|
||||
clickBackArrow();
|
||||
closeSettings();
|
||||
deleteFirstContactFirstTel();
|
||||
});
|
||||
|
||||
test('Confirm window appears with correct message', function() {
|
||||
var confirmBody = client.helper.waitForElement(selectors.confirmBody);
|
||||
|
||||
var expectedResult = subject.l10n(
|
||||
'/locales-obj/contacts.index.en-US.json',
|
||||
'ICEContactDelTelAll');
|
||||
|
||||
assert.equal(confirmBody.text(), expectedResult);
|
||||
});
|
||||
|
||||
test('Contact is deleted from ICE when no numbers left', function() {
|
||||
dismissAndGoBack();
|
||||
openICESettings();
|
||||
var iceButton1 = client.helper.waitForElement(selectors.iceButton1);
|
||||
assert.ok(!iceButton1.enabled());
|
||||
});
|
||||
|
||||
test('ICE list empty after removing phone', function() {
|
||||
dismissAndGoBack();
|
||||
client.helper.waitForElement(selectors.contactListHeader);
|
||||
assert.ok(isIceContactsGroupHidden());
|
||||
});
|
||||
});
|
||||
|
||||
suite('With more than one phone number', function() {
|
||||
test('Deleting the first number keeps the contact as ICE', function() {
|
||||
var mozContact = {
|
||||
tel: [
|
||||
{
|
||||
value: '01234',
|
||||
type: ['home']
|
||||
},
|
||||
{
|
||||
value: '56789',
|
||||
type:['home']
|
||||
}
|
||||
],
|
||||
givenName: ['Hello'],
|
||||
familyName: ['World'],
|
||||
name: ['Hello World']
|
||||
};
|
||||
createMozContact(mozContact);
|
||||
setFirstContactAsICE();
|
||||
clickBackArrow();
|
||||
closeSettings();
|
||||
deleteFirstContactFirstTel();
|
||||
dismissAndGoBack();
|
||||
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
openICESettings();
|
||||
assertICEContact(1, mozContact.name[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('ICE contacts and Merge', function() {
|
||||
// Merges a duplicate contact and closes the duplicates iframe
|
||||
function mergeDuplicate() {
|
||||
var duplicateFrame = client.findElement(selectors.duplicateFrame);
|
||||
subject.waitForSlideUp(duplicateFrame);
|
||||
client.switchToFrame(duplicateFrame);
|
||||
var mergeAction = client.helper.waitForElement(selectors.duplicateMerge);
|
||||
subject.clickOn(mergeAction);
|
||||
|
||||
client.switchToFrame();
|
||||
client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
subject.waitForSlideDown(duplicateFrame);
|
||||
}
|
||||
|
||||
function setTwoICEDuplicates() {
|
||||
var duplicateContact = testContact;
|
||||
|
||||
var contactId1 = createMozContact(duplicateContact);
|
||||
var contactId2 = createMozContact(duplicateContact);
|
||||
|
||||
setICEContacts([contactId1, contactId2]);
|
||||
}
|
||||
|
||||
function addNewAndMatchTest(position) {
|
||||
addTestContact(true);
|
||||
|
||||
mergeDuplicate();
|
||||
|
||||
// Now we go back to the ICE settings and check that our ICE remains
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
openICESettings();
|
||||
assertICEContact(position, 'Hello');
|
||||
}
|
||||
|
||||
function findDuplicatesAndMatchTest(position) {
|
||||
var secondContactID = createMozContact({
|
||||
givenName: ['Hello'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: testContactTelNumber
|
||||
}]
|
||||
});
|
||||
|
||||
var selectorForSecondContact = 'li[data-uuid="' + secondContactID + '"]';
|
||||
|
||||
// Going to the recently created contact
|
||||
var listContactElement =
|
||||
client.helper.waitForElement(selectorForSecondContact);
|
||||
subject.clickOn(listContactElement);
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
var findDups = client.helper.waitForElement(selectors.findDupsButton);
|
||||
subject.clickOn(findDups);
|
||||
|
||||
mergeDuplicate();
|
||||
|
||||
subject.backToList();
|
||||
|
||||
openICESettings();
|
||||
assertICEContact(position, 'Hello');
|
||||
}
|
||||
|
||||
function editAndMatchTest(position) {
|
||||
subject.addContact({
|
||||
givenName: 'Good Bye',
|
||||
tel: '+34638883074'
|
||||
});
|
||||
|
||||
var selectorForSecondContact = 'li[data-group="G"].contact-item';
|
||||
|
||||
// Going to the recently created contact
|
||||
var listContactElement =
|
||||
client.helper.waitForElement(selectorForSecondContact);
|
||||
subject.clickOn(listContactElement);
|
||||
|
||||
// Editing contact
|
||||
subject.editContact();
|
||||
// Adding a tel number equal to the tel number of 'Hello'
|
||||
client.findElement(selectors.formAddNewTel).click();
|
||||
client.helper.waitForElement(selectors.formTelNumberSecond).
|
||||
sendKeys(testContactTelNumber);
|
||||
// Saving the contact
|
||||
var save = client.findElement(selectors.formSave);
|
||||
save.enabled();
|
||||
save.click();
|
||||
|
||||
mergeDuplicate();
|
||||
|
||||
subject.backToList();
|
||||
|
||||
openICESettings();
|
||||
assertICEContact(position, 'Good Bye');
|
||||
}
|
||||
|
||||
suite('> 1 ICE Contact. Position 1', function() {
|
||||
setup(function() {
|
||||
setICEContact(1);
|
||||
});
|
||||
|
||||
test('> Add a new Contact that matches ICE Contact', function() {
|
||||
addNewAndMatchTest(1);
|
||||
assertICEContactNotSet(2);
|
||||
});
|
||||
|
||||
test('> Find duplicates. ICE Contact Matches', function() {
|
||||
findDuplicatesAndMatchTest(1);
|
||||
assertICEContactNotSet(2);
|
||||
});
|
||||
|
||||
test('> Edit existing, change data. ICE Matches. ICE changed',
|
||||
function() {
|
||||
editAndMatchTest(1);
|
||||
assertICEContactNotSet(2);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> 1 ICE Contact. Position 2', function() {
|
||||
setup(function() {
|
||||
setICEContact(2);
|
||||
});
|
||||
|
||||
test('> Add a new Contact that matches ICE Contact', function() {
|
||||
addNewAndMatchTest(2);
|
||||
assertICEContactNotSet(1);
|
||||
});
|
||||
|
||||
test('> Find duplicates. ICE Contact Matches', function() {
|
||||
findDuplicatesAndMatchTest(2);
|
||||
assertICEContactNotSet(1);
|
||||
});
|
||||
|
||||
test('> Edit existing, change data. ICE Matches. ICE changed',
|
||||
function() {
|
||||
editAndMatchTest(2);
|
||||
assertICEContactNotSet(1);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> 2 ICE Contacts. Change position 1. Keep Position 2', function() {
|
||||
setup(function() {
|
||||
createAndSetICEContacts([testContact, {
|
||||
givenName: ['Aufwiedersehen'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '9999999'
|
||||
}]
|
||||
}]);
|
||||
});
|
||||
|
||||
test('> Add a new Contact that matches ICE Contact', function() {
|
||||
addNewAndMatchTest(1);
|
||||
assertICEContact(2, 'Aufwiedersehen');
|
||||
});
|
||||
|
||||
test('> Find duplicates. ICE Contact Matches', function() {
|
||||
findDuplicatesAndMatchTest(1);
|
||||
assertICEContact(2, 'Aufwiedersehen');
|
||||
});
|
||||
|
||||
test('> Edit existing, change data. ICE Matches. ICE changed',
|
||||
function() {
|
||||
editAndMatchTest(1);
|
||||
assertICEContact(2, 'Aufwiedersehen');
|
||||
});
|
||||
});
|
||||
|
||||
suite('> 2 ICE Contacts. Change position 2. Keep Position 1', function() {
|
||||
setup(function() {
|
||||
createAndSetICEContacts([{
|
||||
givenName: ['Aufwiedersehen'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '9999999'
|
||||
}]
|
||||
}, testContact]);
|
||||
});
|
||||
|
||||
test('> Add a new Contact that matches ICE Contact', function() {
|
||||
addNewAndMatchTest(2);
|
||||
assertICEContact(1, 'Aufwiedersehen');
|
||||
});
|
||||
|
||||
test('> Find duplicates. ICE Contact Matches', function() {
|
||||
findDuplicatesAndMatchTest(2);
|
||||
assertICEContact(1, 'Aufwiedersehen');
|
||||
});
|
||||
|
||||
test('> Edit existing, change data. ICE Matches. ICE changed',
|
||||
function() {
|
||||
editAndMatchTest(2);
|
||||
assertICEContact(1, 'Aufwiedersehen');
|
||||
});
|
||||
});
|
||||
|
||||
suite('> 2 ICE Contacts which are merged', function() {
|
||||
setup(function() {
|
||||
setTwoICEDuplicates();
|
||||
});
|
||||
|
||||
test('> Two ICE Contacts are merged into 1', function() {
|
||||
// Going to the recently created contact
|
||||
var listContactElement =
|
||||
client.helper.waitForElement(selectors.listContactFirst);
|
||||
subject.clickOn(listContactElement);
|
||||
subject.waitSlideLeft('details');
|
||||
|
||||
var findDups = client.helper.waitForElement(selectors.findDupsButton);
|
||||
subject.clickOn(findDups);
|
||||
|
||||
mergeDuplicate();
|
||||
|
||||
subject.backToList();
|
||||
|
||||
openICESettings();
|
||||
assertICEContact(1, 'Hello');
|
||||
assertICEContactNotSet(2);
|
||||
});
|
||||
|
||||
test('> A third incoming Contact merges two ICE contacts', function() {
|
||||
addTestContact(true);
|
||||
|
||||
mergeDuplicate();
|
||||
|
||||
// Now we go back to the ICE settings and check that our ICE remains
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
openICESettings();
|
||||
assertICEContact(1, 'Hello');
|
||||
assertICEContactNotSet(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
55
gaia/apps/communications/contacts/test/marionette/import_sdcard_test.js
Executable file
55
gaia/apps/communications/contacts/test/marionette/import_sdcard_test.js
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Import from SDCARD', function() {
|
||||
var profile = Contacts.config;
|
||||
// Enable device storage
|
||||
var prefs = ['device.storage.enabled',
|
||||
'device.storage.testing',
|
||||
'device.storage.prompt.testing'];
|
||||
prefs.forEach(pref => {
|
||||
profile[pref] = true;
|
||||
});
|
||||
var client = marionette.client({
|
||||
profile: profile,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var contactsApp, selectors;
|
||||
|
||||
setup(function() {
|
||||
client.fileManager.removeAllFiles();
|
||||
client.fileManager.add({
|
||||
type: 'text',
|
||||
filePath: 'apps/communications/contacts/test/marionette/data/vcard_4.vcf'
|
||||
});
|
||||
|
||||
contactsApp = new Contacts(client);
|
||||
contactsApp.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
test('> one contact in one file', function() {
|
||||
// Go to settings
|
||||
client.helper.waitForElement(selectors.settingsButton).tap();
|
||||
|
||||
// Now click on import contacts button
|
||||
client.helper.waitForElement(selectors.importContacts).tap();
|
||||
client.helper.waitForElement(selectors.importSDCard).tap();
|
||||
|
||||
// Get back to the list
|
||||
client.switchToShadowRoot(client.helper
|
||||
.waitForElement(selectors.importHeader));
|
||||
contactsApp.clickOn(client.helper.waitForElement(selectors.actionButton));
|
||||
client.switchToShadowRoot();
|
||||
contactsApp.waitForFadeIn(client.helper
|
||||
.waitForElement(selectors.settingsView));
|
||||
client.helper.waitForElement(selectors.settingsClose).tap();
|
||||
contactsApp.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
|
||||
// Check that we have 1 contact and is the one from the SD,
|
||||
var firstContact = client.findElement(selectors.listContactFirstText);
|
||||
assert.equal(firstContact.text(), 'Forrest Gump');
|
||||
});
|
||||
});
|
||||
477
gaia/apps/communications/contacts/test/marionette/lib/contacts.js
Executable file
477
gaia/apps/communications/contacts/test/marionette/lib/contacts.js
Executable file
|
|
@ -0,0 +1,477 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Abstraction around contacts app.
|
||||
* @constructor
|
||||
* @param {Marionette.Client} client for operations.
|
||||
*/
|
||||
function Contacts(client) {
|
||||
this.client = client;
|
||||
this.client.setSearchTimeout(10000);
|
||||
this.actions = this.client.loader.getActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type String Origin of contacts app
|
||||
*/
|
||||
Contacts.URL = 'app://communications.gaiamobile.org';
|
||||
|
||||
Contacts.config = {
|
||||
prefs: {
|
||||
'device.storage.enabled': true,
|
||||
'device.storage.testing': true,
|
||||
'device.storage.prompt.testing': true
|
||||
}
|
||||
};
|
||||
|
||||
Contacts.Selectors = {
|
||||
body: 'body',
|
||||
bodyReady: 'body .view-body',
|
||||
|
||||
settingsButton: '#settings-button',
|
||||
|
||||
confirmHeader: '#confirmation-message h1',
|
||||
confirmBody: '#confirmation-message p',
|
||||
confirmDismiss: '#confirmation-message menu button',
|
||||
confirmDelete: '#confirmation-message .danger',
|
||||
|
||||
details: '#view-contact-details',
|
||||
detailsEditContact: '#edit-contact-button',
|
||||
detailsTelLabelFirst: '#phone-details-template-0 h2',
|
||||
detailsTelButtonFirst: '.button.icon-call[data-tel]',
|
||||
detailsEmail: '#contact-detail-inner #email-details-template-0 div.item',
|
||||
detailsAddress: '#contact-detail-inner #address-details-template-0 div.item',
|
||||
detailsOrg: '#contact-detail-inner #org-title',
|
||||
detailsNote: '#contact-detail-inner #note-details-template-0',
|
||||
detailsFindDuplicate: '#contact-detail-inner #find-merge-button',
|
||||
detailsFavoriteButton: '#toggle-favorite',
|
||||
detailsContactName: '#contact-name-title',
|
||||
detailsHeader: '#details-view-header',
|
||||
detailsSocialLabel: '#contact-detail-inner #details-list #social-label',
|
||||
detailsSocialTemplate: '#contact-detail-inner #details-list .social-actions',
|
||||
detailsCoverImage: '#cover-img',
|
||||
detailsShareButton: '#contact-detail-inner #share_button',
|
||||
|
||||
findDupsButton: '#details-list #find-merge-button',
|
||||
|
||||
duplicateFrame: 'iframe[src*="matching_contacts.html"]',
|
||||
duplicateHeader: '#title',
|
||||
duplicateClose: '#merge-close',
|
||||
duplicateMerge: '#merge-action',
|
||||
|
||||
exportButton: '#exportContacts button',
|
||||
exportSDCard: '#export-sd-option button',
|
||||
|
||||
form: '#view-contact-form',
|
||||
formTitle: '#contact-form-title',
|
||||
formCustomTag: '#custom-tag',
|
||||
formCustomTagPage: '#view-select-tag',
|
||||
formCustomTagDone: '#view-select-tag #settings-done',
|
||||
formNew: '#add-contact-button',
|
||||
formGivenName: '#givenName',
|
||||
formOrg: '#org',
|
||||
formFamilyName: '#familyName',
|
||||
formSave: '#save-button',
|
||||
formTel: '#contacts-form-phones input[type="tel"]',
|
||||
formDelFirstTel: '#add-phone-0 .img-delete-button',
|
||||
formTelLabelFirst: '#tel_type_0',
|
||||
formTelNumberFirst: '#number_0',
|
||||
formTelNumberSecond: '#number_1',
|
||||
formEmailFirst: '#email_0',
|
||||
formEmailSecond: '#email_1',
|
||||
formPhotoButton: '#photo-button',
|
||||
formAddNewTel: '#add-new-phone',
|
||||
formAddNewEmail: '#add-new-email',
|
||||
formHeader: '#contact-form-header',
|
||||
formPhotoImg: '#thumbnail-photo',
|
||||
deleteContact: '#delete-contact',
|
||||
|
||||
groupList: ' #groups-list',
|
||||
contacts: '#groups-list .contact-item',
|
||||
list: '#view-contacts-list',
|
||||
listContactFirst: 'li:not([data-group="ice"]).contact-item',
|
||||
listContactFirstText: 'li:not([data-group="ice"]).contact-item p',
|
||||
contactsItems: 'li:not([data-group="ice"]).contact-item p',
|
||||
contactListHeader: '#contacts-list-header',
|
||||
|
||||
contactsIframe: '#iframe-contacts',
|
||||
|
||||
searchLabel: '#search-start',
|
||||
searchInput: '#search-contact',
|
||||
searchCancel: '#cancel-search',
|
||||
searchResultFirst: '#search-list .contact-item',
|
||||
|
||||
scrollbar: 'nav[data-type="scrollbar"]',
|
||||
overlay: 'nav[data-type="scrollbar"] p',
|
||||
|
||||
settingsView: '#view-settings',
|
||||
settingsClose: '#settings-close',
|
||||
bulkDelete: '#bulkDelete',
|
||||
orderSwitch: '#settingsOrder gaia-switch',
|
||||
changeOrder: '#switch',
|
||||
|
||||
editForm: '#selectable-form',
|
||||
editMenu: '#select-all-wrapper',
|
||||
selectAction: '#select-action',
|
||||
selectAllButton: '#select-all',
|
||||
|
||||
clearOrgButton: '#clear-org',
|
||||
setIceButton: '#set-ice',
|
||||
iceHeader: '#ice-header',
|
||||
iceSettingsHeader: '#ice-settings-header',
|
||||
iceSettings: '#ice-settings',
|
||||
iceSwitch1: '#ice-contacts-1-switch',
|
||||
iceInputSwitch1: '#ice-contacts-1-switch input[type="checkbox"]',
|
||||
iceSwitch2: '#ice-contacts-2-switch',
|
||||
iceInputSwitch2: '#ice-contacts-2-switch input[type="checkbox"]',
|
||||
iceButton1: '#select-ice-contact-1',
|
||||
iceButton2: '#select-ice-contact-2',
|
||||
iceGroupOpen: '#section-group-ice',
|
||||
iceContact: '#ice-group .contact-item',
|
||||
|
||||
importContacts: '#importContacts',
|
||||
importSDCard: '#import-sd-option button',
|
||||
importHeader: '#import-settings-header',
|
||||
|
||||
activityChooser: 'form[data-type="action"]',
|
||||
buttonActivityChooser: 'form[data-type="action"] button',
|
||||
actionMenu: '#action-menu',
|
||||
actionMenuList: '#value-menu',
|
||||
actionButton: '.action-button',
|
||||
|
||||
multipleSelectSave: '#save-button',
|
||||
multipleSelectStatus: '#statusMsg p',
|
||||
multipleSelectList: '#multiple-select-container',
|
||||
|
||||
systemMenu: 'form[data-z-index-level="action-menu"]',
|
||||
|
||||
galleryImage: '.thumbnail img',
|
||||
galleryDone: '#crop-done-button',
|
||||
|
||||
header: '#edit-title',
|
||||
|
||||
noContacts: '#no-contacts'
|
||||
};
|
||||
|
||||
Contacts.prototype = {
|
||||
/**
|
||||
* Launches contacts app and focuses on frame.
|
||||
*/
|
||||
launch: function() {
|
||||
this.client.apps.launch(Contacts.URL, 'contacts');
|
||||
this.switchToApp();
|
||||
this.client.helper.waitForElement(Contacts.Selectors.bodyReady);
|
||||
},
|
||||
|
||||
relaunch: function() {
|
||||
this.close();
|
||||
this.launch();
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.client.apps.close(Contacts.URL, 'contacts');
|
||||
},
|
||||
|
||||
switchToApp: function() {
|
||||
this.client.switchToFrame();
|
||||
// switchToApp already waits for the app to be displayed
|
||||
this.client.apps.switchToApp(Contacts.URL, 'contacts');
|
||||
},
|
||||
|
||||
switchToCreateNewContactActivity: function() {
|
||||
this._switchToActivity('views/form/form.html');
|
||||
},
|
||||
|
||||
switchToMergeInterface: function() {
|
||||
this._switchToActivity('views/matching/matching_contacts.html');
|
||||
},
|
||||
|
||||
_switchToActivity: function(href) {
|
||||
this.client.switchToFrame();
|
||||
// switchToActivity already waits for the app to be displayed
|
||||
this.client.apps.switchToActivity(Contacts.URL, '/contacts/' + href);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a localized string from a properties file.
|
||||
* @param {String} file to open.
|
||||
* @param {String} key of the string to lookup.
|
||||
*/
|
||||
l10n: function(file, key) {
|
||||
var ast = this.client.executeScript(function(file, key) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var data;
|
||||
xhr.open('GET', file, false); // Intentional sync
|
||||
xhr.onload = function(o) {
|
||||
data = JSON.parse(xhr.response);
|
||||
};
|
||||
xhr.send(null);
|
||||
return data;
|
||||
}, [file, key]);
|
||||
|
||||
for (var i = 0; i < ast.length; i++) {
|
||||
if (ast[i].$i === key) {
|
||||
return ast[i].$v;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
waitSlideLeft: function(elementKey) {
|
||||
var element = this.client.findElement(Contacts.Selectors[elementKey]),
|
||||
location;
|
||||
var test = function() {
|
||||
location = element.location();
|
||||
return location.x <= 0;
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForSlideDown: function(element) {
|
||||
var bodyHeight = this.client.findElement(Contacts.Selectors.body).
|
||||
size().height;
|
||||
var test = function() {
|
||||
return element.location().y >= bodyHeight;
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForSlideUp: function(element) {
|
||||
var test = function() {
|
||||
return element.location().y <= 0;
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForFadeIn: function(element) {
|
||||
var test = function() {
|
||||
var opacity = element.cssProperty('opacity');
|
||||
var pointerEvents = element.cssProperty('pointer-events');
|
||||
|
||||
return opacity == 1 && pointerEvents == 'auto';
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForFormShown: function() {
|
||||
var form = this.client.helper.waitForElement(Contacts.Selectors.form),
|
||||
location;
|
||||
var test = function() {
|
||||
location = form.location();
|
||||
return location.y <= 0;
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForFormTransition: function() {
|
||||
var selectors = Contacts.Selectors;
|
||||
var form = this.client.findElement(selectors.form);
|
||||
try {
|
||||
this.client.helper.waitForElementToDisappear(form);
|
||||
} catch (e) {
|
||||
// When the contact details pages was created in an activity and we close
|
||||
// it, we might encounter errors like "GenericError: can't access dead
|
||||
// object" or 'JavaScriptError: unload was called'. So we drop them as it
|
||||
// makes the tests crash.
|
||||
var isKnownError = e.message.indexOf(
|
||||
'GenericError: can\'t access dead object') > -1 ||
|
||||
e.message.indexOf('JavaScriptError: unload was called') > -1;
|
||||
|
||||
if (!isKnownError) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
editContact: function() {
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
var edit = this.client.helper.waitForElement(selectors.detailsEditContact);
|
||||
this.clickOn(edit);
|
||||
this.waitForFadeIn(this.client.helper.waitForElement(selectors.form));
|
||||
},
|
||||
|
||||
// Goes back to the Contact List view from a Details view
|
||||
backToList: function() {
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
// Now we go back to the ICE settings and check that our ICE remains
|
||||
this.waitForFadeIn(this.client.helper.waitForElement(selectors.details));
|
||||
var header = this.client.helper.waitForElement(selectors.detailsHeader);
|
||||
this.actions.wait(0.5).tap(header, 10, 10).perform();
|
||||
this.waitSlideLeft('list');
|
||||
},
|
||||
|
||||
enterContactDetails: function(details) {
|
||||
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
details = details || {
|
||||
givenName: 'Hello',
|
||||
familyName: 'Contact',
|
||||
org: 'Enterprise'
|
||||
};
|
||||
|
||||
this.waitForFormShown();
|
||||
|
||||
for (var i in details) {
|
||||
// Camelcase details to match form.* selectors.
|
||||
var key = 'form' + i.charAt(0).toUpperCase() + i.slice(1);
|
||||
|
||||
this.client.findElement(selectors[key])
|
||||
.sendKeys(details[i]);
|
||||
}
|
||||
|
||||
this.client.findElement(selectors.formSave).click();
|
||||
},
|
||||
|
||||
addContact: function(details) {
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
var addContact = this.client.findElement(selectors.formNew);
|
||||
addContact.click();
|
||||
|
||||
this.enterContactDetails(details);
|
||||
this.waitForFormTransition();
|
||||
|
||||
this.client.helper.waitForElement(selectors.list);
|
||||
},
|
||||
|
||||
mergeContact: function(details) {
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
var addContact = this.client.findElement(selectors.formNew);
|
||||
addContact.click();
|
||||
|
||||
this.enterContactDetails(details);
|
||||
this.switchToMergeInterface();
|
||||
|
||||
var duplicateFrame = this.client.findElement(selectors.duplicateFrame);
|
||||
|
||||
var mergeAction =
|
||||
this.client.helper.waitForElement(selectors.duplicateMerge);
|
||||
this.clickOn(mergeAction);
|
||||
|
||||
this.switchTo();
|
||||
this.waitForSlideDown(duplicateFrame);
|
||||
},
|
||||
|
||||
addContactMultipleEmails: function(details) {
|
||||
var selectors = Contacts.Selectors;
|
||||
|
||||
var addContact = this.client.findElement(selectors.formNew);
|
||||
addContact.click();
|
||||
this.client.helper.waitForElement(selectors.formAddNewEmail).click();
|
||||
|
||||
this.enterContactDetails(details);
|
||||
this.waitForFormTransition();
|
||||
|
||||
this.client.helper.waitForElement(selectors.list);
|
||||
},
|
||||
|
||||
tapContact: function(contactName) {
|
||||
// There are currently no way to search on the text of an HTML Element
|
||||
// That's why this function do the filter and check that no more than 1
|
||||
// contact has the name we look up.
|
||||
var elements = this.client.findElements(Contacts.Selectors.contacts);
|
||||
var contactsWithName = elements.filter(function(el) {
|
||||
var data = el.text();
|
||||
return data && data.indexOf(contactName) > -1;
|
||||
});
|
||||
|
||||
if (contactsWithName.length === 1) {
|
||||
contactsWithName[0].tap();
|
||||
} else if (contactsWithName.length > 1) {
|
||||
throw new Error('There are more than 1 contact that contains "' +
|
||||
contactName + '"');
|
||||
} else {
|
||||
throw new Error('"' + contactName + '" was not found');
|
||||
}
|
||||
},
|
||||
|
||||
getContactFirstName: function() {
|
||||
var ci = this.client.findElement(Contacts.Selectors.contactsIframe);
|
||||
this.client.switchToFrame(ci);
|
||||
|
||||
var contactInContactList = this.client.findElement(
|
||||
Contacts.Selectors.listContactFirst
|
||||
);
|
||||
var contactName = contactInContactList.text();
|
||||
return contactName;
|
||||
},
|
||||
|
||||
tapSave: function() {
|
||||
this.client.helper.waitForElement(Contacts.Selectors.formSave).click();
|
||||
},
|
||||
|
||||
createNewContactAndReturnToDialer: function(contactName) {
|
||||
this.client.helper.waitForElement(Contacts.Selectors.formGivenName);
|
||||
this.client.helper.fillInputField(
|
||||
Contacts.Selectors.formGivenName, contactName
|
||||
);
|
||||
this.client.helper.waitForElement(Contacts.Selectors.formSave).click();
|
||||
|
||||
var dialer = this.client.loader.getAppClass('dialer');
|
||||
dialer.switchTo();
|
||||
return dialer;
|
||||
},
|
||||
|
||||
tapUpdate: function() {
|
||||
this.tapSave();
|
||||
},
|
||||
|
||||
get systemMenu() {
|
||||
var selectors = Contacts.Selectors;
|
||||
// Switch to the system app first.
|
||||
this.client.switchToFrame();
|
||||
return this.client.helper.waitForElement(selectors.systemMenu);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method to simulate clicks on iFrames which is not currently
|
||||
* working in the Marionette JS Runner.
|
||||
* @param {Marionette.Element} element The element to simulate the click on.
|
||||
**/
|
||||
clickOn: function(element) {
|
||||
element.scriptWith(function(elementEl) {
|
||||
var event = new MouseEvent('click', {
|
||||
'view': window,
|
||||
'bubbles': true,
|
||||
'cancelable': true
|
||||
});
|
||||
elementEl.dispatchEvent(event);
|
||||
});
|
||||
},
|
||||
|
||||
goToSettings: function() {
|
||||
this.client.helper.waitForElement(
|
||||
Contacts.Selectors.settingsButton).tap();
|
||||
var settings = this.client.helper.waitForElement(
|
||||
Contacts.Selectors.settingsView);
|
||||
this.waitForFadeIn(settings);
|
||||
},
|
||||
|
||||
getElementStyle: function(selector, type) {
|
||||
return this.client.executeScript(function(selector, type) {
|
||||
return document.querySelector(selector).style[type];
|
||||
}, [selector, type]);
|
||||
},
|
||||
|
||||
getNumberOfContacts: function() {
|
||||
return this.contactsNames.length;
|
||||
},
|
||||
|
||||
get contactsNames() {
|
||||
try {
|
||||
var contactElements = this.client.findElements(
|
||||
Contacts.Selectors.contactsItems);
|
||||
return contactElements.map((element) => {
|
||||
return element.text();
|
||||
});
|
||||
} catch(e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = Contacts;
|
||||
126
gaia/apps/communications/contacts/test/marionette/lib/contacts_data.js
Executable file
126
gaia/apps/communications/contacts/test/marionette/lib/contacts_data.js
Executable file
|
|
@ -0,0 +1,126 @@
|
|||
'use strict';
|
||||
|
||||
/* globals mozContact */
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
/* This module contains Contacts Data Layer functions */
|
||||
|
||||
function ContactsData(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
ContactsData.prototype = {
|
||||
// Creates a new FB Contact
|
||||
createFbContact: function() {
|
||||
this.client.importScript(fs.readFileSync(__dirname +
|
||||
'/../data/facebook_contact_data.js',
|
||||
'utf8'));
|
||||
|
||||
var saveFBContact = function() {
|
||||
var LazyLoader = window.wrappedJSObject.LazyLoader;
|
||||
var data = window.wrappedJSObject.data;
|
||||
var fb = window.wrappedJSObject.fb;
|
||||
var Contacts = window.wrappedJSObject.Contacts;
|
||||
|
||||
var DEPS = [
|
||||
'/shared/js/contacts/utilities/image_square.js'
|
||||
];
|
||||
Contacts.loadFacebook(function() {
|
||||
LazyLoader.load(DEPS, function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/contacts/style/images/f_logo.png');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = function() {
|
||||
var fbContact = new fb.Contact();
|
||||
data.fbContactData.fbInfo.photo = [xhr.response];
|
||||
fbContact.setData(data.fbContactData);
|
||||
|
||||
var savingFBContact = fbContact.save();
|
||||
|
||||
savingFBContact.onsuccess = function() {
|
||||
marionetteScriptFinished(data.fbContactData);
|
||||
};
|
||||
|
||||
savingFBContact.onerror = function() {
|
||||
marionetteScriptFinished();
|
||||
};
|
||||
};
|
||||
xhr.onerror = marionetteScriptFinished;
|
||||
xhr.send(null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var fbContactData;
|
||||
this.client.executeAsyncScript(saveFBContact, function(err, val) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
fbContactData = val;
|
||||
});
|
||||
|
||||
this.client.waitFor(function() {
|
||||
return fbContactData;
|
||||
});
|
||||
|
||||
return fbContactData;
|
||||
},
|
||||
|
||||
createMozContact: function(contactData, withPhoto) {
|
||||
var saveMozContact = function(contactData, withPhoto) {
|
||||
var doSave = function doSave(contactData) {
|
||||
var mozContacts = navigator.mozContacts;
|
||||
|
||||
var handler = function handler(event) {
|
||||
mozContacts.removeEventListener('contactchange', handler);
|
||||
marionetteScriptFinished(event.contactID);
|
||||
};
|
||||
|
||||
mozContacts.addEventListener('contactchange', handler);
|
||||
|
||||
var contact = new mozContact(contactData);
|
||||
var req = mozContacts.save(contact);
|
||||
|
||||
req.onerror = function() {
|
||||
mozContacts.removeEventListener('contactchange', handler);
|
||||
marionetteScriptFinished();
|
||||
};
|
||||
};
|
||||
|
||||
if (withPhoto) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/contacts/style/images/f_logo.png');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = function() {
|
||||
contactData.photo = [xhr.response];
|
||||
doSave(contactData);
|
||||
};
|
||||
xhr.onerror = marionetteScriptFinished;
|
||||
|
||||
xhr.send(null);
|
||||
}
|
||||
else {
|
||||
doSave(contactData);
|
||||
}
|
||||
};
|
||||
|
||||
var contactID;
|
||||
this.client.executeAsyncScript(saveMozContact, [contactData, withPhoto],
|
||||
function(err, val) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
contactID = val;
|
||||
});
|
||||
|
||||
this.client.waitFor(function() {
|
||||
return contactID;
|
||||
});
|
||||
|
||||
return contactID;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ContactsData;
|
||||
40
gaia/apps/communications/contacts/test/marionette/lib/sms.js
Executable file
40
gaia/apps/communications/contacts/test/marionette/lib/sms.js
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Abstraction around sms app.
|
||||
* This file can be moved to the sms app once we
|
||||
* implement sms marionette tests.
|
||||
* @constructor
|
||||
* @param {Marionette.Client} client for operations.
|
||||
*/
|
||||
function Sms(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type String Origin of sms app
|
||||
*/
|
||||
Sms.URL = 'app://sms.gaiamobile.org';
|
||||
|
||||
Sms.Selectors = {
|
||||
listCompose: '#icon-add',
|
||||
threadAddContact: '#messages-contact-pick-button'
|
||||
};
|
||||
|
||||
Sms.prototype = {
|
||||
/**
|
||||
* Launches sms app and focuses on frame.
|
||||
*/
|
||||
launch: function() {
|
||||
this.client.apps.launch(Sms.URL);
|
||||
this.client.apps.switchToApp(Sms.URL);
|
||||
this.client.helper.waitForElement('body');
|
||||
},
|
||||
|
||||
relaunch: function() {
|
||||
this.client.apps.close(Sms.URL);
|
||||
this.launch();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Sms;
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
/* global module */
|
||||
var SELECTORS = Object.freeze({
|
||||
detailsFavoriteButton: '#toggle-favorite',
|
||||
detailsHeader: '#details-view-header',
|
||||
details: '#view-contact-details',
|
||||
list: '#view-contacts-list'
|
||||
});
|
||||
|
||||
function ContactsDetailsAccessor(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
ContactsDetailsAccessor.prototype = {
|
||||
get favoritesButton() {
|
||||
return this.client.helper.waitForElement(
|
||||
SELECTORS.detailsFavoriteButton);
|
||||
},
|
||||
|
||||
get detailsHeader() {
|
||||
return this.client.helper.waitForElement(
|
||||
SELECTORS.detailsHeader);
|
||||
},
|
||||
|
||||
get listSelector () {
|
||||
return SELECTORS.list;
|
||||
},
|
||||
|
||||
get detailsSelector () {
|
||||
return SELECTORS.details;
|
||||
},
|
||||
|
||||
get detailsHeaderSelector () {
|
||||
return SELECTORS.detailsHeader;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ContactsDetailsAccessor;
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
'use strict';
|
||||
|
||||
/* global module */
|
||||
|
||||
var ContactsDetailsAccessor = require('./accessors');
|
||||
|
||||
function ContactsDetailsView(client) {
|
||||
this.client = client;
|
||||
this.accessors = new ContactsDetailsAccessor(client);
|
||||
}
|
||||
|
||||
ContactsDetailsView.prototype = {
|
||||
makeFavorited: function() {
|
||||
this.accessors.favoritesButton.tap();
|
||||
this.waitForFavorited;
|
||||
},
|
||||
|
||||
waitForFavorited: function() {
|
||||
var self = this;
|
||||
this.client.waitFor(
|
||||
'waitForHeaderToContainFavoriteClass', function() {
|
||||
return self.accessors.detailsHeader.getAttribute(
|
||||
'class').indexOf('favorite') != -1;
|
||||
});
|
||||
},
|
||||
//TO-DO: ADD THIS TO A CONTACT VIEW BASE CLASS
|
||||
backToList: function() {
|
||||
this.waitForFadeIn(this.client.helper.waitForElement(
|
||||
this.accessors.detailsSelector));
|
||||
var header = this.client.helper.waitForElement(
|
||||
this.accessors.detailsHeaderSelector);
|
||||
this.client.loader.getActions().wait(0.5).tap(header, 10, 10).perform();
|
||||
this.waitSlideLeftList();
|
||||
},
|
||||
|
||||
waitSlideLeftList: function() {
|
||||
var element = this.client.findElement(
|
||||
this.accessors.listSelector),
|
||||
location;
|
||||
var test = function() {
|
||||
location = element.location();
|
||||
return location.x <= 0;
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
waitForFadeIn: function(element) {
|
||||
var test = function() {
|
||||
var opacity = element.cssProperty('opacity');
|
||||
var pointerEvents = element.cssProperty('pointer-events');
|
||||
return opacity == 1 && pointerEvents == 'auto';
|
||||
};
|
||||
this.client.waitFor(test);
|
||||
},
|
||||
|
||||
backtoContactsList: function() {
|
||||
this.backToList();
|
||||
var ContactsListView = require('../contact-list/view');
|
||||
var contactsListView = new ContactsListView(this.client);
|
||||
contactsListView.accessors.firstFavorite;
|
||||
return contactsListView;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = ContactsDetailsView;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
/* global module */
|
||||
var SELECTORS = Object.freeze({
|
||||
listContactFirstText: 'li:not([data-group="ice"]).contact-item p',
|
||||
listFavoritesFirstText: '#contacts-list-favorites .contact-item p',
|
||||
details: '#view-contact-details'
|
||||
});
|
||||
|
||||
function ContactsListAccessor(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
ContactsListAccessor.prototype = {
|
||||
get firstContact() {
|
||||
return this.client.helper.waitForElement(
|
||||
SELECTORS.listContactFirstText);
|
||||
},
|
||||
|
||||
get firstFavorite() {
|
||||
return this.client.helper.waitForElement(
|
||||
SELECTORS.listFavoritesFirstText);
|
||||
},
|
||||
|
||||
get detailsSelector() {
|
||||
return SELECTORS.details;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = ContactsListAccessor;
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
/* global module */
|
||||
|
||||
var ContactsListAccessor = require('./accessors');
|
||||
|
||||
function ContactsListView(client) {
|
||||
this.client = client;
|
||||
this.accessors = new ContactsListAccessor(client);
|
||||
}
|
||||
|
||||
ContactsListView.prototype = {
|
||||
get firstContact() {
|
||||
return this.accessors.firstContact;
|
||||
},
|
||||
|
||||
get firstFavorite() {
|
||||
return this.accessors.firstFavorite;
|
||||
},
|
||||
|
||||
waitSlideLeftDetails: function() {
|
||||
var element = this.client.findElement(
|
||||
this.accessors.detailsSelector),
|
||||
location;
|
||||
var waitUntilPanelReachedLeftBorder = function() {
|
||||
location = element.location();
|
||||
return location.x <= 0;
|
||||
};
|
||||
this.client.waitFor(waitUntilPanelReachedLeftBorder);
|
||||
},
|
||||
|
||||
goToContact: function() {
|
||||
this.firstContact.tap();
|
||||
this.waitSlideLeftDetails();
|
||||
return this._createContactsDetailsView();
|
||||
},
|
||||
|
||||
_createContactsDetailsView: function() {
|
||||
var ContactsDetailsView = require('../contact-details/view');
|
||||
var contactsDetailsView = new ContactsDetailsView(
|
||||
this.client, this.subject);
|
||||
return contactsDetailsView;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = ContactsListView;
|
||||
192
gaia/apps/communications/contacts/test/marionette/list_test.js
Executable file
192
gaia/apps/communications/contacts/test/marionette/list_test.js
Executable file
|
|
@ -0,0 +1,192 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var ContactsData = require('./lib/contacts_data');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts > List', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var subject;
|
||||
var selectors;
|
||||
var contactsData;
|
||||
var actions;
|
||||
|
||||
var agenda = [{ givenName: 'a' }, { givenName: 'b' }, { givenName: 'c' },
|
||||
{ givenName: 'd' }, { givenName: 'e' }, { givenName: 'f' },
|
||||
{ givenName: 'g' }, { givenName: 'h' }, { givenName: 'i' }];
|
||||
|
||||
function getNumberOfItemsVisited() {
|
||||
return client.executeScript(function() {
|
||||
return document.querySelectorAll('li[data-visited="true"]').length;
|
||||
});
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
contactsData = new ContactsData(client);
|
||||
actions = client.loader.getActions();
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
suite('Visited contacts > ', function() {
|
||||
setup(function() {
|
||||
agenda.forEach(function(contact) {
|
||||
subject.addContact(contact);
|
||||
});
|
||||
});
|
||||
|
||||
test('at least one has been visited by the imageLoader', function() {
|
||||
assert.ok(getNumberOfItemsVisited() > 0);
|
||||
});
|
||||
|
||||
test('number of visited is the same after leaving search view', function() {
|
||||
var numItemsVisited = getNumberOfItemsVisited();
|
||||
client.findElement(selectors.searchLabel).click();
|
||||
client.helper.waitForElement(selectors.searchCancel).click();
|
||||
assert.ok(getNumberOfItemsVisited() === numItemsVisited);
|
||||
});
|
||||
});
|
||||
|
||||
suite('List Order > ', function() {
|
||||
var data = [['GG', 'E'], ['AA', 'Z'],
|
||||
['XX', 'C'], ['CC', 'X'], ['EE', 'G'], ['FF', 'F'], ['HH', 'D'],
|
||||
['BB', 'Y'], ['YY', 'B'], ['ZZ', 'A'], ['DD', 'H']];
|
||||
setup(function() {
|
||||
data.forEach(contactData => {
|
||||
contactsData.createMozContact({
|
||||
givenName: [contactData[0]],
|
||||
familyName: [contactData[1]]
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
function givenNameOrder(a, b) {
|
||||
return a[0].localeCompare(b[0]);
|
||||
}
|
||||
|
||||
function familyNameOrder(a, b) {
|
||||
return a[1].localeCompare(b[1]);
|
||||
}
|
||||
|
||||
test('Default to: given name > ', function() {
|
||||
var names = subject.contactsNames;
|
||||
var targetOrder = data.sort(givenNameOrder);
|
||||
names.forEach((name, index) => {
|
||||
assert.equal(name, targetOrder[index][0] + ' ' + targetOrder[index][1]);
|
||||
});
|
||||
});
|
||||
|
||||
test('Order by family name > ', function() {
|
||||
subject.goToSettings();
|
||||
|
||||
// Change order
|
||||
client.switchToShadowRoot(
|
||||
client.helper.waitForElement(selectors.orderSwitch));
|
||||
subject.clickOn(client.findElement(selectors.changeOrder));
|
||||
client.switchToShadowRoot();
|
||||
subject.clickOn(client.findElement(selectors.settingsClose));
|
||||
subject.waitForFadeIn(client.helper.waitForElement(selectors.list));
|
||||
|
||||
var names = subject.contactsNames;
|
||||
var targetOrder = data.sort(familyNameOrder);
|
||||
names.forEach((name, index) => {
|
||||
assert.equal(name, targetOrder[index][0] + ' ' + targetOrder[index][1]);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('Images in list > ', function() {
|
||||
// Generates 3 contacts for each letter with image
|
||||
function generateContactsWithImage() {
|
||||
for(var i = 0; i < 25; i++) {
|
||||
var name = '';
|
||||
var character = 97 + i;
|
||||
for (var j = 0; j < 3; j++) {
|
||||
name += String.fromCharCode(character);
|
||||
var contactData = {
|
||||
givenName: [name]
|
||||
};
|
||||
contactsData.createMozContact(contactData, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function firstContactHasImage() {
|
||||
return client.executeScript(function() {
|
||||
var span = document.querySelector(
|
||||
'#contacts-list-A .contact-item span');
|
||||
if (!span) {
|
||||
return false;
|
||||
}
|
||||
return span.dataset.src && span.style.backgroundImage !== null;
|
||||
});
|
||||
}
|
||||
|
||||
function firstContactHasDefaultImage() {
|
||||
try {
|
||||
var span = client.findElement(
|
||||
'#contacts-list-A .contact-item span');
|
||||
return span.cssProperty('background-image') === 'url(' +
|
||||
'"app://communications.gaiamobile.org/contacts/' +
|
||||
'style/images/Imagery.png")';
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkLetterForElement(selector, letter) {
|
||||
try {
|
||||
var elem = client.findElement(selector);
|
||||
return elem.getAttribute('data-group') === letter;
|
||||
} catch (e) {
|
||||
return e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
suite('Default Images > ', function() {
|
||||
// Moztrap: https://moztrap.mozilla.org/manage/case/14399/
|
||||
test('contact with no picture show the default one', function() {
|
||||
subject.addContact({givenName: 'Anthony'});
|
||||
assert.ok(firstContactHasDefaultImage());
|
||||
assert.ok(checkLetterForElement('span[data-type="img"]', 'A'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Contacts with images > ', function() {
|
||||
setup(function() {
|
||||
generateContactsWithImage();
|
||||
});
|
||||
|
||||
test('after scrolling we keep the images', function() {
|
||||
// Scroll to different sections in the list
|
||||
var scrollbar = client.helper.waitForElement(
|
||||
Contacts.Selectors.scrollbar);
|
||||
//F
|
||||
actions.press(scrollbar, 15, 100).release().perform();
|
||||
client.helper.waitForElement(Contacts.Selectors.overlay);
|
||||
client.helper.waitForElementToDisappear(Contacts.Selectors.overlay);
|
||||
//T
|
||||
actions.press(scrollbar, 15, 300).release().perform();
|
||||
client.helper.waitForElement(Contacts.Selectors.overlay);
|
||||
client.helper.waitForElementToDisappear(Contacts.Selectors.overlay);
|
||||
//X
|
||||
actions.press(scrollbar, 15, 350).release().perform();
|
||||
client.helper.waitForElement(Contacts.Selectors.overlay);
|
||||
client.helper.waitForElementToDisappear(Contacts.Selectors.overlay);
|
||||
//A
|
||||
actions.press(scrollbar, 15, 40).release().perform();
|
||||
client.helper.waitForElement(Contacts.Selectors.overlay);
|
||||
client.helper.waitForElementToDisappear(Contacts.Selectors.overlay);
|
||||
|
||||
assert.ok(firstContactHasImage());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
7
gaia/apps/communications/contacts/test/marionette/manifest.ini
Executable file
7
gaia/apps/communications/contacts/test/marionette/manifest.ini
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
[form_test.js]
|
||||
[search_test.js]
|
||||
[activities_test.js]
|
||||
[details_test.js]
|
||||
[contacts_shortcuts_test.js]
|
||||
[delete_contacts_test.js]
|
||||
[ice_test.js]
|
||||
77
gaia/apps/communications/contacts/test/marionette/merge_test.js
Executable file
77
gaia/apps/communications/contacts/test/marionette/merge_test.js
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts > Merge contacts', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var subject;
|
||||
var selectors;
|
||||
|
||||
var aTelNumber = '655555555';
|
||||
var anotherTelNumber = '655555556';
|
||||
|
||||
function addTestContact(name, telephone) {
|
||||
subject.addContact({
|
||||
givenName: name,
|
||||
tel: telephone
|
||||
});
|
||||
}
|
||||
|
||||
function mergeContact(name, telephone) {
|
||||
subject.mergeContact({
|
||||
givenName: name,
|
||||
tel: telephone
|
||||
});
|
||||
}
|
||||
|
||||
function selectAll(callback) {
|
||||
// Click on settings button and wait for slide up animation
|
||||
client.helper.waitForElement(selectors.settingsButton).click();
|
||||
var settings = client.helper.waitForElement(selectors.settingsView);
|
||||
subject.waitForSlideUp(settings);
|
||||
|
||||
// Click on delete button and wait for slide down animation
|
||||
client.helper.waitForElement(selectors.bulkDelete).click();
|
||||
subject.waitForSlideDown(settings);
|
||||
|
||||
var editForm = client.findElement(selectors.editForm);
|
||||
editForm.displayed(callback);
|
||||
}
|
||||
|
||||
function checkHeaderCount(expectedCount) {
|
||||
client.helper.waitForElement(selectors.selectAllButton).click();
|
||||
|
||||
var header = client.helper.waitForElement(selectors.header);
|
||||
return assert.equal(header.getAttribute('data-l10n-args'),
|
||||
'{"n":' + expectedCount + '}');
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
// Disabling these tests by now due to we need a way to switch to a
|
||||
// different window instead of switching to an app, due to paths can
|
||||
// differ.
|
||||
// More info in [1].
|
||||
// These test must be recovered once this bug will be landed.
|
||||
|
||||
// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1140344#c9
|
||||
test.skip(
|
||||
'Selection count should be correct after merging contacts',
|
||||
function() {
|
||||
addTestContact('Contact1', aTelNumber);
|
||||
addTestContact('Contact2', anotherTelNumber);
|
||||
mergeContact('Contact3', anotherTelNumber);
|
||||
selectAll(function() {
|
||||
checkHeaderCount(2);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
60
gaia/apps/communications/contacts/test/marionette/multiple_select_test.js
Executable file
60
gaia/apps/communications/contacts/test/marionette/multiple_select_test.js
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
/* global MozActivity */
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var Sms = require('./lib/sms');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
marionette('Contacts > MultipleSelect', function() {
|
||||
var client = marionette.client({ profile: Contacts.config });
|
||||
var subject;
|
||||
var smsSubject;
|
||||
var selectors;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
smsSubject = new Sms(client);
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
suite('Import', function() {
|
||||
function getNumberOfContacts(callback) {
|
||||
client.executeAsyncScript(function() {
|
||||
var request = navigator.mozContacts.getCount();
|
||||
request.onsuccess = function() {
|
||||
marionetteScriptFinished(request.result);
|
||||
};
|
||||
}, callback);
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
smsSubject.launch();
|
||||
client.executeScript(function(vCardFile) {
|
||||
new MozActivity({
|
||||
name: 'open',
|
||||
data: {
|
||||
type: 'text/vcard',
|
||||
filename: 'vcard_21_multiple.vcf',
|
||||
blob: new Blob([vCardFile], {type: 'text/vcard'}),
|
||||
allowSave: true
|
||||
}
|
||||
});
|
||||
}, [fs.readFileSync(__dirname + '/data/vcard_21_multiple.vcf', 'utf8')]);
|
||||
|
||||
var iframe = 'iframe[src="' + Contacts.URL +
|
||||
'/contacts/views/vcard_load/vcard_load.html"]';
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(client.findElement(iframe), {'focus': true});
|
||||
});
|
||||
|
||||
test('Importing all contacts', function() {
|
||||
client.helper.waitForElement(selectors.multipleSelectSave).click();
|
||||
var status = client.helper.waitForElement(selectors.multipleSelectStatus);
|
||||
assert.ok(status.text().indexOf('2') >= 0);
|
||||
getNumberOfContacts(function(err, value) {
|
||||
assert.equal(value, 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
76
gaia/apps/communications/contacts/test/marionette/search_test.js
Executable file
76
gaia/apps/communications/contacts/test/marionette/search_test.js
Executable file
|
|
@ -0,0 +1,76 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var ContactsData = require('./lib/contacts_data');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts > Search', function() {
|
||||
var client = marionette.client({
|
||||
profile: Contacts.config,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var contactsData = new ContactsData(client);
|
||||
var subject;
|
||||
var selectors;
|
||||
var testContact;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
|
||||
testContact = {
|
||||
tel: [{value: '1231231234', type: ['home']}],
|
||||
givenName: ['Hello'],
|
||||
familyName: ['World'],
|
||||
name: ['Hello World'],
|
||||
email: [{value: 'hello@example.com', type: ['home']}],
|
||||
adr: [{type: ['home'], pref: true, streetAddress: 'False Street 123'}],
|
||||
org: ['Mozilla'],
|
||||
note: ['This is a note about the contact.']
|
||||
};
|
||||
|
||||
selectors = Contacts.Selectors;
|
||||
});
|
||||
|
||||
suite('Search Mode', function() {
|
||||
test('Can enter and exit search mode', function() {
|
||||
contactsData.createMozContact(testContact);
|
||||
|
||||
client.helper.waitForElement(selectors.searchLabel).click();
|
||||
var result = client.helper.waitForElement(selectors.searchResultFirst);
|
||||
assert.ok(result.displayed(), 'Search view was not opened');
|
||||
|
||||
client.helper.waitForElement(selectors.searchCancel).click();
|
||||
var listView = client.helper.waitForElement(selectors.list);
|
||||
assert.ok(listView.displayed(), 'List view was not shown');
|
||||
});
|
||||
|
||||
test('Search text is displayed correctly', function() {
|
||||
var details = details || {
|
||||
givenName: ['A%%&']
|
||||
};
|
||||
|
||||
contactsData.createMozContact(details);
|
||||
client.helper.waitForElement(selectors.searchLabel).click();
|
||||
client.helper.waitForElement(selectors.searchInput).sendKeys('a');
|
||||
client.helper.waitForElement(selectors.searchResultFirst).text(
|
||||
function(error, textContent) {
|
||||
assert.equal('A%%&', textContent);
|
||||
});
|
||||
});
|
||||
|
||||
test('Search gets updated if contact changes', function() {
|
||||
contactsData.createMozContact(testContact);
|
||||
client.helper.waitForElement(selectors.searchLabel).click();
|
||||
client.helper.waitForElement(selectors.searchResultFirst).click();
|
||||
client.helper.waitForElement(selectors.detailsEditContact).click();
|
||||
subject.waitForFormShown();
|
||||
client.helper.waitForElement(selectors.formGivenName).sendKeys('zzz');
|
||||
client.findElement(selectors.formSave).click();
|
||||
client.helper.waitForElement(selectors.detailsContactName).text(
|
||||
function(error, textContent) {
|
||||
assert.ok(textContent.indexOf('zzz') > -1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
49
gaia/apps/communications/contacts/test/marionette/settings_test.js
Executable file
49
gaia/apps/communications/contacts/test/marionette/settings_test.js
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
var Contacts = require('./lib/contacts');
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Contacts > Settings', function() {
|
||||
var client = marionette.client({ profile: Contacts.config });
|
||||
var subject;
|
||||
var selectors;
|
||||
var buttonSelectors;
|
||||
|
||||
setup(function() {
|
||||
subject = new Contacts(client);
|
||||
subject.launch();
|
||||
selectors = Contacts.Selectors;
|
||||
buttonSelectors = [selectors.exportButton, selectors.bulkDelete,
|
||||
selectors.setIceButton];
|
||||
});
|
||||
|
||||
function isDisabled(selector) {
|
||||
return client.executeScript(function(selector) {
|
||||
return document.querySelector(selector).disabled;
|
||||
}, [selector]);
|
||||
}
|
||||
|
||||
suite('Export, delete and ice buttons disabled', function() {
|
||||
test('No contacts -> Disabled', function() {
|
||||
client.findElement(selectors.settingsButton).click();
|
||||
var settings = client.helper.waitForElement(selectors.settingsView);
|
||||
subject.waitForSlideUp(settings);
|
||||
buttonSelectors.forEach(function(selector) {
|
||||
assert.ok(isDisabled(selector));
|
||||
});
|
||||
});
|
||||
|
||||
test('List not empty -> Active', function() {
|
||||
subject.addContact({
|
||||
givenName: 'Cristian'
|
||||
});
|
||||
|
||||
client.helper.waitForElement(selectors.settingsButton).click();
|
||||
var settings = client.helper.waitForElement(selectors.settingsView);
|
||||
subject.waitForSlideUp(settings);
|
||||
buttonSelectors.forEach(function(selector) {
|
||||
assert.ok(!isDisabled(selector));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
17
gaia/apps/communications/contacts/test/unit/.jshintrc
Executable file
17
gaia/apps/communications/contacts/test/unit/.jshintrc
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"require",
|
||||
"requireApp",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
24
gaia/apps/communications/contacts/test/unit/base64_photo.js
Executable file
24
gaia/apps/communications/contacts/test/unit/base64_photo.js
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
/* exported b64Photo */
|
||||
'use strict';
|
||||
|
||||
var b64Photo = 'Qk02BAAAAAAAADYAAAAoAAAAEAAAAPD///8BACAAAAAAAAAAAABiBwAAYgc' +
|
||||
'AAAAAAAAAAAAA///////////////////////////////////////////////////+//////////' +
|
||||
'///////////////////////////////////' +
|
||||
'//////////////////////////V0s3/b21l/1pbVf' +
|
||||
'9ydHL/u8HB//D09f/29vb///////////////////////////////////////Lx8P9ycWv/EhEO' +
|
||||
'/wAAAP8AAgD/Gh0Z/15mav+tt7z/6+zr/////////////v////////////////////////+IiY' +
|
||||
'f/AgYF/wAAAP8AAAD/AAAA/x8iI/88Ojv/e3l6///+/v//////////////////////////////' +
|
||||
'///p5+f/am5z/xoeI/8iKDH/HSIr/ztATP+wtL//sbfC/zI4P//Ky8r///////////////////' +
|
||||
'////7+/f/s7O3/vcDH/2Fkbf8+Qk7/foSW/5Wcsv+5vtP/7ezz//////97g5P/j5Oh//f4+P//' +
|
||||
'////+/v7//Py8v/z8vP/9/j5/8jL2/8zNkD/MDM4/3Nydf/X0+H/0cvZ/7Srrv/Hvrz/h4uX/2' +
|
||||
'Vsf/+5vcP/5OXj//Tz8//5+fn///////7+/v+eoa3/NjxE/2Vnaf9vbGr/pqSt/+ro8v+xqrP/' +
|
||||
'6ePi/4SLnP85QE//e4SQ/5CWmv////////////z8+//X1tf/kZWc/09UXP9hY2f/TEhL/62twP' +
|
||||
'/o6vP/n5ij/9LM0f+WnbX/PkRS/4CFkv99gor//f39//j39//19PP/+Pj3//////+ysrj/cnqP' +
|
||||
'/21viv/c2On/9PL3//Hv+v/l5/T/x8jd/7Cvv//Y0NX/5NzD//X19f/7+/v///////Py9v/W3u' +
|
||||
'f/z9Xa/4WFm/9UVGn/tK3D/+/o8v/Y0uD/9fL8/+3q9f/w7fn/+/n+////////////////////' +
|
||||
'///08/b/2eLo/8XT2P9zdYb/XFxy/8S80//68vz/urTE/9XU5//j4+//9vX6////////////7e' +
|
||||
'/u/+Dk5v/a4OT/8vf5///////g5+n/kZKe/25of/9sa3D/ZGNn/2pndf/ExdP/0tTf/+nm4//+' +
|
||||
'/Pr//////87V2v+KmKf/cYOV/3mMn/+NnK3/TVll/1dYZP9kYHn/ODBG/yAcMP9fXW//ubzK/9' +
|
||||
'PW3/9JREX/OTIu/7OxsP//////y9HZ/4WSov9xfo//TVhx/x8nNP8ZGiH/Y2F//3Bphv9vZYj/' +
|
||||
'mZm3/7C1yv/Ey9n/DREX/wYIDf9ZaYb//v7+/8vS2v+Hk6T/h4+c/2hxg/8iJi//AwQE/0pHYP' +
|
||||
'9nX4f/kIuv/4WIo/+GjaT/doOb/wECBv8dIS3/VWWL/w==';
|
||||
667
gaia/apps/communications/contacts/test/unit/bootstrap_test.js
vendored
Executable file
667
gaia/apps/communications/contacts/test/unit/bootstrap_test.js
vendored
Executable file
|
|
@ -0,0 +1,667 @@
|
|||
/* global Cache */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('communications/contacts/js/utilities/performance_helper.js');
|
||||
requireApp('communications/contacts/js/bootstrap.js');
|
||||
requireApp('communications/contacts/js/cache.js');
|
||||
|
||||
const DUMMY_CONTACT_UUID = '06eecb011f424a97aaa615c26ef66e0c';
|
||||
const ANOTHER_DUMMY_CONTACT_UUID = 'c7e3e90e2d8d4ade872ba3575deef54d';
|
||||
const YET_ANOTHER_DUMMY_CONTACT_UUID = '2ac02c47e2984c07a81476e5ae8f40d7';
|
||||
|
||||
// Cache of a contact named "Dummy"
|
||||
const VALID_CACHE_ONE_CONTACT = { content: [
|
||||
{
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-D'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-D\" class=\"\"
|
||||
id=\"group-D\">
|
||||
<abbr id=\"contacts-listed-abbr-D\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed D\">D</abbr>
|
||||
</header>
|
||||
<ol data-group=\"D\" id=\"contacts-list-D\"
|
||||
aria-labelledby=\"contacts-listed-abbr-D\" role=\"listbox\">
|
||||
<li data-cache=\"true\" data-rendered=\"true\"
|
||||
data-updated=\"1424785158782\" class=\"contact-item\"
|
||||
data-group=\"D\" role=\"option\"
|
||||
data-uuid=\"${DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\">
|
||||
<bdi><strong>Dummy</strong></bdi>
|
||||
</p>
|
||||
</li>
|
||||
</ol>`
|
||||
}]
|
||||
};
|
||||
|
||||
// Cache with contacts "Dummy", "AnotherDummy" and "YetAnotherDummy"
|
||||
const VALID_CACHE_MULTIPLE_CONTACTS = { content: [{
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-A'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-A\" class=\"\"
|
||||
id=\"group-A\">
|
||||
<abbr id=\"contacts-listed-abbr-A\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed A\">A</abbr>
|
||||
</header>
|
||||
<ol data-group=\"A\" id=\"contacts-list-A\"
|
||||
aria-labelledby=\"contacts-listed-abbr-A\" role=\"listbox\">
|
||||
<li data-cache=\"true\" data-rendered=\"true\"
|
||||
data-updated=\"1424803481298\" class=\"contact-item\"
|
||||
data-group=\"A\" role=\"option\"
|
||||
data-uuid=\"${ANOTHER_DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${ANOTHER_DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\">
|
||||
<bdi><strong>AnotherDummy</strong></bdi>
|
||||
</p>
|
||||
</li>
|
||||
</ol>`
|
||||
}, {
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-D'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-D\" class=\"\"
|
||||
id=\"group-D\">
|
||||
<abbr id=\"contacts-listed-abbr-D\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed D\">D</abbr>
|
||||
</header>
|
||||
<ol data-group=\"D\" id=\"contacts-list-D\"
|
||||
aria-labelledby=\"contacts-listed-abbr-D\" role=\"listbox\">
|
||||
<li data-cache=\"true\" data-rendered=\"true\"
|
||||
data-updated=\"1424803471199\" class=\"contact-item\"
|
||||
data-group=\"D\" role=\"option\"
|
||||
data-uuid=\"${DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\">
|
||||
<bdi><strong>Dummy</strong></bdi>
|
||||
</p>
|
||||
</li>
|
||||
</ol>`
|
||||
}, {
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-Y'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-Y\" class=\"\"
|
||||
id=\"group-Y\">
|
||||
<abbr id=\"contacts-listed-abbr-Y\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed Y\">Y</abbr>
|
||||
</header>
|
||||
<ol data-group=\"Y\" id=\"contacts-list-Y\"
|
||||
aria-labelledby=\"contacts-listed-abbr-Y\" role=\"listbox\">
|
||||
<li data-cache=\"true\" data-rendered=\"true\"
|
||||
data-updated=\"1424803496924\" class=\"contact-item\"
|
||||
data-group=\"Y\" role=\"option\"
|
||||
data-uuid=\"${YET_ANOTHER_DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${YET_ANOTHER_DUMMY_CONTACT_UUID}\"
|
||||
name=\"selectIds[]\" type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\">
|
||||
<bdi><strong>YetAnotherDummy</strong></bdi>
|
||||
</p>
|
||||
</li>
|
||||
</ol>`
|
||||
}]
|
||||
};
|
||||
|
||||
const VALID_CACHE_MULTIPLE_CONTACTS_AND_FAVORITE = { content: [{
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section hide'
|
||||
},
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-ice'
|
||||
},
|
||||
{
|
||||
'name': 'data-nonsearchable',
|
||||
'value': 'true'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<ol id=\"contact-list-ice\" data-group=\"ice\">
|
||||
<li data-visited=\"false\" data-rendered=\"false\" data-status=\"\"
|
||||
data-cache=\"true\" data-group=\"ice\" class=\"contact-item\">
|
||||
<span></span>
|
||||
<p data-l10n-id=\"ICEContactsGroup\" class=\"contact-text\">
|
||||
ICE Contacts
|
||||
</p>
|
||||
</li>
|
||||
</ol>`
|
||||
}, {
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-favorites'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
},
|
||||
{
|
||||
'name': 'data-nonsearchable',
|
||||
'value': 'true'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-favorites\" class=\"\"
|
||||
id=\"group-favorites\">
|
||||
<abbr id=\"contacts-listed-abbr-favorites\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed favorites\">
|
||||
</abbr>
|
||||
</header>
|
||||
<ol data-group=\"favorites\" id=\"contacts-list-favorites\"
|
||||
aria-labelledby=\"contacts-listed-abbr-favorites\" role=\"listbox\">
|
||||
<li data-status=\"\" data-cache=\"true\" data-visited=\"false\"
|
||||
data-order=\"DUMMY\" data-search=\"Dummy\" data-rendered=\"false\"
|
||||
data-updated=\"1426068653117\" class=\"contact-item\"
|
||||
data-group=\"favorites\" role=\"option\"
|
||||
data-uuid=\"${DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\"><bdi><strong>Dummy</strong> </bdi></p>
|
||||
</li>
|
||||
</ol>`
|
||||
}, {
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-A'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-A\" class=\"\"
|
||||
id=\"group-A\">
|
||||
<abbr id=\"contacts-listed-abbr-A\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed A\">A</abbr>
|
||||
</header>
|
||||
<ol data-group=\"A\" id=\"contacts-list-A\"
|
||||
aria-labelledby=\"contacts-listed-abbr-A\" role=\"listbox\">
|
||||
<li data-status=\"\" data-cache=\"true\" data-visited=\"false\"
|
||||
data-order=\"ANOTHERDUMMY\" data-search=\"AnotherDummy\"
|
||||
data-rendered=\"false\" data-updated=\"1426068639081\"
|
||||
class=\"contact-item\" data-group=\"A\" role=\"option\"
|
||||
data-uuid=\"${ANOTHER_DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${ANOTHER_DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\"><bdi><strong>AnotherDummy</strong> </bdi></p>
|
||||
</li>
|
||||
</ol>`
|
||||
}, {
|
||||
'elementName': 'section',
|
||||
'attributes': [
|
||||
{
|
||||
'name': 'id',
|
||||
'value': 'section-group-D'
|
||||
},
|
||||
{
|
||||
'name': 'class',
|
||||
'value': 'group-section'
|
||||
}
|
||||
],
|
||||
'innerHTML':
|
||||
`<header aria-labelledby=\"contacts-listed-abbr-D\" class=\"\"
|
||||
id=\"group-D\">
|
||||
<abbr id=\"contacts-listed-abbr-D\" aria-hidden=\"true\"
|
||||
title=\"Contacts listed D\">D</abbr>
|
||||
</header>
|
||||
<ol data-group=\"D\" id=\"contacts-list-D\"
|
||||
aria-labelledby=\"contacts-listed-abbr-D\" role=\"listbox\">
|
||||
<li data-status=\"\" data-cache=\"true\" data-visited=\"false\"
|
||||
data-order=\"DUMMY\" data-search=\"Dummy\" data-rendered=\"false\"
|
||||
data-updated=\"1426068653117\" class=\"contact-item\"
|
||||
data-group=\"D\"
|
||||
role=\"option\" data-uuid=\"${DUMMY_CONTACT_UUID}\">
|
||||
<label class=\"contact-checkbox pack-checkbox\">
|
||||
<input value=\"${DUMMY_CONTACT_UUID}\" name=\"selectIds[]\"
|
||||
type=\"checkbox\">
|
||||
<span></span>
|
||||
</label>
|
||||
<p class=\"contact-text\"><bdi><strong>Dummy</strong> </bdi></p>
|
||||
</li>
|
||||
</ol>`
|
||||
}
|
||||
]};
|
||||
|
||||
suite('Bootstrap - empty cache', function() {
|
||||
|
||||
suiteSetup(function() {
|
||||
// Make sure that the cache is empty.
|
||||
localStorage.removeItem('firstChunk');
|
||||
});
|
||||
|
||||
suite('No cache', function() {
|
||||
setup(function(done) {
|
||||
Cache.apply('firstChunk').then(done, done);
|
||||
});
|
||||
|
||||
test('Cache apply promise is rejected', function(done) {
|
||||
Cache.apply('firstChunk').then(() => {
|
||||
throw new Error('Should not resolve');
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('Cache should not be active', function() {
|
||||
assert.isFalse(Cache.active);
|
||||
});
|
||||
|
||||
test('No contact should be cached', function() {
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.equal(Cache.length, 0);
|
||||
});
|
||||
|
||||
test('No header should be cached', function() {
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Bootstrap - Valid cache, one contact', function() {
|
||||
var fakeContainer;
|
||||
|
||||
suiteSetup(function() {
|
||||
localStorage.setItem('firstChunk',
|
||||
JSON.stringify(VALID_CACHE_ONE_CONTACT));
|
||||
fakeContainer = document.createElement('div');
|
||||
fakeContainer.id = 'groups-list';
|
||||
document.body.appendChild(fakeContainer);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Cache.cleanup();
|
||||
localStorage.removeItem('firstChunk');
|
||||
document.body.removeChild(fakeContainer);
|
||||
});
|
||||
|
||||
suite('Cache with one contact', function() {
|
||||
setup(function(done) {
|
||||
Cache.apply('firstChunk').then(done);
|
||||
});
|
||||
|
||||
test('Cache should be active', function() {
|
||||
assert.isTrue(Cache.active);
|
||||
});
|
||||
|
||||
test('Contacts should be cached', function() {
|
||||
assert.isDefined(Cache.contacts);
|
||||
assert.equal(Cache.length, 1);
|
||||
assert.isTrue(Cache.hasContact(DUMMY_CONTACT_UUID));
|
||||
assert.isFalse(Cache.hasFavorite(DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Header "D" should be cached for contact "Dummy"', function() {
|
||||
assert.isDefined(Cache.headers.D);
|
||||
});
|
||||
|
||||
test('Cache content should not be kept in memory', function() {
|
||||
assert.isNull(Cache._rawContent);
|
||||
});
|
||||
|
||||
test('Getting the contact should remove it from memory', function() {
|
||||
assert.equal(Cache.length, 1);
|
||||
Cache.getContact(DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 0);
|
||||
assert.isUndefined(Cache.getContact(DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Cache content should be applied to the DOM', function() {
|
||||
var contactsListD =
|
||||
fakeContainer.querySelector('ol#contacts-list-D');
|
||||
assert.isDefined(contactsListD);
|
||||
assert.equal(contactsListD.children.length, 1);
|
||||
});
|
||||
|
||||
test('Evicting cache should remove cache from disk and memory',
|
||||
function() {
|
||||
assert.isDefined(localStorage.getItem('firstChunk'));
|
||||
Cache.oneviction = () => {
|
||||
assert.isNull(localStorage.getItem('firstChunk'));
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
};
|
||||
Cache.evict();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Bootstrap - Valid cache, multiple contacts', function() {
|
||||
var fakeContainer;
|
||||
|
||||
suiteSetup(function() {
|
||||
localStorage.setItem('firstChunk',
|
||||
JSON.stringify(VALID_CACHE_MULTIPLE_CONTACTS));
|
||||
fakeContainer = document.createElement('div');
|
||||
fakeContainer.id = 'groups-list';
|
||||
document.body.appendChild(fakeContainer);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Cache.cleanup();
|
||||
localStorage.removeItem('firstChunk');
|
||||
document.body.removeChild(fakeContainer);
|
||||
});
|
||||
|
||||
suite('Cache with multiple contacts', function() {
|
||||
setup(function(done) {
|
||||
Cache.apply('firstChunk').then(done);
|
||||
});
|
||||
|
||||
test('Cache should be active', function() {
|
||||
assert.isTrue(Cache.active);
|
||||
});
|
||||
|
||||
test('Contacts should be cached', function() {
|
||||
assert.isDefined(Cache.contacts);
|
||||
assert.equal(Cache.length, 3);
|
||||
assert.isTrue(Cache.hasContact(DUMMY_CONTACT_UUID));
|
||||
assert.isTrue(Cache.hasContact(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isTrue(Cache.hasContact(YET_ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isFalse(Cache.hasFavorite(DUMMY_CONTACT_UUID));
|
||||
assert.isFalse(Cache.hasFavorite(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isFalse(Cache.hasFavorite(YET_ANOTHER_DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Headers should be cached for contacts', function() {
|
||||
assert.isDefined(Cache.headers.D);
|
||||
assert.isDefined(Cache.headers.A);
|
||||
assert.isDefined(Cache.headers.Y);
|
||||
});
|
||||
|
||||
test('Cache content should not be kept in memory', function() {
|
||||
assert.isNull(Cache._rawContent);
|
||||
});
|
||||
|
||||
test('Getting the contact should remove it from memory', function() {
|
||||
assert.equal(Cache.length, 3);
|
||||
Cache.getContact(DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 2);
|
||||
Cache.getContact(ANOTHER_DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 1);
|
||||
Cache.getContact(YET_ANOTHER_DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 0);
|
||||
assert.isUndefined(Cache.getContact(DUMMY_CONTACT_UUID));
|
||||
assert.isUndefined(Cache.getContact(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isUndefined(Cache.getContact(YET_ANOTHER_DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Cache content should be applied to the DOM', function() {
|
||||
var contactDSection = fakeContainer.querySelector('.section-group-D');
|
||||
var contactASection = fakeContainer.querySelector('.section-group-A');
|
||||
var contactYSection = fakeContainer.querySelector('.section-group-Y');
|
||||
assert.isDefined(contactDSection);
|
||||
assert.isDefined(contactASection);
|
||||
assert.isDefined(contactYSection);
|
||||
});
|
||||
|
||||
test('Evicting cache should remove cache from disk and memory',
|
||||
function() {
|
||||
assert.isDefined(localStorage.getItem('firstChunk'));
|
||||
Cache.oneviction = () => {
|
||||
assert.isNull(localStorage.getItem('firstChunk'));
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
};
|
||||
Cache.evict();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Bootstrap - Valid cache, multiple contacts, favorites', function() {
|
||||
var fakeContainer;
|
||||
|
||||
suiteSetup(function() {
|
||||
localStorage.setItem('firstChunk',
|
||||
JSON.stringify(VALID_CACHE_MULTIPLE_CONTACTS_AND_FAVORITE));
|
||||
fakeContainer = document.createElement('div');
|
||||
fakeContainer.id = 'groups-list';
|
||||
document.body.appendChild(fakeContainer);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Cache.cleanup();
|
||||
localStorage.removeItem('firstChunk');
|
||||
document.body.removeChild(fakeContainer);
|
||||
});
|
||||
|
||||
suite('Cache with multiple contacts and favorites', function() {
|
||||
setup(function(done) {
|
||||
Cache.apply('firstChunk').then(done);
|
||||
});
|
||||
|
||||
test('Cache should be active', function() {
|
||||
assert.isTrue(Cache.active);
|
||||
});
|
||||
|
||||
test('Contacts should be cached', function() {
|
||||
assert.isDefined(Cache.contacts);
|
||||
assert.equal(Cache.length, 3);
|
||||
assert.isTrue(Cache.hasContact(DUMMY_CONTACT_UUID));
|
||||
assert.isTrue(Cache.hasContact(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isTrue(Cache.hasFavorite(DUMMY_CONTACT_UUID));
|
||||
assert.isFalse(Cache.hasFavorite(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Headers should be cached for contacts', function() {
|
||||
assert.isDefined(Cache.headers.D);
|
||||
assert.isDefined(Cache.headers.A);
|
||||
assert.isDefined(Cache.headers.favorites);
|
||||
});
|
||||
|
||||
test('Cache content should not be kept in memory', function() {
|
||||
assert.isNull(Cache._rawContent);
|
||||
});
|
||||
|
||||
test('Getting the contact should remove it from memory', function() {
|
||||
assert.equal(Cache.length, 3);
|
||||
Cache.getContact(DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 2);
|
||||
Cache.getContact(ANOTHER_DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 1);
|
||||
Cache.getFavorite(DUMMY_CONTACT_UUID);
|
||||
assert.equal(Cache.length, 0);
|
||||
assert.isUndefined(Cache.getContact(DUMMY_CONTACT_UUID));
|
||||
assert.isUndefined(Cache.getContact(ANOTHER_DUMMY_CONTACT_UUID));
|
||||
assert.isUndefined(Cache.getFavorite(DUMMY_CONTACT_UUID));
|
||||
});
|
||||
|
||||
test('Cache content should be applied to the DOM', function() {
|
||||
var contactDSection = fakeContainer.querySelector('.section-group-D');
|
||||
var contactASection = fakeContainer.querySelector('.section-group-A');
|
||||
var favoritesSection =
|
||||
fakeContainer.querySelector('.section-group-favorites');
|
||||
assert.isDefined(contactDSection);
|
||||
assert.isDefined(contactASection);
|
||||
assert.isDefined(favoritesSection);
|
||||
});
|
||||
|
||||
test('Evicting cache should remove cache from disk and memory',
|
||||
function() {
|
||||
assert.isDefined(localStorage.getItem('firstChunk'));
|
||||
Cache.oneviction = () => {
|
||||
assert.isNull(localStorage.getItem('firstChunk'));
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
};
|
||||
Cache.evict();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Bootstrap - Evict and undo cache', function() {
|
||||
var fakeContainer;
|
||||
|
||||
suiteSetup(function() {
|
||||
fakeContainer = document.createElement('div');
|
||||
fakeContainer.id = 'groups-list';
|
||||
document.body.appendChild(fakeContainer);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Cache.cleanup();
|
||||
localStorage.removeItem('firstChunk');
|
||||
document.body.removeChild(fakeContainer);
|
||||
});
|
||||
|
||||
suite('Evict and undo cache', function() {
|
||||
var alreadyDone;
|
||||
var spy;
|
||||
setup(function(done) {
|
||||
localStorage.setItem('firstChunk',
|
||||
JSON.stringify(VALID_CACHE_ONE_CONTACT));
|
||||
Cache.apply('firstChunk').then(done);
|
||||
spy = sinon.spy(window, 'setTimeout');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
spy.restore();
|
||||
});
|
||||
|
||||
test('Cache content should be applied to the DOM', function() {
|
||||
var contactsListD =
|
||||
fakeContainer.querySelector('ol#contacts-list-D');
|
||||
assert.equal(contactsListD.children.length, 1);
|
||||
});
|
||||
|
||||
test('Evicting cache should remove cache from disk and memory ' +
|
||||
'and from the DOM', function(done) {
|
||||
assert.isDefined(localStorage.getItem('firstChunk'));
|
||||
Cache.oneviction = () => {
|
||||
// We will be evicting the cache again in following tests
|
||||
// and we don't want to run this again.
|
||||
if (alreadyDone) {
|
||||
return;
|
||||
}
|
||||
assert.isNull(localStorage.getItem('firstChunk'));
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
var contactsListD =
|
||||
fakeContainer.querySelector('ol#contacts-list-D');
|
||||
assert.equal(contactsListD.children.length, 0);
|
||||
assert.isTrue(spy.called);
|
||||
alreadyDone = true;
|
||||
done();
|
||||
};
|
||||
Cache.evict(true /* undo */, false /* inmediate */);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Bootstrap - Evict cache right away', function() {
|
||||
var fakeContainer;
|
||||
|
||||
suiteSetup(function() {
|
||||
fakeContainer = document.createElement('div');
|
||||
fakeContainer.id = 'groups-list';
|
||||
document.body.appendChild(fakeContainer);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Cache.cleanup();
|
||||
localStorage.removeItem('firstChunk');
|
||||
document.body.removeChild(fakeContainer);
|
||||
});
|
||||
|
||||
suite('Evict now!', function() {
|
||||
var spy;
|
||||
setup(function(done) {
|
||||
localStorage.setItem('firstChunk',
|
||||
JSON.stringify(VALID_CACHE_ONE_CONTACT));
|
||||
Cache.apply('firstChunk').then(done);
|
||||
spy = sinon.spy(window, 'setTimeout');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
spy.restore();
|
||||
});
|
||||
|
||||
test('Cache content should be applied to the DOM', function() {
|
||||
var contactsListD =
|
||||
fakeContainer.querySelector('ol#contacts-list-D');
|
||||
assert.equal(contactsListD.children.length, 1);
|
||||
});
|
||||
|
||||
test('Evicting cache should remove cache from disk and memory ' +
|
||||
'and from the DOM', function(done) {
|
||||
assert.isDefined(localStorage.getItem('firstChunk'));
|
||||
Cache.oneviction = () => {
|
||||
assert.isNull(localStorage.getItem('firstChunk'));
|
||||
assert.isNull(Cache.contacts);
|
||||
assert.isNull(Cache.favorites);
|
||||
assert.deepEqual(Cache.headers, {});
|
||||
assert.isFalse(spy.called);
|
||||
done();
|
||||
};
|
||||
Cache.evict(false /* undo */, true /* inmediate */);
|
||||
});
|
||||
});
|
||||
});
|
||||
169
gaia/apps/communications/contacts/test/unit/cache_eviction_test.js
Executable file
169
gaia/apps/communications/contacts/test/unit/cache_eviction_test.js
Executable file
|
|
@ -0,0 +1,169 @@
|
|||
'use strict';
|
||||
|
||||
/* global Cache */
|
||||
/* global Contacts */
|
||||
/* global ICEData */
|
||||
/* global MockContactsListObj */
|
||||
/* global MocksHelper */
|
||||
/* global MockMozContacts */
|
||||
/* global MockMozL10n */
|
||||
/* global MockNavigationStack */
|
||||
/* global MockUtils */
|
||||
/* global MockLoader */
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_header_ui.js');
|
||||
requireApp('communications/contacts/test/unit/mock_activities.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_cache.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_list_obj.js');
|
||||
requireApp('communications/contacts/test/unit/mock_event_listeners.js');
|
||||
requireApp('communications/contacts/test/unit/mock_asyncstorage.js');
|
||||
requireApp('communications/contacts/test/unit/mock_loader.js');
|
||||
requireApp('communications/contacts/services/contacts.js');
|
||||
requireApp('communications/contacts/js/utilities/ice_data.js');
|
||||
require('/shared/test/unit/mocks/mock_ice_store.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
var mocksForCacheEviction = new MocksHelper([
|
||||
'ActivityHandler',
|
||||
'asyncStorage',
|
||||
'Cache',
|
||||
'Contacts',
|
||||
'ICEStore',
|
||||
'LazyLoader',
|
||||
'HeaderUI'
|
||||
]).init();
|
||||
|
||||
if (!window.navigationStack) {
|
||||
window.navigationStack = null;
|
||||
}
|
||||
if (!window.contacts) {
|
||||
window.contacts = null;
|
||||
}
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
if (!navigator.mozContacts) {
|
||||
navigator.mozContacts = null;
|
||||
}
|
||||
|
||||
suite('Contacts', function() {
|
||||
var realNavigationStack;
|
||||
var realMozL10n;
|
||||
var realContacts;
|
||||
var realUtils;
|
||||
var mockNavigation;
|
||||
var realMozContacts;
|
||||
var realLoader;
|
||||
|
||||
mocksForCacheEviction.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
mocksForCacheEviction.suiteSetup();
|
||||
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
|
||||
realContacts = window.contacts;
|
||||
window.contacts = {};
|
||||
window.contacts.List = MockContactsListObj;
|
||||
|
||||
realUtils = window.utils;
|
||||
window.utils = MockUtils;
|
||||
|
||||
realNavigationStack = window.navigationStack;
|
||||
window.navigationStack = MockNavigationStack;
|
||||
|
||||
realLoader = window.Loader;
|
||||
window.Loader = MockLoader;
|
||||
|
||||
sinon.spy(window, 'navigationStack');
|
||||
requireApp('communications/contacts/js/utilities/performance_helper.js');
|
||||
requireApp('communications/contacts/js/main_navigation.js');
|
||||
requireApp('communications/contacts/js/contacts.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realMozL10n;
|
||||
navigator.mozContacts = realMozContacts;
|
||||
|
||||
window.contacts = realContacts;
|
||||
window.utils = realUtils;
|
||||
window.loader = realLoader;
|
||||
|
||||
window.navigationStack.restore();
|
||||
window.navigationStack = realNavigationStack;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
navigator.addIdleObserver = function() {};
|
||||
|
||||
loadBodyHTML('/contacts/index.html');
|
||||
|
||||
Contacts.init();
|
||||
mockNavigation = window.navigationStack.firstCall.thisValue;
|
||||
|
||||
navigator.mozL10n.fireOnce();
|
||||
});
|
||||
|
||||
suite('oncontactchange', function() {
|
||||
var evictSpy;
|
||||
|
||||
setup(function() {
|
||||
evictSpy = sinon.spy(Cache, 'evict');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
evictSpy.restore();
|
||||
});
|
||||
|
||||
test('Should evict cache', function() {
|
||||
var evt = new CustomEvent('contactchange');
|
||||
navigator.mozContacts.dispatchEvent(evt);
|
||||
sinon.assert.calledOnce(Cache.evict);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ICE', function() {
|
||||
var evictSpy;
|
||||
|
||||
setup(function() {
|
||||
evictSpy = sinon.spy(Cache, 'evict');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
evictSpy.restore();
|
||||
});
|
||||
|
||||
test('Setting a contact as ICE should evict cache', function() {
|
||||
ICEData.setICEContact(2, 1, true).then(function() {
|
||||
sinon.assert.calledOnce(Cache.evict);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Locale change', function() {
|
||||
var maybeEvictSpy;
|
||||
|
||||
setup(function() {
|
||||
maybeEvictSpy = sinon.spy(Cache, 'maybeEvict');
|
||||
window.contacts = realContacts;
|
||||
navigator.mozL10n.fireReady();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
maybeEvictSpy.restore();
|
||||
});
|
||||
|
||||
test('Locale change should evict cache', function() {
|
||||
sinon.assert.calledOnce(Cache.maybeEvict);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
60
gaia/apps/communications/contacts/test/unit/contacts_action_menu_test.js
Executable file
60
gaia/apps/communications/contacts/test/unit/contacts_action_menu_test.js
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
/* globals ActionMenu */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
|
||||
suite('Test ActionMenu', function() {
|
||||
var fakeDOM;
|
||||
var fakeform;
|
||||
var fakeCallback;
|
||||
var real_;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
fakeDOM = document.createElement('div');
|
||||
fakeDOM.innerHTML =
|
||||
'<form id="action-menu" role="dialog" data-type="action" class="hide">' +
|
||||
'<header id="org-title" data-l10n-id="select_recipient">' +
|
||||
'Select recipient' +
|
||||
'</header>' +
|
||||
'<menu id="value-menu" type="toolbar">' +
|
||||
'</menu>' +
|
||||
'</form>';
|
||||
|
||||
document.body.appendChild(fakeDOM);
|
||||
fakeform = document.getElementById('action-menu');
|
||||
fakeCallback = function() {};
|
||||
requireApp('communications/contacts/js/action_menu.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window._ = real_;
|
||||
fakeDOM.parentNode.removeChild(fakeDOM);
|
||||
});
|
||||
|
||||
suite('Invoke function', function() {
|
||||
var actionmenu;
|
||||
setup(function() {
|
||||
actionmenu = new ActionMenu();
|
||||
});
|
||||
|
||||
test('invoke show()', function() {
|
||||
actionmenu.addToList('123456789', fakeCallback);
|
||||
actionmenu.addToList('111111111', fakeCallback);
|
||||
actionmenu.addToList('222222222', fakeCallback);
|
||||
actionmenu.show();
|
||||
var buttons = fakeDOM.querySelectorAll('button');
|
||||
assert.isFalse(fakeform.classList.contains('hide'));
|
||||
assert.equal(buttons.length, 4); // addToList + canncel
|
||||
});
|
||||
|
||||
test('invoke hide()', function() {
|
||||
actionmenu.hide();
|
||||
assert.isTrue(fakeform.classList.contains('hide'));
|
||||
assert.equal(fakeDOM.querySelectorAll('button').length, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
415
gaia/apps/communications/contacts/test/unit/contacts_activities_test.js
Executable file
415
gaia/apps/communications/contacts/test/unit/contacts_activities_test.js
Executable file
|
|
@ -0,0 +1,415 @@
|
|||
/* globals ActivityHandler, VcardActivityHandler, ConfirmDialog,
|
||||
MockContactAllFields, MocksHelper, MockMozL10n
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_contact_all_fields.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/js/contacts/import/utilities/misc.js');
|
||||
require('/shared/js/contact2vcard.js');
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/setImmediate.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_header_ui.js');
|
||||
requireApp('communications/contacts/js/activities.js');
|
||||
requireApp('communications/contacts/js/activities_vcard.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_main_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_action_menu.js');
|
||||
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_contact.js');
|
||||
|
||||
if (!window._) {
|
||||
window._ = null;
|
||||
}
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
|
||||
var mocksHelperForActivities = new MocksHelper([
|
||||
'MainNavigation',
|
||||
'Contacts',
|
||||
'ConfirmDialog',
|
||||
'LazyLoader',
|
||||
'mozContact',
|
||||
'HeaderUI'
|
||||
]).init();
|
||||
|
||||
suite('Test Activities', function() {
|
||||
var realMozL10n,
|
||||
real_,
|
||||
realImport;
|
||||
|
||||
mocksHelperForActivities.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = {};
|
||||
}
|
||||
|
||||
window.utils.overlay = {
|
||||
show: function() {},
|
||||
hide: function() {}
|
||||
};
|
||||
|
||||
window.utils.importedCount = null;
|
||||
window.utils.importedID = null;
|
||||
realImport = window.utils.importFromVcard;
|
||||
window.utils.importFromVcard = function(file, callback) {
|
||||
callback(this.importedCount, this.importedID);
|
||||
};
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realMozL10n;
|
||||
window._ = real_;
|
||||
window.utils.importFromVcard = realImport;
|
||||
});
|
||||
|
||||
function assertIsOpened(activity, viewName) {
|
||||
ActivityHandler.handle(activity);
|
||||
assert.include(document.location.hash, viewName);
|
||||
assert.equal(ActivityHandler._currentActivity, activity);
|
||||
}
|
||||
|
||||
suite('Activity launching', function() {
|
||||
setup(function() {
|
||||
ActivityHandler._currentActivity = null;
|
||||
ActivityHandler._launchedAsInlineActivity = false;
|
||||
window.utils.importedID = null;
|
||||
document.location.hash = '';
|
||||
|
||||
this.sinon.spy(ActivityHandler, 'isCancelable');
|
||||
this.sinon.spy(VcardActivityHandler, 'handle');
|
||||
});
|
||||
|
||||
test('New contact', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
name: 'new',
|
||||
data: {}
|
||||
}
|
||||
};
|
||||
assertIsOpened(activity, 'view-contact-form');
|
||||
});
|
||||
|
||||
test('Open contact calls for vcard handling', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
name: 'open',
|
||||
data: {}
|
||||
}
|
||||
};
|
||||
ActivityHandler.handle(activity);
|
||||
assert.isTrue(VcardActivityHandler.handle.called);
|
||||
});
|
||||
|
||||
test('Import contact calls for vcard handling', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
name: 'import',
|
||||
data: {
|
||||
blob: 'blob'
|
||||
}
|
||||
}
|
||||
};
|
||||
ActivityHandler.handle(activity);
|
||||
assert.isTrue(VcardActivityHandler.handle.called);
|
||||
});
|
||||
|
||||
test('Update contact', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
name: 'update',
|
||||
data: {}
|
||||
}
|
||||
};
|
||||
assertIsOpened(activity, 'add-parameters');
|
||||
assert.isTrue(ActivityHandler.isCancelable.called,
|
||||
'checks for activity UI specifics');
|
||||
});
|
||||
|
||||
test('Pick contact', function() {
|
||||
ActivityHandler._launchedAsInlineActivity = true;
|
||||
var activity = {
|
||||
source: {
|
||||
name: 'pick',
|
||||
data: {}
|
||||
}
|
||||
};
|
||||
ActivityHandler.handle(activity);
|
||||
assert.isTrue(ActivityHandler.isCancelable.called,
|
||||
'checks for activity UI specifics');
|
||||
assert.equal(ActivityHandler._currentActivity, activity);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Pick activity handling', function() {
|
||||
var activity,
|
||||
contact,
|
||||
result;
|
||||
|
||||
setup(function() {
|
||||
activity = {
|
||||
source: {
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'webcontacts/tel'
|
||||
}
|
||||
},
|
||||
postResult: function(response) {
|
||||
result = response;
|
||||
}
|
||||
};
|
||||
contact = new MockContactAllFields();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
activity = {};
|
||||
contact = {};
|
||||
result = {};
|
||||
ConfirmDialog.hide();
|
||||
});
|
||||
|
||||
test('text/vcard, 1 result', function(done) {
|
||||
var vcardActivity = {
|
||||
source: {
|
||||
name: 'pick',
|
||||
data: {
|
||||
}
|
||||
}
|
||||
};
|
||||
vcardActivity.source.data.type = 'text/vcard';
|
||||
ActivityHandler._currentActivity = vcardActivity;
|
||||
|
||||
var stub = sinon.stub(window, 'ContactToVcardBlob',
|
||||
function(aContact, cb) {
|
||||
cb(new Blob(['1234567'], {
|
||||
type: 'text/vcard'
|
||||
}));
|
||||
});
|
||||
|
||||
vcardActivity.postResult = function(response) {
|
||||
assert.equal(response.name, contact.givenName[0] + '_' +
|
||||
contact.familyName[0] + '.vcf');
|
||||
assert.equal(response.blob.type, 'text/vcard');
|
||||
|
||||
stub.restore();
|
||||
done();
|
||||
};
|
||||
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
});
|
||||
|
||||
test('webcontacts/tel, 0 results', function() {
|
||||
activity.source.data.type = 'webcontacts/tel';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel = [];
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isTrue(ConfirmDialog.showing);
|
||||
assert.isNull(ConfirmDialog.title);
|
||||
assert.equal(ConfirmDialog.text, window._('no_contact_phones'));
|
||||
});
|
||||
|
||||
test('webcontacts/tel, 1 result', function() {
|
||||
activity.source.data.type = 'webcontacts/tel';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
// We want to test only with one phone, so erase the last one
|
||||
contact.tel.pop();
|
||||
// we need to create a object from data to compare prototypes
|
||||
// check activities.js > function copyContactData
|
||||
var newContact = contact;
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
// Check if all the properties are the same
|
||||
contact = window.utils.misc.toMozContact(contact);
|
||||
for (var prop in contact) {
|
||||
if (prop === 'photo' && result[prop] && result[prop][0]) {
|
||||
assert.equal(result[prop][0].size, contact[prop][0].size);
|
||||
assert.equal(result[prop][0].type, contact[prop][0].type);
|
||||
} else {
|
||||
assert.equal(JSON.stringify(result[prop]),
|
||||
JSON.stringify(contact[prop]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('webcontacts/tel, many results', function() {
|
||||
activity.source.data.type = 'webcontacts/tel';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
// we need to create a object from data to compare prototypes
|
||||
// check activities.js > function copyContactData
|
||||
var newContact = Object.create(contact);
|
||||
sinon.stub(window.utils.misc, 'toMozContact',
|
||||
function() {return newContact;});
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
// Mock returns always the first option from the select, so we need
|
||||
// to compare to a contact with only the first phone
|
||||
|
||||
// As is filtered, we only retrieve one phone number
|
||||
assert.equal(result.tel.length, 1);
|
||||
|
||||
// As the mock of action menu is giving us the first option
|
||||
// we ensure that this option is the one filtered as well.
|
||||
assert.equal(newContact.tel[0].value, result.tel[0].value);
|
||||
// Restore the function
|
||||
window.utils.misc.toMozContact.restore();
|
||||
});
|
||||
|
||||
test('webcontacts/contact, 0 results', function() {
|
||||
activity.source.data.type = 'webcontacts/contact';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel = [];
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isTrue(ConfirmDialog.showing);
|
||||
assert.isNull(ConfirmDialog.title);
|
||||
assert.equal(ConfirmDialog.text, window._('no_contact_phones'));
|
||||
});
|
||||
|
||||
test('webcontacts/contact, 1 result', function() {
|
||||
activity.source.data.type = 'webcontacts/contact';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel.pop();
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(result.number, contact.tel[0].value);
|
||||
});
|
||||
|
||||
test('webcontacts/contact, many results', function() {
|
||||
activity.source.data.type = 'webcontacts/contact';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
// Mock returns always the first option from the select
|
||||
assert.equal(result.number, contact.tel[0].value);
|
||||
});
|
||||
|
||||
test('webcontacts/contact, returning a Contact', function() {
|
||||
activity.source.data.type = 'webcontacts/contact';
|
||||
activity.source.data.fullContact = true;
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel.pop();
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.deepEqual(result.tel, contact.tel);
|
||||
assert.deepEqual(result.email, contact.email);
|
||||
assert.equal(result.id, contact.id);
|
||||
});
|
||||
|
||||
test('webcontacts/email, 0 results', function() {
|
||||
activity.source.data.type = 'webcontacts/email';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.email = [];
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isTrue(ConfirmDialog.showing);
|
||||
assert.isNull(ConfirmDialog.title);
|
||||
assert.equal(ConfirmDialog.text, window._('no_contact_email'));
|
||||
});
|
||||
|
||||
test('webcontacts/email, 1 result', function() {
|
||||
activity.source.data.type = 'webcontacts/email';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(result.email, contact.email[0].value);
|
||||
});
|
||||
|
||||
test('webcontacts/email, many results', function() {
|
||||
activity.source.data.type = 'webcontacts/email';
|
||||
ActivityHandler._currentActivity = activity;
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
// Mock returns always the first option from the select
|
||||
assert.equal(result.email, contact.email[0].value);
|
||||
});
|
||||
|
||||
test('webcontacts/select, 0 results', function() {
|
||||
activity.source.data.type = 'webcontacts/select';
|
||||
activity.source.data.contactProperties = ['tel', 'email'];
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel = [];
|
||||
contact.email = [];
|
||||
ActivityHandler.dataPickHandler(contact);
|
||||
assert.isTrue(ConfirmDialog.showing);
|
||||
assert.isNull(ConfirmDialog.title);
|
||||
assert.equal(ConfirmDialog.text, window._('no_contact_data_available'));
|
||||
});
|
||||
|
||||
test('webcontacts/select, 1 results(tel)', function() {
|
||||
activity.source.data.type = 'webcontacts/select';
|
||||
activity.source.data.contactProperties = ['tel', 'email'];
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel.pop();
|
||||
contact.email = [];
|
||||
var newContact = Object.create(contact);
|
||||
sinon.stub(window.utils.misc, 'toMozContact',
|
||||
function() {return newContact;});
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
contact = window.utils.misc.toMozContact(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(JSON.stringify(result.select),
|
||||
JSON.stringify(contact.tel));
|
||||
assert.equal(JSON.stringify(result.contact),
|
||||
JSON.stringify(contact));
|
||||
window.utils.misc.toMozContact.restore();
|
||||
});
|
||||
|
||||
test('webcontacts/select, 1 results(email)', function() {
|
||||
activity.source.data.type = 'webcontacts/select';
|
||||
activity.source.data.contactProperties = ['tel', 'email'];
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel = [];
|
||||
contact.email.pop();
|
||||
var newContact = Object.create(contact);
|
||||
sinon.stub(window.utils.misc, 'toMozContact',
|
||||
function() {return newContact;});
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
contact = window.utils.misc.toMozContact(contact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(JSON.stringify(result.select),
|
||||
JSON.stringify(contact.email));
|
||||
assert.equal(JSON.stringify(result.contact),
|
||||
JSON.stringify(contact));
|
||||
window.utils.misc.toMozContact.restore();
|
||||
});
|
||||
|
||||
test('webcontacts/select, many results(tel)', function() {
|
||||
activity.source.data.type = 'webcontacts/select';
|
||||
activity.source.data.contactProperties = ['tel', 'email'];
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.email = [];
|
||||
var newContact = Object.create(contact);
|
||||
sinon.stub(window.utils.misc, 'toMozContact',
|
||||
function() {return newContact;});
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(newContact.tel[0].value, result.select[0].value);
|
||||
window.utils.misc.toMozContact.restore();
|
||||
});
|
||||
|
||||
test('webcontacts/select, many results(email)', function() {
|
||||
activity.source.data.type = 'webcontacts/select';
|
||||
activity.source.data.contactProperties = ['tel', 'email'];
|
||||
ActivityHandler._currentActivity = activity;
|
||||
contact.tel = [];
|
||||
var newContact = Object.create(contact);
|
||||
sinon.stub(window.utils.misc, 'toMozContact',
|
||||
function() {return newContact;});
|
||||
ActivityHandler.dataPickHandler(newContact);
|
||||
assert.isFalse(ConfirmDialog.showing);
|
||||
assert.equal(newContact.email[0].value, result.select[0].value);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
96
gaia/apps/communications/contacts/test/unit/contacts_bulk_delete_test.js
Executable file
96
gaia/apps/communications/contacts/test/unit/contacts_bulk_delete_test.js
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
/*jshint node: true, browser: true */
|
||||
/* globals MocksHelper, MockLoader, BulkDelete, ConfirmDialog */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_confirm_dialog.js');
|
||||
requireApp('communications/contacts/test/unit/mock_loader.js');
|
||||
|
||||
requireApp('communications/contacts/js/contacts_bulk_delete.js');
|
||||
|
||||
var mocksHelperForContactsBulkDelete = new MocksHelper([
|
||||
'ConfirmDialog'
|
||||
]).init();
|
||||
|
||||
/* jshint ignore:start */
|
||||
if (!this.utils) {
|
||||
this.utils = null;
|
||||
}
|
||||
/* jshint ignore:end */
|
||||
|
||||
suite('contacts_bulk_delete.js', function() {
|
||||
|
||||
var realOverlay = null;
|
||||
var realLoader = null;
|
||||
|
||||
var promise = {};
|
||||
|
||||
var confirmShowSpy, confirmHideSpy, spies;
|
||||
|
||||
mocksHelperForContactsBulkDelete.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
if (!window.utils) {
|
||||
window.utils = {};
|
||||
}
|
||||
realOverlay = window.utils.overlay;
|
||||
window.utils.overlay = {
|
||||
show: function() {}
|
||||
};
|
||||
realLoader = window.Loader;
|
||||
window.Loader = MockLoader;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.utils.overlay = realOverlay;
|
||||
window.Loader = realLoader;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
confirmShowSpy = sinon.spy(ConfirmDialog, 'show');
|
||||
confirmHideSpy = sinon.spy(ConfirmDialog, 'hide');
|
||||
spies = [confirmShowSpy, confirmHideSpy];
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
spies.forEach(function(spy) {
|
||||
spy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
function assertPerformDeleteSuccess(numberOfContacts) {
|
||||
BulkDelete.performDelete(promise);
|
||||
|
||||
promise.onsuccess({
|
||||
length: numberOfContacts
|
||||
});
|
||||
|
||||
assert.isTrue(confirmShowSpy.called);
|
||||
assert.isNull(ConfirmDialog.title);
|
||||
assert.deepEqual(ConfirmDialog.text,
|
||||
{ id: 'ContactConfirmDel', args: { n: 69 } });
|
||||
assert.equal(ConfirmDialog.noObject.title, 'cancel');
|
||||
assert.equal(ConfirmDialog.yesObject.title, 'delete');
|
||||
}
|
||||
|
||||
test('call performDelete successfully and user confirms', function(done) {
|
||||
var doDeleteStub = sinon.stub(BulkDelete, 'doDelete', function() {
|
||||
doDeleteStub.restore();
|
||||
done();
|
||||
});
|
||||
|
||||
assertPerformDeleteSuccess(69);
|
||||
// Confirmed by user
|
||||
ConfirmDialog.executeYes();
|
||||
assert.isTrue(confirmHideSpy.called);
|
||||
});
|
||||
|
||||
test('call performDelete successfully and user cancels', function() {
|
||||
assertPerformDeleteSuccess(69);
|
||||
// Cancelled by user
|
||||
ConfirmDialog.executeNo();
|
||||
assert.isTrue(confirmHideSpy.called);
|
||||
});
|
||||
});
|
||||
328
gaia/apps/communications/contacts/test/unit/contacts_buttons_test.js
Executable file
328
gaia/apps/communications/contacts/test/unit/contacts_buttons_test.js
Executable file
|
|
@ -0,0 +1,328 @@
|
|||
/* globals MocksHelper, ContactsButtons, MockL10n, MockContactAllFields,
|
||||
MockContactsButtonsDom, LazyLoader, TelephonyHelper,
|
||||
MultiSimActionButton, ActivityHandler, MockActivityHandler,
|
||||
SmsIntegration */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/contacts/contacts_buttons.js');
|
||||
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/contacts/utilities/dom.js');
|
||||
require('/shared/js/contacts/utilities/templates.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_multi_sim_action_button.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_contact_all_fields.js');
|
||||
require('/shared/test/unit/mocks/dialer/mock_telephony_helper.js');
|
||||
require('/contacts/test/unit/mock_navigation.js');
|
||||
require('/contacts/test/unit/mock_contacts.js');
|
||||
require('/contacts/test/unit/mock_contacts_buttons_dom.js.html');
|
||||
require('/contacts/test/unit/mock_utils.js');
|
||||
require('/contacts/test/unit/mock_activities.js');
|
||||
require('/contacts/test/unit/mock_sms_integration.js');
|
||||
|
||||
var mocksHelperForContactsButtons = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'ActivityHandler',
|
||||
'Contacts',
|
||||
'MultiSimActionButton',
|
||||
'TelephonyHelper',
|
||||
'SmsIntegration'
|
||||
]).init();
|
||||
|
||||
suite('Render contact', function() {
|
||||
var subject;
|
||||
|
||||
var realL10n;
|
||||
|
||||
var mockContact;
|
||||
|
||||
var container;
|
||||
var listDetails;
|
||||
|
||||
var getSpy;
|
||||
|
||||
var assertCarrierWrapperVisibility = function(visibility) {
|
||||
var carrierWrapperElt = listDetails.querySelector('.carrier-wrapper');
|
||||
assert.equal(carrierWrapperElt.hidden, !visibility);
|
||||
};
|
||||
|
||||
mocksHelperForContactsButtons.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
subject = ContactsButtons;
|
||||
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
getSpy = this.sinon.spy(MockL10n, 'get');
|
||||
|
||||
mockContact = new MockContactAllFields(true);
|
||||
|
||||
document.body.innerHTML = MockContactsButtonsDom;
|
||||
|
||||
container = document.getElementById('contact-detail');
|
||||
listDetails = document.getElementById('list-details');
|
||||
subject.init(listDetails, container, MockActivityHandler);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
suite('Render phones', function() {
|
||||
test('with 1 phone', function() {
|
||||
subject.renderPhones(mockContact);
|
||||
assert.include(container.innerHTML, 'phone-details-template-0');
|
||||
assert.include(container.innerHTML, mockContact.tel[0].value);
|
||||
assert.include(container.innerHTML, mockContact.tel[0].carrier);
|
||||
assert.include(container.innerHTML, mockContact.tel[0].type);
|
||||
assert.include(
|
||||
listDetails.querySelector('h2').innerHTML,
|
||||
mockContact.tel[0].carrier
|
||||
);
|
||||
assertCarrierWrapperVisibility(true);
|
||||
});
|
||||
|
||||
test('with 1 phone and carrier undefined', function() {
|
||||
|
||||
var contactNoCarrier = new MockContactAllFields(true);
|
||||
contactNoCarrier.tel = [
|
||||
{
|
||||
value: '+34678987123',
|
||||
type: ['Personal']
|
||||
}
|
||||
];
|
||||
subject.renderPhones(contactNoCarrier);
|
||||
var phoneButton = container.querySelector('#call-or-pick-0');
|
||||
assert.equal(phoneButton.querySelector('b').textContent,
|
||||
contactNoCarrier.tel[0].value);
|
||||
var carrierContent = listDetails.querySelector('.carrier').textContent;
|
||||
assert.lengthOf(carrierContent, 0);
|
||||
assertCarrierWrapperVisibility(false);
|
||||
|
||||
});
|
||||
|
||||
test('with no phones', function() {
|
||||
var contactWoTel = new MockContactAllFields(true);
|
||||
contactWoTel.tel = [];
|
||||
subject.renderPhones(contactWoTel);
|
||||
assert.equal(-1, listDetails.innerHTML.indexOf('phone-details-template'));
|
||||
});
|
||||
|
||||
test('with null phones', function() {
|
||||
var contactWoTel = new MockContactAllFields(true);
|
||||
contactWoTel.tel = null;
|
||||
subject.renderPhones(contactWoTel);
|
||||
assert.equal(-1, listDetails.innerHTML.indexOf('phone-details-template'));
|
||||
});
|
||||
|
||||
test('with more than 1 phone', function() {
|
||||
var contactMultTel = new MockContactAllFields(true);
|
||||
contactMultTel.tel[1] = contactMultTel.tel[0];
|
||||
for (var elem in contactMultTel.tel[1]) {
|
||||
var currentElem = contactMultTel.tel[1][elem] + 'dup';
|
||||
contactMultTel.tel[1][elem] = currentElem;
|
||||
}
|
||||
contactMultTel.tel[1].type = '';
|
||||
subject.renderPhones(contactMultTel);
|
||||
assert.include(listDetails.innerHTML, 'phone-details-template-0');
|
||||
assert.include(listDetails.innerHTML, 'phone-details-template-1');
|
||||
assert.include(listDetails.innerHTML, contactMultTel.tel[0].value);
|
||||
assert.include(listDetails.innerHTML, contactMultTel.tel[0].carrier);
|
||||
assert.include(listDetails.innerHTML, contactMultTel.tel[0].type);
|
||||
assert.include(listDetails.innerHTML, contactMultTel.tel[1].value);
|
||||
assert.include(listDetails.innerHTML, contactMultTel.tel[1].carrier);
|
||||
assert.include(listDetails.innerHTML, subject.DEFAULT_TEL_TYPE);
|
||||
assert.equal(
|
||||
-1, listDetails.innerHTML.indexOf('phone-details-template-2'));
|
||||
assertCarrierWrapperVisibility(true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Render emails', function() {
|
||||
test('with 1 email', function() {
|
||||
subject.renderEmails(mockContact);
|
||||
assert.include(listDetails.innerHTML, 'email-details-template-0');
|
||||
assert.include(listDetails.innerHTML, mockContact.email[0].value);
|
||||
assert.include(listDetails.innerHTML, mockContact.email[0].type);
|
||||
});
|
||||
|
||||
test('with no emails', function() {
|
||||
var contactWoEmail = new MockContactAllFields(true);
|
||||
contactWoEmail.email = [];
|
||||
subject.renderEmails(contactWoEmail);
|
||||
assert.equal(-1, listDetails.innerHTML.indexOf('email-details-template'));
|
||||
});
|
||||
|
||||
test('with null emails', function() {
|
||||
var contactWoEmail = new MockContactAllFields(true);
|
||||
contactWoEmail.email = null;
|
||||
subject.renderEmails(contactWoEmail);
|
||||
assert.equal(-1, listDetails.innerHTML.indexOf('email-details-template'));
|
||||
});
|
||||
|
||||
test('with more than 1 email', function() {
|
||||
var contactMultEmail = new MockContactAllFields(true);
|
||||
contactMultEmail.email[1] = contactMultEmail.email[0];
|
||||
for (var elem in contactMultEmail.email[1]) {
|
||||
var currentElem = contactMultEmail.email[1][elem] + 'dup';
|
||||
contactMultEmail.email[1][elem] = currentElem;
|
||||
}
|
||||
subject.renderEmails(contactMultEmail);
|
||||
assert.include(container.innerHTML, 'email-details-template-0');
|
||||
assert.include(container.innerHTML, 'email-details-template-1');
|
||||
var email0 = contactMultEmail.email[0];
|
||||
var email1 = contactMultEmail.email[1];
|
||||
assert.include(listDetails.innerHTML, email0.value);
|
||||
assert.include(listDetails.innerHTML, email0.type);
|
||||
assert.include(listDetails.innerHTML, email1.value);
|
||||
assert.include(listDetails.innerHTML, email1.type);
|
||||
assert.equal(
|
||||
-1, listDetails.innerHTML.indexOf('email-details-template-2'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('> Send sms', function() {
|
||||
var evt = {};
|
||||
evt.target.dataset.target = '+445312973212';
|
||||
setup(function() {
|
||||
this.sinon.spy(SmsIntegration, 'sendSms');
|
||||
});
|
||||
|
||||
test('> send sms', function() {
|
||||
subject._onSendSmsClicked(evt);
|
||||
|
||||
sinon.assert.calledWith(SmsIntegration.sendSms, evt);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> User actions', function() {
|
||||
var realMozTelephony;
|
||||
var realMozMobileConnections;
|
||||
suiteSetup(function() {
|
||||
realMozTelephony = navigator.mozTelephony;
|
||||
realMozMobileConnections = navigator.mozMobileConnections;
|
||||
navigator.mozTelephony = true;
|
||||
navigator.mozMobileConnections = [true];
|
||||
sinon.spy(window, 'MultiSimActionButton');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozTelephony = realMozTelephony;
|
||||
navigator.mozMobileConnections = realMozMobileConnections;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(LazyLoader, 'load');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
LazyLoader.load.reset();
|
||||
});
|
||||
|
||||
function makeCall(cb) {
|
||||
var theContact = new MockContactAllFields(true);
|
||||
subject.renderPhones(theContact);
|
||||
|
||||
var stubCall = sinon.stub(TelephonyHelper, 'call', cb);
|
||||
MultiSimActionButton.args[0][1]();
|
||||
stubCall.restore();
|
||||
}
|
||||
|
||||
test('> Not loading MultiSimActionButton when we are on an activity',
|
||||
function() {
|
||||
ActivityHandler.currentlyHandling = true;
|
||||
subject.renderPhones(mockContact);
|
||||
|
||||
sinon.assert.neverCalledWith(LazyLoader.load,
|
||||
['/shared/js/multi_sim_action_button.js']);
|
||||
ActivityHandler.currentlyHandling = false;
|
||||
});
|
||||
|
||||
test('> Not loading MultiSimActionButton if we have a MMI code',
|
||||
function() {
|
||||
this.sinon.stub(subject, '_isMMI').returns(true);
|
||||
|
||||
subject.renderPhones(mockContact);
|
||||
|
||||
sinon.assert.neverCalledWith(LazyLoader.load,
|
||||
['/shared/js/multi_sim_action_button.js']);
|
||||
});
|
||||
|
||||
test('> Load call button', function() {
|
||||
subject.renderPhones(mockContact);
|
||||
|
||||
// We have two buttons, one call per button created plus webrtc
|
||||
// client call
|
||||
// XXX: Should we include webrtc?
|
||||
//assert.equal(LazyLoader.load.callCount, 5);
|
||||
assert.equal(LazyLoader.load.callCount, 2);
|
||||
var spyCall = LazyLoader.load.getCall(1);
|
||||
assert.deepEqual(
|
||||
['/shared/js/multi_sim_action_button.js'], spyCall.args[0]);
|
||||
});
|
||||
|
||||
test('> Multiple MultiSimActionButtons initialized with correct values',
|
||||
function() {
|
||||
var theContact = new MockContactAllFields(true);
|
||||
subject.renderPhones(theContact);
|
||||
|
||||
var phone1 = container.querySelector('#call-or-pick-0');
|
||||
var phone2 = container.querySelector('#call-or-pick-1');
|
||||
var phoneNumber1 = theContact.tel[0].value;
|
||||
var phoneNumber2 = theContact.tel[1].value;
|
||||
|
||||
sinon.assert.calledWith(MultiSimActionButton, phone1,
|
||||
sinon.match.func, 'ril.telephony.defaultServiceId',
|
||||
sinon.match.func);
|
||||
// Check the getter contains the correct phone number
|
||||
var getterResult = MultiSimActionButton.args[0][3]();
|
||||
assert.equal(phoneNumber1, getterResult);
|
||||
|
||||
sinon.assert.calledWith(MultiSimActionButton, phone2,
|
||||
sinon.match.func, 'ril.telephony.defaultServiceId',
|
||||
sinon.match.func);
|
||||
// Second call getter result
|
||||
getterResult = MultiSimActionButton.args[1][3]();
|
||||
assert.equal(phoneNumber2, getterResult);
|
||||
|
||||
});
|
||||
|
||||
test('> Calling and oncall ', function() {
|
||||
makeCall(function(num, cIndex, oncall, connected, disconnected, error) {
|
||||
assert.isTrue(container.classList.contains('calls-disabled'));
|
||||
oncall();
|
||||
assert.isFalse(container.classList.contains('calls-disabled'));
|
||||
});
|
||||
});
|
||||
|
||||
test('> Calling and connected ', function() {
|
||||
makeCall(function(num, cIndex, oncall, connected, disconnected, error) {
|
||||
assert.isTrue(container.classList.contains('calls-disabled'));
|
||||
connected();
|
||||
assert.isFalse(container.classList.contains('calls-disabled'));
|
||||
});
|
||||
});
|
||||
|
||||
test('> Calling and disconnected ', function() {
|
||||
makeCall(function(num, cIndex, oncall, connected, disconnected, error) {
|
||||
assert.isTrue(container.classList.contains('calls-disabled'));
|
||||
disconnected();
|
||||
assert.isFalse(container.classList.contains('calls-disabled'));
|
||||
});
|
||||
});
|
||||
|
||||
test('> Calling and error ', function() {
|
||||
makeCall(function(num, cIndex, oncall, connected, disconnected, error) {
|
||||
assert.isTrue(container.classList.contains('calls-disabled'));
|
||||
error();
|
||||
assert.isFalse(container.classList.contains('calls-disabled'));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
936
gaia/apps/communications/contacts/test/unit/contacts_matcher_test.js
Executable file
936
gaia/apps/communications/contacts/test/unit/contacts_matcher_test.js
Executable file
|
|
@ -0,0 +1,936 @@
|
|||
'use strict';
|
||||
/* global contactFB:true */
|
||||
/* global MockFindMatcher */
|
||||
/* global Matcher */
|
||||
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/simple_phone_matcher.js');
|
||||
require('/shared/js/contacts/contacts_matcher.js');
|
||||
requireApp('communications/contacts/test/unit/mock_find_matcher.js');
|
||||
|
||||
|
||||
var realmozContacts,
|
||||
contact;
|
||||
|
||||
|
||||
if (!window.realmozContacts) {
|
||||
window.realmozContacts = null;
|
||||
}
|
||||
|
||||
if (!window.contact) {
|
||||
window.contact = null;
|
||||
}
|
||||
|
||||
if (!window.contactFB) {
|
||||
window.contactFB = null;
|
||||
}
|
||||
|
||||
if (!window.SimplePhoneMatcher) {
|
||||
window.SimplePhoneMatcher = null;
|
||||
}
|
||||
|
||||
suite('Test Contacts Matcher', function() {
|
||||
function assertDefaultMatch(results, matchingFields, telValue) {
|
||||
assert.equal(Object.keys(results).length, 1);
|
||||
assert.equal(Object.keys(results)[0], '1B');
|
||||
var matchingContact = results['1B'].matchingContact;
|
||||
if (Array.isArray(matchingContact.email) && matchingContact.email[0]) {
|
||||
assert.equal(matchingContact.email[0].value, 'jj@jj.com');
|
||||
}
|
||||
if (Array.isArray(matchingContact.tel) && matchingContact.tel[0]) {
|
||||
assert.equal(matchingContact.tel[0].value, telValue || '676767671');
|
||||
}
|
||||
|
||||
if (matchingFields) {
|
||||
matchingFields.forEach(function(matchingField) {
|
||||
if (typeof matchingField === 'string') {
|
||||
assert.isDefined(results['1B'].matchings[matchingField]);
|
||||
}
|
||||
else if (matchingField && typeof matchingField === 'object') {
|
||||
var matchArr = results['1B'].matchings[matchingField.field];
|
||||
assert.isDefined(matchArr);
|
||||
assert.lengthOf(matchArr, matchingField.times);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function testMatch(myObj, mode, matchingFields, done, telValue) {
|
||||
var cbs = {
|
||||
onmatch: function(results) {
|
||||
assertDefaultMatch(results, matchingFields, telValue);
|
||||
done();
|
||||
},
|
||||
onmismatch: function() {
|
||||
assert.fail(cbs.onmatch, cbs.onmismatch, 'No contacts matches found!!');
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
Matcher.match(myObj, mode, cbs);
|
||||
}
|
||||
|
||||
function testMismatch(myObj, mode, done) {
|
||||
var cbs = {
|
||||
onmatch: function(results) {
|
||||
assert.fail(cbs.onmismatch, cbs.onmatch, 'Matching found!!');
|
||||
done();
|
||||
},
|
||||
onmismatch: function() {
|
||||
assert.ok(true, 'Mismatch callback invoked');
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
Matcher.match(myObj, mode, cbs);
|
||||
}
|
||||
|
||||
function setupSuite() {
|
||||
contact = {
|
||||
id: '1B',
|
||||
givenName: ['Carlos'],
|
||||
familyName: ['Álvarez del Río'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(contact);
|
||||
|
||||
realmozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockFindMatcher;
|
||||
Matcher.dataProvider = navigator.mozContacts;
|
||||
}
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozContacts = realmozContacts;
|
||||
});
|
||||
|
||||
suite('Test Contacts Matcher. PassiveMode', function() {
|
||||
suiteSetup(setupSuite);
|
||||
|
||||
test('Matching by name and phone number', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
|
||||
testMatch(myObj, 'passive', null, done);
|
||||
});
|
||||
|
||||
test('Matching by name and phone number. Accents', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.familyName = ['Alvarez delrio'];
|
||||
|
||||
testMatch(myObj, 'passive', null, done);
|
||||
});
|
||||
|
||||
test('Matching by name and phone number. International number incoming',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.tel = [{
|
||||
type: contact.tel[0].type,
|
||||
value: '+34' + contact.tel[0].value
|
||||
}];
|
||||
myObj.email = [];
|
||||
myObj.familyName = ['Alvarez delrio'];
|
||||
|
||||
testMatch(myObj, 'passive', null, done);
|
||||
});
|
||||
|
||||
test('Matching by name and phone number. International number existing',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
var savedContactTel = contact.tel;
|
||||
contact.tel = [{
|
||||
type: ['mobile'],
|
||||
value: '+34' + savedContactTel[0].value
|
||||
}];
|
||||
myObj.id = '1A';
|
||||
myObj.tel = [{
|
||||
type: savedContactTel[0].type,
|
||||
value: savedContactTel[0].value
|
||||
}];
|
||||
myObj.email = [];
|
||||
myObj.familyName = ['Alvarez delrio'];
|
||||
|
||||
testMatch(myObj, 'passive', null, function() {
|
||||
contact.tel = savedContactTel;
|
||||
done();
|
||||
}, contact.tel[0].value);
|
||||
});
|
||||
|
||||
test('Matching by name and phone number. Name defined in the name prop',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.familyName = [];
|
||||
myObj.givenName = ['Carlos Alvarez del Río'];
|
||||
myObj.name = ['Carlos Alvarez del Río'];
|
||||
|
||||
var saveGN = contact.givenName;
|
||||
var saveFN = contact.familyName;
|
||||
contact.givenName = ['Carlos Alvarez del Río'];
|
||||
contact.familyName = [' '];
|
||||
contact.name = ['Carlos Álvarez del rio'];
|
||||
|
||||
testMatch(myObj, 'passive', null, function() {
|
||||
contact.givenName = saveGN;
|
||||
contact.familyName = saveFN;
|
||||
contact.name = null;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Matching by name and e-mail', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.tel = null;
|
||||
|
||||
testMatch(myObj, 'passive', null, done);
|
||||
});
|
||||
|
||||
test('Matching by name, e-mail and phone number', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
testMatch(myObj, 'passive', null, done);
|
||||
});
|
||||
|
||||
test('Phone number matches but name does not match', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.givenName = ['Adolfo'];
|
||||
myObj.email = null;
|
||||
|
||||
testMismatch(myObj, 'passive', done);
|
||||
});
|
||||
|
||||
test('e-mail matches but name does not match', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.givenName = ['Adolfo'];
|
||||
myObj.tel = [];
|
||||
|
||||
testMismatch(myObj, 'passive', done);
|
||||
});
|
||||
|
||||
test('Name matches, e-mail matches but phone number does not match',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.tel = [{
|
||||
type: ['mobile'],
|
||||
value: '98645678'
|
||||
}];
|
||||
|
||||
testMismatch(myObj, 'passive', done);
|
||||
});
|
||||
|
||||
test('Name matches, phone number matches but e-mail does not match',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [{
|
||||
type: ['personal'],
|
||||
value: 'kk@kk.com'
|
||||
}];
|
||||
|
||||
testMismatch(myObj, 'passive', done);
|
||||
});
|
||||
|
||||
test('First name is null only in incoming, lastName matches. Then mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'abcde';
|
||||
myObj.givenName = [];
|
||||
|
||||
testMismatch(myObj, 'passive', done);
|
||||
});
|
||||
|
||||
test('First name is null only in existing contact. Then mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'wvy';
|
||||
myObj.givenName = ['Carlos'];
|
||||
|
||||
var saveGN = contact.givenName;
|
||||
contact.givenName = null;
|
||||
|
||||
testMismatch(myObj, 'passive', function() {
|
||||
contact.givenName = saveGN;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('First name is null, in both. LastName matches. Then match',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
|
||||
myObj.id = 'zx1';
|
||||
|
||||
myObj.givenName = [];
|
||||
var saveGN = contact.givenName;
|
||||
contact.givenName = [];
|
||||
|
||||
testMatch(myObj, 'passive', null, function() {
|
||||
contact.givenName = saveGN;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Last name is null, in both. First name matches. Then match',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'zx1';
|
||||
|
||||
myObj.familyName = [];
|
||||
var saveFN = contact.familyName;
|
||||
contact.familyName = [];
|
||||
|
||||
testMatch(myObj, 'passive', null, function() {
|
||||
contact.familyName = saveFN;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Match by name and phone number when existing contact is FB Linked',
|
||||
function(done) {
|
||||
var linkedContact = {
|
||||
id: '1B',
|
||||
category: ['facebook', 'fb_linked', '678910'],
|
||||
givenName: ['Jose'],
|
||||
familyName: ['Mota'],
|
||||
name: ['Jose Mota'],
|
||||
tel: [
|
||||
{
|
||||
type: ['mobile'],
|
||||
value: '676767671'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var incomingContact = {
|
||||
id: 'kjh987',
|
||||
category: ['gmail'],
|
||||
givenName: linkedContact.givenName,
|
||||
familyName: linkedContact.familyName,
|
||||
name: linkedContact.name,
|
||||
tel: [
|
||||
{
|
||||
type: ['mobile'],
|
||||
value: '676767671'
|
||||
},
|
||||
{
|
||||
type: ['personal'],
|
||||
value: '983456789'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(linkedContact);
|
||||
testMatch(incomingContact, 'passive', null, function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('SIM Contacts Matching', function() {
|
||||
var existingSimContact = {
|
||||
id: '1B',
|
||||
category: ['sim'],
|
||||
name: ['Juan Ramón del SIM'],
|
||||
givenName: ['Juan Ramón del SIM'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
var incomingSimContact = {
|
||||
id: '678',
|
||||
category: ['sim'],
|
||||
givenName: ['Juan Ramon'],
|
||||
familyName: ['del SIM'],
|
||||
name: ['Juan Ramón del SIM'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}]
|
||||
};
|
||||
|
||||
test('Incoming SIM Contact matches with a normal contact',
|
||||
function(done) {
|
||||
MockFindMatcher.setData(existingSimContact);
|
||||
|
||||
testMatch(incomingSimContact, 'passive', null, function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Incoming Contact matches with an existing SIM contact',
|
||||
function(done) {
|
||||
MockFindMatcher.setData(existingSimContact);
|
||||
|
||||
testMatch(incomingSimContact, 'passive', null, function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('SIM Contact. Matching by name and SIM url', function(done) {
|
||||
var existing = Object.create(existingSimContact);
|
||||
existing.givenName = ['Álvaro'];
|
||||
existing.familyName = ['Fummetta'];
|
||||
existing.name = ['Álvaro Fummetta'];
|
||||
existing.url = [
|
||||
{
|
||||
type: ['sim', 'source'],
|
||||
value: '12345-6789'
|
||||
}
|
||||
];
|
||||
// Avoiding matching by other criteria
|
||||
existing.tel = null;
|
||||
existing.email = null;
|
||||
|
||||
var incoming = Object.create(incomingSimContact);
|
||||
incoming.url = existing.url;
|
||||
incoming.name = existing.name;
|
||||
incoming.givenName = existing.givenName;
|
||||
incoming.familyName = existing.familyName;
|
||||
|
||||
MockFindMatcher.setData(existing);
|
||||
|
||||
testMatch(incoming, 'passive', null, function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
}); // Test
|
||||
|
||||
test('SIM Contact. Matching by name but SIM url different',
|
||||
function(done) {
|
||||
var existing = Object.create(existingSimContact);
|
||||
existing.url = [
|
||||
{
|
||||
type: ['sim', 'source'],
|
||||
value: '12345-6789'
|
||||
}
|
||||
];
|
||||
// Avoiding matching by other criteria
|
||||
existing.tel = null;
|
||||
existing.email = null;
|
||||
|
||||
var incoming = Object.create(incomingSimContact);
|
||||
incoming.url = [
|
||||
{
|
||||
type: ['sim', 'source'],
|
||||
value: '6666-9999'
|
||||
}
|
||||
];
|
||||
incoming.name = existing.name;
|
||||
incoming.givenName = existing.givenName;
|
||||
incoming.familyName = existing.familyName;
|
||||
|
||||
|
||||
MockFindMatcher.setData(existing);
|
||||
|
||||
testMismatch(incoming, 'passive', function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('SIM Contact. Multiple names matching. Only one by SIM url',
|
||||
function(done) {
|
||||
var existing1 = Object.create(existingSimContact);
|
||||
existing1.url = [
|
||||
{
|
||||
type: ['sim', 'source'],
|
||||
value: '12345-6789'
|
||||
}
|
||||
];
|
||||
// Avoiding matching by other criteria
|
||||
existing1.tel = null;
|
||||
existing1.email = null;
|
||||
|
||||
var incoming = Object.create(incomingSimContact);
|
||||
incoming.url = [
|
||||
{
|
||||
type: ['sim', 'source'],
|
||||
value: '6666-9999'
|
||||
}
|
||||
];
|
||||
incoming.name = existing1.name;
|
||||
incoming.givenName = existing1.givenName;
|
||||
incoming.familyName = existing1.familyName;
|
||||
|
||||
var existing2 = Object.create(incoming);
|
||||
existing2.id = 'vtrew12';
|
||||
|
||||
MockFindMatcher.setData(null);
|
||||
MockFindMatcher.setFoundData([existing1, existing2]);
|
||||
|
||||
var callbacks = {
|
||||
onmatch: function(results) {
|
||||
var resultList = Object.keys(results);
|
||||
assert.equal(resultList.length, 1);
|
||||
assert.equal(results[resultList[0]].matchingContact.id,
|
||||
existing2.id);
|
||||
MockFindMatcher.setData(contact);
|
||||
MockFindMatcher.setFoundData(null);
|
||||
done();
|
||||
},
|
||||
onmismatch: function() {
|
||||
done('error');
|
||||
}
|
||||
};
|
||||
Matcher.match(incoming, 'passive', callbacks);
|
||||
}); // Test
|
||||
}); // SIM Suite
|
||||
}); // Passive Merge Suite
|
||||
|
||||
suite('Test Contacts Matcher. Active Mode', function() {
|
||||
suiteSetup(setupSuite);
|
||||
|
||||
test('Matching by name', function(done) {
|
||||
var existingContact = {
|
||||
id: '1B',
|
||||
givenName: ['Jander'],
|
||||
familyName: ['Klander'],
|
||||
name: ['Jander Klander']
|
||||
};
|
||||
|
||||
var updatedContact = {
|
||||
id: '1B',
|
||||
givenName: ['Jander'],
|
||||
familyName: ['Klander'],
|
||||
name: ['Jander Klander'],
|
||||
org: ['Company']
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(existingContact);
|
||||
|
||||
testMismatch(updatedContact, 'active', function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Matching by phone', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
myObj.givenName = [];
|
||||
myObj.familyName = null;
|
||||
|
||||
testMatch(myObj, 'active', ['tel'], done);
|
||||
});
|
||||
|
||||
test('Matching by phone internationalized number', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
myObj.givenName = [];
|
||||
myObj.familyName = null;
|
||||
myObj.tel = [];
|
||||
myObj.tel[0] = {
|
||||
type: ['mobile'],
|
||||
value: '+34' + contact.tel[0].value
|
||||
};
|
||||
|
||||
testMatch(myObj, 'active', ['tel'], done);
|
||||
});
|
||||
|
||||
test('Matching by phone internationalized number existing', function(done) {
|
||||
var savedTel = contact.tel;
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
myObj.givenName = [];
|
||||
myObj.familyName = null;
|
||||
myObj.tel = [];
|
||||
myObj.tel[0] = {
|
||||
type: ['mobile'],
|
||||
value: savedTel[0].value
|
||||
};
|
||||
contact.tel = [{
|
||||
type: savedTel[0].type,
|
||||
value: '0034' + savedTel[0].value
|
||||
}];
|
||||
|
||||
testMatch(myObj, 'active', ['tel'], function() {
|
||||
contact.tel = savedTel;
|
||||
done();
|
||||
}, contact.tel[0].value);
|
||||
});
|
||||
|
||||
|
||||
test('Matching by multiple phones', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
var savedTel = contact.tel;
|
||||
contact.tel = [
|
||||
savedTel[0],
|
||||
{
|
||||
type: ['home'],
|
||||
value: '67890123'
|
||||
}
|
||||
];
|
||||
myObj.givenName = [];
|
||||
myObj.familyName = null;
|
||||
|
||||
testMatch(myObj, 'active', [{field: 'tel', times: 2}], function() {
|
||||
contact.tel = savedTel;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Matching by email', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.tel = [{
|
||||
type: ['personal'],
|
||||
value: '9999999'
|
||||
}];
|
||||
myObj.givenName = ['Lucas'];
|
||||
myObj.familyName = ['Petrov'];
|
||||
|
||||
testMatch(myObj, 'active', ['email'], done);
|
||||
});
|
||||
|
||||
test('Matching by multiple emails', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
var savedEmail = contact.email;
|
||||
|
||||
contact.email = [
|
||||
savedEmail[0],
|
||||
{
|
||||
type: ['work'],
|
||||
value: 'k1zq@example.com'
|
||||
}];
|
||||
|
||||
myObj.givenName = [];
|
||||
myObj.familyName = null;
|
||||
|
||||
testMatch(myObj, 'active', [{field: 'email', times: 2}], function() {
|
||||
contact.email = savedEmail;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Matching by phone and email', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.givenName = [' '];
|
||||
myObj.familyName = [' '];
|
||||
|
||||
testMatch(myObj, 'active', ['tel', 'email'], done);
|
||||
});
|
||||
|
||||
test('Matching by name', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.tel = [{
|
||||
type: ['personal'],
|
||||
value: '9999999'
|
||||
}];
|
||||
|
||||
testMatch(myObj, 'active', ['name'], done);
|
||||
});
|
||||
|
||||
test('SIM Contact. Name is totally empty and there is tel. No matches',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.name = myObj.givenName = myObj.familyName = [];
|
||||
myObj.category = ['sim'];
|
||||
myObj.tel = [{
|
||||
type: ['personal'],
|
||||
value: '9999999'
|
||||
}];
|
||||
myObj.email = null;
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
|
||||
test('Regular Contact. Name is totally empty and there is tel. No matches',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.name = myObj.givenName = myObj.familyName = [];
|
||||
myObj.category = null;
|
||||
myObj.tel = [{
|
||||
type: ['personal'],
|
||||
value: '9999999'
|
||||
}];
|
||||
myObj.email = null;
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
|
||||
|
||||
test('Matching by phone, email and name', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
|
||||
testMatch(myObj, 'active', ['tel', 'email', 'name'], done);
|
||||
});
|
||||
|
||||
test('Matching by name. givenName startsWith', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.tel = null;
|
||||
myObj.givenName = ['Carlos Ángel'];
|
||||
|
||||
testMatch(myObj, 'active', ['name'], done);
|
||||
});
|
||||
|
||||
test('familyName matches but givenName not. Mismatch', function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.tel = null;
|
||||
myObj.givenName = ['David'];
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
|
||||
test('familyName of incoming is empty. GivenName matches. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.tel = null;
|
||||
myObj.familyName = null;
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
|
||||
test('givenName of incoming is empty. familyName matches. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = '1A';
|
||||
myObj.email = [];
|
||||
myObj.tel = null;
|
||||
myObj.givenName = null;
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
|
||||
test('family Name of existing is empty. givenName Matches. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'zxy';
|
||||
myObj.email = null;
|
||||
myObj.tel = null;
|
||||
myObj.familyName = contact.familyName;
|
||||
|
||||
contact.familyName = [];
|
||||
|
||||
testMismatch(myObj, 'active', function() {
|
||||
contact.familyName = myObj.familyName;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('given Name of existing is empty. family Name Matches. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'zxy';
|
||||
myObj.email = null;
|
||||
myObj.tel = null;
|
||||
myObj.givenName = contact.givenName;
|
||||
|
||||
contact.givenName = null;
|
||||
|
||||
testMismatch(myObj, 'active', function() {
|
||||
contact.givenName = myObj.givenName;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Both familyNames are empty. Given names match. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'zxy';
|
||||
myObj.email = null;
|
||||
myObj.tel = null;
|
||||
var saveFN = contact.familyName;
|
||||
myObj.familyName = contact.familyName = [null];
|
||||
|
||||
testMismatch(myObj, 'active', function() {
|
||||
contact.familyName = saveFN;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Both givenNames are empty. Family names match. Mismatch',
|
||||
function(done) {
|
||||
var myObj = Object.create(contact);
|
||||
myObj.id = 'zxy';
|
||||
myObj.email = null;
|
||||
myObj.tel = null;
|
||||
var saveGN = contact.givenName;
|
||||
myObj.givenName = contact.givenName = [''];
|
||||
|
||||
testMismatch(myObj, 'active', function() {
|
||||
contact.givenName = saveGN;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Incoming SIM Contact matches with a normal contact', function(done) {
|
||||
var simObj = {
|
||||
id: '678',
|
||||
category: ['sim'],
|
||||
name: ['Juan Ramón del SIM'],
|
||||
givenName: ['Juan Ramón del SIM']
|
||||
};
|
||||
|
||||
var existingContact = {
|
||||
id: '1B',
|
||||
givenName: ['Juan Ramon'],
|
||||
familyName: ['del SIM'],
|
||||
name: ['Juan Ramón del SIM'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(existingContact);
|
||||
|
||||
testMatch(simObj, 'active', ['name'], function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Incoming Contact matches with an existing SIM contact',
|
||||
function(done) {
|
||||
var existingSimContact = {
|
||||
id: '1B',
|
||||
category: ['sim'],
|
||||
name: ['Juan Ramón del SIM'],
|
||||
givenName: ['Juan Ramón del SIM'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
var incomingContact = {
|
||||
id: '678',
|
||||
givenName: ['Juan Ramon'],
|
||||
familyName: ['del SIM'],
|
||||
name: ['Juan Ramón del SIM']
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(existingSimContact);
|
||||
|
||||
testMatch(incomingContact, 'active', ['name'], function() {
|
||||
MockFindMatcher.setData(contact);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('No matches at all', function(done) {
|
||||
var myObj = {
|
||||
id: '1A',
|
||||
email: [{}],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '8888888'
|
||||
}],
|
||||
givenName: null,
|
||||
familyName: []
|
||||
};
|
||||
|
||||
testMismatch(myObj, 'active', done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Test Contacts Matcher. Active Mode. Facebook Contacts', function() {
|
||||
suiteSetup(function() {
|
||||
contactFB = {
|
||||
id: '1B',
|
||||
givenName: ['Carlos'],
|
||||
familyName: ['Álvarez del Río'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '676767671'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}],
|
||||
category: ['facebook']
|
||||
};
|
||||
|
||||
MockFindMatcher.setData(contactFB);
|
||||
|
||||
realmozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockFindMatcher;
|
||||
});
|
||||
|
||||
test('A Facebook Imported Contact never matches', function(done) {
|
||||
var contactObj = Object.create(contact);
|
||||
contactObj.id = '9876';
|
||||
contactObj.category = null;
|
||||
|
||||
testMismatch(contactObj, 'active', done);
|
||||
});
|
||||
|
||||
test('A Facebook linked Contact can match', function(done) {
|
||||
var contactObj = Object.create(contactFB);
|
||||
contactObj.id = '9876';
|
||||
contactFB.category = ['facebook', 'fb_linked', '123456789'];
|
||||
contactObj.category = [];
|
||||
|
||||
testMatch(contactObj, 'active', ['tel', 'email'], done);
|
||||
});
|
||||
|
||||
test('Two FB linked Contacts can match if they link the same Friend',
|
||||
function(done) {
|
||||
var contactObj = Object.create(contactFB);
|
||||
contactObj.id = '9876';
|
||||
|
||||
testMatch(contactObj, 'active', ['tel', 'email'], done);
|
||||
});
|
||||
|
||||
test('A FB linked Contact cannot match with a Contact linked to another',
|
||||
function(done) {
|
||||
var contactObj = Object.create(contactFB);
|
||||
contactObj.id = 'xc9876';
|
||||
contactObj.category = ['facebook', 'fb_linked', '987654321'];
|
||||
|
||||
testMismatch(contactObj, 'active', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
138
gaia/apps/communications/contacts/test/unit/contacts_matching_ui_test_data.js
Executable file
138
gaia/apps/communications/contacts/test/unit/contacts_matching_ui_test_data.js
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
'use strict';
|
||||
/* exported dupContacts */
|
||||
/* exported matchingDetailsData */
|
||||
|
||||
var CORRECT_MATCHED_VALUE = '$correct$';
|
||||
|
||||
var dataImage = 'data:image/gif;base64,R0lGODlhyAAiALM...DfD0QAADs=';
|
||||
|
||||
var dupContacts = {
|
||||
'1a': {
|
||||
matchingContact: {
|
||||
id: '1a',
|
||||
givenName: ['Manolo'],
|
||||
familyName: ['García'],
|
||||
photo: [dataImage],
|
||||
email: [{
|
||||
value: 'man@tid.es'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'name': [{
|
||||
target: 'Manolo',
|
||||
matchedValue: CORRECT_MATCHED_VALUE
|
||||
}]
|
||||
}
|
||||
},
|
||||
'2b': {
|
||||
matchingContact: {
|
||||
id: '2b',
|
||||
givenName: ['Manolo'],
|
||||
familyName: ['García'],
|
||||
photo: [dataImage],
|
||||
email: [{
|
||||
value: 'man@tid.es'
|
||||
}, {
|
||||
value: 'man@telefonica.es'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'name': [{
|
||||
target: 'Manolo',
|
||||
matchedValue: 'Manolo Garcia'
|
||||
}],
|
||||
'email': [{
|
||||
target: 'man@tid.es',
|
||||
matchedValue: CORRECT_MATCHED_VALUE
|
||||
}]
|
||||
}
|
||||
},
|
||||
'3c': {
|
||||
matchingContact: {
|
||||
id: '3c',
|
||||
givenName: ['Manolo'],
|
||||
familyName: ['García'],
|
||||
photo: [dataImage],
|
||||
email: [{
|
||||
value: 'man@tid.es'
|
||||
}],
|
||||
'tel': [{
|
||||
value: '+346578888881',
|
||||
type: 'Mobile'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'name': [{
|
||||
target: 'Manolo',
|
||||
matchedValue: 'Manolo Garcia'
|
||||
}],
|
||||
'email': [{
|
||||
target: 'man@tid.es',
|
||||
matchedValue: 'man@tid.es'
|
||||
}],
|
||||
'tel': [{
|
||||
target: '+346578888881',
|
||||
matchedValue: CORRECT_MATCHED_VALUE
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var matchingDetailsData = {
|
||||
'user_id_1': {
|
||||
matchingContact: {
|
||||
id: 'user_id_1',
|
||||
name: ['The Name The Surname'],
|
||||
givenName: ['The Name'],
|
||||
familyName: ['The Surname'],
|
||||
photo: [],
|
||||
email: [{
|
||||
value: 'email_1@acme.com',
|
||||
type: 'email_type_1'
|
||||
}, {
|
||||
value: 'email_2@acme.com',
|
||||
type: 'email_type_2'
|
||||
}],
|
||||
'tel': [{
|
||||
value: '111111111',
|
||||
type: 'type_1'
|
||||
}, {
|
||||
value: '222222222',
|
||||
type: 'type_2'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'name': [{
|
||||
target: 'The Name The Surname',
|
||||
matchedValue: 'The Name The Surname'
|
||||
}],
|
||||
'tel': [{
|
||||
target: '222222222',
|
||||
matchedValue: '222222222'
|
||||
}],
|
||||
'email': [{
|
||||
target: 'email_2@acme.com',
|
||||
matchedValue: 'email_2@acme.com'
|
||||
}]
|
||||
}
|
||||
},
|
||||
'user_id_2': {
|
||||
matchingContact: {
|
||||
id: 'user_id_2',
|
||||
name: ['The Name Another Surname'],
|
||||
givenName: ['The Name'],
|
||||
familyName: ['Another Surname'],
|
||||
photo: [],
|
||||
'tel': [{
|
||||
value: '111111111',
|
||||
type: 'type_1'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'tel': [{
|
||||
target: '111111111',
|
||||
matchedValue: 'type_1'
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
719
gaia/apps/communications/contacts/test/unit/contacts_merger_test.js
Executable file
719
gaia/apps/communications/contacts/test/unit/contacts_merger_test.js
Executable file
|
|
@ -0,0 +1,719 @@
|
|||
/* globals contacts, MockFindMatcher, utils, MocksHelper, MockThumbnailImage */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/simple_phone_matcher.js');
|
||||
require('/shared/js/contacts/import/utilities/misc.js');
|
||||
require('/shared/js/contacts/contacts_merger.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_find_matcher.js');
|
||||
requireApp('communications/contacts/test/unit/mock_image_thumbnail.js');
|
||||
require('/shared/test/unit/mocks/mock_contact_photo_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_contact.js');
|
||||
|
||||
|
||||
var mocksHelperForContactsMerger = new MocksHelper([
|
||||
'ContactPhotoHelper',
|
||||
'mozContact'
|
||||
]).init();
|
||||
|
||||
suite('Contacts Merging Tests', function() {
|
||||
mocksHelperForContactsMerger.attachTestHelpers();
|
||||
var toMergeContacts = null,
|
||||
toMergeContact = null,
|
||||
realmozContacts = null,
|
||||
realThumbnailImage = null;
|
||||
|
||||
var aPhoto1 = new Blob(['123456789'], {type: 'image/png'});
|
||||
var aPhoto2 = new Blob(['98786'], {type: 'image/jpg'});
|
||||
|
||||
function MasterContact() {
|
||||
this.id = '1A';
|
||||
this.givenName = ['Alfred'];
|
||||
this.familyName = ['Müller'];
|
||||
this.tel = [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}];
|
||||
this.email = [{
|
||||
type: ['work'],
|
||||
value: 'jj@jj.com'
|
||||
}];
|
||||
this.org = ['Müller & Co'];
|
||||
this.adr = [{
|
||||
type: ['work'],
|
||||
streetAddress: 'Friedrich',
|
||||
locality: 'Madrid',
|
||||
region: 'Madrid',
|
||||
postalCode: '28009',
|
||||
countryName: 'Spanien'
|
||||
}];
|
||||
this.note = [
|
||||
'Ingenieur'
|
||||
];
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
toMergeContacts = [{
|
||||
matchingContact: null,
|
||||
matchings: {}
|
||||
}
|
||||
];
|
||||
|
||||
toMergeContact = toMergeContacts[0];
|
||||
|
||||
realmozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockFindMatcher;
|
||||
|
||||
realThumbnailImage = utils.thumbnailImage;
|
||||
utils.thumbnailImage = MockThumbnailImage;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozContacts = realmozContacts;
|
||||
utils.thumbnailImage = realThumbnailImage;
|
||||
});
|
||||
|
||||
function assertFieldValues(field, values, property) {
|
||||
values.forEach(function(aValue) {
|
||||
var val = field.filter(function(x) {
|
||||
var testVal = x.value || x;
|
||||
if (property) {
|
||||
testVal = x[property][0];
|
||||
}
|
||||
return testVal === aValue;
|
||||
});
|
||||
assert.lengthOf(val, 1);
|
||||
});
|
||||
}
|
||||
|
||||
function assertPhoto(photo, target) {
|
||||
assert.isTrue(photo.size === target.size);
|
||||
assert.isTrue(photo.type === target.type);
|
||||
}
|
||||
|
||||
test('Merge first name and last name. First name prefix', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred Albert'],
|
||||
familyName: ['Müller']
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.equal(result.givenName[0], 'Alfred');
|
||||
assert.equal(result.givenName[1], 'Alfred Albert');
|
||||
assert.equal(result.familyName[0], 'Müller');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge accepts matching results without the `matchings` field',
|
||||
function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred Albert'],
|
||||
familyName: ['Müller']
|
||||
};
|
||||
delete toMergeContact.matchings;
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.equal(result.givenName[0], 'Alfred');
|
||||
assert.equal(result.givenName[1], 'Alfred Albert');
|
||||
assert.equal(result.familyName[0], 'Müller');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge first name and last name. incoming names empty', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: [],
|
||||
familyName: [],
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.equal(result.givenName[0], 'Alfred');
|
||||
assert.equal(result.familyName[0], 'Müller');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge first name and last name. existing names empty', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred'],
|
||||
familyName: ['Müller von Bismarck'],
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.givenName = null;
|
||||
masterContact.familyName = null;
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.equal(result.givenName[0], 'Alfred');
|
||||
assert.equal(result.familyName[0], 'Müller von Bismarck');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge first name and last name. existing and incoming given names' +
|
||||
'empty', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: [],
|
||||
familyName: ['Müller von Bismarck'],
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.givenName = null;
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.isTrue(result.givenName.length === 0);
|
||||
assert.equal(result.familyName[0], 'Müller');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge first name and last name. existing and incoming last names empty',
|
||||
function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred Albert'],
|
||||
familyName: [],
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.familyName = null;
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.isTrue(result.familyName.length === 0);
|
||||
assert.equal(result.givenName[0], 'Alfred');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merging existing with only familyName with an incoming SIM Contact',
|
||||
function(done) {
|
||||
var masterContact = new MasterContact();
|
||||
masterContact.givenName[0] = '';
|
||||
masterContact.name = [];
|
||||
masterContact.familyName = ['Smith'];
|
||||
masterContact.name[0] = masterContact.familyName[0];
|
||||
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Smith'],
|
||||
familyName: [],
|
||||
name: ['Smith'],
|
||||
category: ['sim']
|
||||
};
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.isTrue(!result.givenName[0]);
|
||||
assert.equal(result.familyName[0], 'Smith');
|
||||
assert.equal(result.name[0], 'Smith');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Merging existing with only givenName with an incoming SIM Contact',
|
||||
function(done) {
|
||||
var masterContact = new MasterContact();
|
||||
masterContact.givenName[0] = 'Lionel';
|
||||
masterContact.name = [];
|
||||
masterContact.familyName = null;
|
||||
masterContact.name[0] = masterContact.givenName[0];
|
||||
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Lionel'],
|
||||
name: ['Lionel'],
|
||||
category: ['sim']
|
||||
};
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.isTrue(!result.familyName[0]);
|
||||
assert.equal(result.givenName[0], 'Lionel');
|
||||
assert.equal(result.name[0], 'Lionel');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Merging a complete existing with an incoming SIM Contact',
|
||||
function(done) {
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred'],
|
||||
name: ['Müller'],
|
||||
category: ['sim']
|
||||
};
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.equal(masterContact.familyName[0], result.familyName[0]);
|
||||
assert.equal(masterContact.givenName[0], result.givenName[0]);
|
||||
assert.equal(masterContact.name[0], result.name[0]);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Merge telephone numbers. Adding a new one', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
},
|
||||
{
|
||||
type: null,
|
||||
value: '0987654'
|
||||
}]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.tel, 2);
|
||||
// email is left untouched
|
||||
assert.lengthOf(result.email, 1);
|
||||
|
||||
assertFieldValues(result.tel, ['67676767', '0987654']);
|
||||
assertFieldValues(result.tel, ['work', 'other'], 'type');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge telephone numbers. Leaving as they are', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.tel, 1);
|
||||
|
||||
assertFieldValues(result.tel, [masterContact.tel[0].value]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge international telephone numbers with local ones', function(done) {
|
||||
toMergeContacts[0] = {
|
||||
matchingContact: {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '+3467676767'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'tel': [
|
||||
{
|
||||
target: '67676767',
|
||||
matchedValue: '+3467676767'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assertFieldValues(result.tel, [masterContact.tel[0].value]);
|
||||
|
||||
// Restoring
|
||||
toMergeContacts[0] = toMergeContact;
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
|
||||
test('Merge tel numbers with extra characters and without', function(done) {
|
||||
toMergeContacts[0] = {
|
||||
matchingContact: {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '(67)-67. 67 67-()'
|
||||
}]
|
||||
},
|
||||
matchings: {
|
||||
'tel': [
|
||||
{
|
||||
target: '67676767',
|
||||
matchedValue: '(67)-67. 67 67-()'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assertFieldValues(result.tel, [masterContact.tel[0].value]);
|
||||
|
||||
// Restoring
|
||||
toMergeContacts[0] = toMergeContact;
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
|
||||
test('Merge emails. Adding a new one', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
email: [{
|
||||
type: [],
|
||||
value: 'home@sweet.home'
|
||||
}]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.email, 2);
|
||||
// tel is left untouched
|
||||
assert.lengthOf(result.tel, 1);
|
||||
|
||||
assertFieldValues(result.email, ['jj@jj.com', 'home@sweet.home']);
|
||||
|
||||
assertFieldValues(result.email, ['work', 'other'], 'type');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge emails. Leaving as they are', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
email: [{
|
||||
type: ['work'],
|
||||
value: 'jj@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.email, 1);
|
||||
|
||||
assertFieldValues(result.email, [masterContact.email[0].value]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge emails. Leaving as they are. Capital Letters', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
email: [{
|
||||
type: ['work'],
|
||||
value: 'JJ@jj.com'
|
||||
}]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.email, 1);
|
||||
|
||||
assertFieldValues(result.email, [masterContact.email[0].value]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge comments', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
note: ['Another comment for him']
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.note, 2);
|
||||
|
||||
assertFieldValues(result.note, [toMergeContact.matchingContact.note[0],
|
||||
masterContact.note[0]]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge addresses', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
adr: [{
|
||||
type: null,
|
||||
streetAddress: 'Gran Via',
|
||||
locality: 'Madrid',
|
||||
region: 'Madrid',
|
||||
postalCode: '28100',
|
||||
countryName: 'España'
|
||||
}]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.adr, 2);
|
||||
assertFieldValues(result.adr, ['work', 'home'], 'type');
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge companies. Existing has company', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
org: ['ONG and Assoc.']
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.org, 1);
|
||||
assertFieldValues(result.org, [masterContact.org[0]]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge companies. Existing has no company', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
org: ['ONG and Assoc.']
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
masterContact.org = null;
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.org, 1);
|
||||
assertFieldValues(result.org, [toMergeContact.matchingContact.org[0]]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge photo. To merge has photo. Master not', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
photo: [aPhoto1]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.photo, 1);
|
||||
assertPhoto(result.photo[0],
|
||||
toMergeContact.matchingContact.photo[0]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge photo. Master has photo. To merge not', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.photo = [aPhoto2]; // Different photo
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.photo, 1);
|
||||
assertPhoto(result.photo[0], masterContact.photo[0]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge photo. Both have photo', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
tel: [{
|
||||
type: ['work'],
|
||||
value: '67676767'
|
||||
}],
|
||||
photo: [aPhoto1]
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.photo = [aPhoto2]; // Different photo
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.photo, 1);
|
||||
assertPhoto(result.photo[0], masterContact.photo[0]);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge Categories', function(done) {
|
||||
toMergeContact.matchingContact = {
|
||||
category: ['category1']
|
||||
};
|
||||
|
||||
var masterContact = new MasterContact();
|
||||
|
||||
masterContact.category = ['category1', 'category2'];
|
||||
|
||||
contacts.Merger.merge(masterContact, toMergeContacts, {
|
||||
success: function(result) {
|
||||
assert.lengthOf(result.category, 2);
|
||||
assertFieldValues(result.category, masterContact.category);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Multiple merges', function(done) {
|
||||
toMergeContacts.push({
|
||||
matchingContact: {
|
||||
id: '1B',
|
||||
givenName: ['Alfred'],
|
||||
familyName: ['Müller'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '3456789'
|
||||
},
|
||||
{
|
||||
type: ['mobile'],
|
||||
value: '777777'
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'personal@example.com'
|
||||
},
|
||||
{
|
||||
type: ['personal'],
|
||||
value: 'jj@jj.com'
|
||||
}],
|
||||
note: [
|
||||
'Another note'
|
||||
],
|
||||
photo: [aPhoto1]
|
||||
},
|
||||
matchings: {}
|
||||
});
|
||||
|
||||
toMergeContact.matchingContact = {
|
||||
givenName: ['Alfred'],
|
||||
familyName: ['Müller'],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: '3456789'
|
||||
}]
|
||||
};
|
||||
|
||||
contacts.Merger.merge(new MasterContact(), toMergeContacts, {
|
||||
success: function(result) {
|
||||
assertFieldValues(result.givenName, ['Alfred']);
|
||||
assertFieldValues(result.familyName, ['Müller']);
|
||||
|
||||
assert.lengthOf(result.tel, 3);
|
||||
assertFieldValues(result.tel, ['3456789', '777777', '67676767']);
|
||||
|
||||
assert.lengthOf(result.email, 2);
|
||||
assertFieldValues(result.email, ['jj@jj.com', 'personal@example.com']);
|
||||
|
||||
assert.lengthOf(result.adr, 1);
|
||||
assert.lengthOf(result.note, 2);
|
||||
|
||||
assert.lengthOf(result.photo, 1);
|
||||
assertPhoto(result.photo[0], aPhoto1);
|
||||
|
||||
assert.lengthOf(result.org, 1);
|
||||
assertFieldValues(result.org, ['Müller & Co']);
|
||||
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
test('Merge duplicated contact', function(done) {
|
||||
var contactToMerge = new MasterContact();
|
||||
|
||||
contacts.Merger.merge(
|
||||
new MasterContact(),
|
||||
[
|
||||
{
|
||||
matchingContact: contactToMerge
|
||||
}
|
||||
], {
|
||||
success: function(result) {
|
||||
// mozContacts fields that are not filled in main contact will be
|
||||
// filled with 'undefined' what makes no difference for how the app
|
||||
// works, but we cannot just compare (deepEqually) MasterContact to
|
||||
// the result contact.
|
||||
for (var key in contactToMerge) {
|
||||
// Some of the fields are Arrays and we want to be sure they are
|
||||
// equal. deepEqual works as equal for simple literals so it makes
|
||||
// no difference for us here.
|
||||
assert.deepEqual(result[key], contactToMerge[key]);
|
||||
}
|
||||
done();
|
||||
}});
|
||||
});
|
||||
|
||||
});
|
||||
70
gaia/apps/communications/contacts/test/unit/contacts_tag_test.js
Executable file
70
gaia/apps/communications/contacts/test/unit/contacts_tag_test.js
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
'use strict';
|
||||
/* global MockSelectionDom */
|
||||
/* global triggerEvent */
|
||||
|
||||
require('/shared/js/contacts/utilities/dom.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/helper.js');
|
||||
requireApp('communications/contacts/test/unit/mock_selection_dom.js.html');
|
||||
requireApp('communications/contacts/js/contacts_tag.js');
|
||||
|
||||
suite('Fill tag options', function() {
|
||||
var subject;
|
||||
|
||||
suiteSetup(function() {
|
||||
subject = window.ContactsTag;
|
||||
document.body.innerHTML = MockSelectionDom;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
suite('go to selected tag', function() {
|
||||
var container,
|
||||
customTag,
|
||||
originalTag;
|
||||
var testTagOptions = {
|
||||
'test-type' : [
|
||||
{type: 'value1', value: 'value1'},
|
||||
{type: 'value2', value: 'value2'}
|
||||
]
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
container = document.getElementById('tags-list');
|
||||
customTag = document.getElementById('custom-tag');
|
||||
originalTag = document.createElement('button');
|
||||
originalTag.dataset.value = 'value1';
|
||||
subject.setCustomTag(customTag);
|
||||
customTag.addEventListener('touchend', subject.touchCustomTag);
|
||||
});
|
||||
|
||||
test('render tag selection form', function() {
|
||||
subject.fillTagOptions(container, originalTag,
|
||||
testTagOptions['test-type']);
|
||||
assert.equal(container.querySelector('button[data-index="0"]')
|
||||
.getAttribute('data-l10n-id'), 'value1');
|
||||
assert.equal(container.querySelector('button[data-index="1"]')
|
||||
.getAttribute('data-l10n-id'), 'value2');
|
||||
});
|
||||
|
||||
test('choose a tag', function() {
|
||||
var tag = container.querySelector('button[data-index="0"]');
|
||||
triggerEvent(tag, 'click');
|
||||
assert.isTrue(tag.className.includes('icon-selected'));
|
||||
});
|
||||
|
||||
test('choose custom tag', function() {
|
||||
var tags = container.querySelectorAll('button');
|
||||
triggerEvent(customTag, 'touchend');
|
||||
for (var i = 0; i < tags.length; i++) {
|
||||
assert.isFalse(tags[i].classList.contains('icon-selected'));
|
||||
}
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
customTag.removeEventListener('touchend', subject.touchCustomTag);
|
||||
});
|
||||
});
|
||||
});
|
||||
465
gaia/apps/communications/contacts/test/unit/contacts_test.js
Executable file
465
gaia/apps/communications/contacts/test/unit/contacts_test.js
Executable file
|
|
@ -0,0 +1,465 @@
|
|||
'use strict';
|
||||
|
||||
/* global Contacts, contacts, Loader, ActivityHandler, LazyLoader,
|
||||
MockContactsListObj, MockCookie, MockMozL10n,
|
||||
MockNavigationStack, MockUtils, MocksHelper,
|
||||
MockContactAllFields, MockContactDetails, Search,
|
||||
MockContactsSearch, MockContactsSettings, Mockfb, MockLoader,
|
||||
MockImportStatusData, MockMozContacts, ContactsService, HeaderUI
|
||||
*/
|
||||
|
||||
requireApp('communications/contacts/services/contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_cache.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_list_obj.js');
|
||||
requireApp('communications/contacts/test/unit/mock_cookie.js');
|
||||
requireApp('communications/contacts/test/unit/mock_datastore_migrator.js');
|
||||
requireApp('communications/contacts/test/unit/mock_event_listeners.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
// requireApp('communications/contacts/test/unit/mock_main_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_activities.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_details.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_search.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_settings.js');
|
||||
requireApp('communications/contacts/test/unit/mock_fb.js');
|
||||
requireApp('communications/contacts/test/unit/mock_import_status_data.js');
|
||||
requireApp('communications/contacts/test/unit/mock_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_contact_all_fields.js');
|
||||
|
||||
var mocksForStatusBar = new MocksHelper([
|
||||
'ActivityHandler',
|
||||
'Cache',
|
||||
'DatastoreMigration',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
if (!window.navigationStack) {
|
||||
window.navigationStack = null;
|
||||
}
|
||||
if (!window.contacts) {
|
||||
window.contacts = null;
|
||||
}
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
if (!navigator.mozContacts) {
|
||||
navigator.mozContacts = null;
|
||||
}
|
||||
|
||||
var globals = ['COMMS_APP_ORIGIN',
|
||||
'TAG_OPTIONS',
|
||||
'_',
|
||||
'asyncScriptsLoaded',
|
||||
'SCALE_RATIO',
|
||||
'Contacts'];
|
||||
globals.forEach(function(item) {
|
||||
if (!window[item]) {
|
||||
window[item] = null;
|
||||
}
|
||||
});
|
||||
|
||||
suite('Contacts', function() {
|
||||
var realNavigationStack;
|
||||
var realMozL10n;
|
||||
var realContacts;
|
||||
var realUtils;
|
||||
var realFb;
|
||||
var realImportStatusData;
|
||||
var mockNavigation;
|
||||
var realMozContacts;
|
||||
var realLoader;
|
||||
|
||||
mocksForStatusBar.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
loadBodyHTML('/contacts/index.html');
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
sinon.spy(navigator.mozL10n, 'once');
|
||||
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
|
||||
realContacts = window.contacts;
|
||||
window.contacts = {};
|
||||
window.contacts.List = MockContactsListObj;
|
||||
window.contacts.Details = MockContactDetails;
|
||||
window.Search = MockContactsSearch;
|
||||
window.contacts.Settings = MockContactsSettings;
|
||||
|
||||
realUtils = window.utils;
|
||||
window.utils = MockUtils;
|
||||
window.utils.cookie = MockCookie;
|
||||
|
||||
realFb = window.fb;
|
||||
window.fb = Mockfb;
|
||||
|
||||
realImportStatusData = window.ImportStatusData;
|
||||
window.ImportStatusData = MockImportStatusData;
|
||||
|
||||
realNavigationStack = window.navigationStack;
|
||||
window.navigationStack = MockNavigationStack;
|
||||
|
||||
realLoader = window.Loader;
|
||||
window.Loader = MockLoader;
|
||||
|
||||
sinon.spy(window, 'navigationStack');
|
||||
requireApp('communications/contacts/js/utilities/performance_helper.js');
|
||||
requireApp('communications/contacts/js/main_navigation.js');
|
||||
requireApp('communications/contacts/js/header_ui.js');
|
||||
requireApp('communications/contacts/js/contacts.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realMozL10n;
|
||||
navigator.mozContacts = realMozContacts;
|
||||
window.contacts = realContacts;
|
||||
window.utils = realUtils;
|
||||
window.fb = realFb;
|
||||
window.ImportStatusData = realImportStatusData;
|
||||
window.Loader = realLoader;
|
||||
|
||||
window.navigationStack.restore();
|
||||
window.navigationStack = realNavigationStack;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(window.utils.PerformanceHelper, 'chromeInteractive');
|
||||
this.sinon.spy(window.utils.PerformanceHelper, 'contentInteractive');
|
||||
|
||||
window.ImportStatusData.clear();
|
||||
|
||||
navigator.addIdleObserver = function() {};
|
||||
|
||||
// We don't want to trigger migrations in this test suite.
|
||||
MockCookie.data = {
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: true
|
||||
};
|
||||
|
||||
Contacts.init();
|
||||
mockNavigation = window.navigationStack.firstCall.thisValue;
|
||||
|
||||
navigator.mozL10n.fireOnce();
|
||||
});
|
||||
|
||||
test('hashchange home', function(done) {
|
||||
this.sinon.spy(mockNavigation, 'home');
|
||||
window.location.hash = '#home';
|
||||
setTimeout(function() {
|
||||
sinon.assert.called(mockNavigation.home);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('mozL10n initialized', function() {
|
||||
sinon.assert.calledOnce(navigator.mozL10n.once);
|
||||
sinon.assert.calledOnce(window.utils.PerformanceHelper.chromeInteractive);
|
||||
sinon.assert.calledOnce(window.utils.PerformanceHelper.contentInteractive);
|
||||
});
|
||||
|
||||
suite('on contacts change', function() {
|
||||
var mozContact = null;
|
||||
|
||||
setup(function() {
|
||||
mozContact = new MockContactAllFields();
|
||||
Contacts.setCurrent(mozContact);
|
||||
|
||||
this.sinon.stub(
|
||||
ContactsService,
|
||||
'get',
|
||||
function(id, cb) {
|
||||
// Return the contact + additional FB info
|
||||
cb(
|
||||
mozContact,
|
||||
{
|
||||
id: 'FBID',
|
||||
email: [
|
||||
{
|
||||
type: ['work'],
|
||||
value: 'myfbemail@email.com'
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
this.sinon.stub(contacts.List, 'refresh', function(id, cb) {
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
test('> FB contact update sends MozContacts info', function() {
|
||||
|
||||
mockNavigation._currentView = 'view-contact-details';
|
||||
navigator.mozContacts.dispatchEvent({
|
||||
type: 'contactchange',
|
||||
contactID: mozContact.id,
|
||||
reason: 'update'
|
||||
});
|
||||
|
||||
sinon.assert.called(ContactsService.get);
|
||||
sinon.assert.called(contacts.List.refresh);
|
||||
|
||||
var argument = contacts.List.refresh.getCall(0).args[0];
|
||||
assert.isTrue(Array.isArray(argument.email));
|
||||
argument.email.forEach(function onEmail(email) {
|
||||
assert.isTrue(email.value === 'myfbemail@email.com');
|
||||
});
|
||||
});
|
||||
|
||||
suite('> Custom contact change', function() {
|
||||
test('> Trigger custom event on contact change', function(done) {
|
||||
Contacts.onLocalized();
|
||||
|
||||
mockNavigation._currentView = 'view-contact-details';
|
||||
document.addEventListener('contactChanged', function(e) {
|
||||
assert.equal(e.detail.contactID, 1234567);
|
||||
done();
|
||||
});
|
||||
|
||||
navigator.mozContacts.dispatchEvent({
|
||||
type: 'contactchange',
|
||||
contactID: 1234567,
|
||||
reason: 'update'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Controller actions', function() {
|
||||
var navigation;
|
||||
setup(function() {
|
||||
navigation = window.navigationStack.firstCall.thisValue;
|
||||
this.sinon.spy(navigation, 'back');
|
||||
this.sinon.spy(navigation, 'home');
|
||||
this.sinon.spy(window.ActivityHandler, 'postCancel');
|
||||
});
|
||||
test('> go back', function() {
|
||||
Contacts.goBack();
|
||||
sinon.assert.called(navigation.back);
|
||||
navigation.back.restore();
|
||||
});
|
||||
test('> handle cancel with activity', function() {
|
||||
ActivityHandler.currentlyHandling = true;
|
||||
|
||||
Contacts.cancel();
|
||||
sinon.assert.called(window.ActivityHandler.postCancel);
|
||||
sinon.assert.called(navigation.home);
|
||||
|
||||
window.ActivityHandler.currentlyHandling = false;
|
||||
});
|
||||
test('> handle cancel without activity', function() {
|
||||
Contacts.cancel();
|
||||
sinon.assert.called(navigation.back);
|
||||
sinon.assert.notCalled(window.ActivityHandler.postCancel);
|
||||
});
|
||||
|
||||
suite('> CancelableActivity', function() {
|
||||
var prevCurrentlyHandling, prevActivityName, prevActivityDataType;
|
||||
|
||||
suiteSetup(function() {
|
||||
prevCurrentlyHandling = window.ActivityHandler.currentlyHandling;
|
||||
prevActivityName = window.ActivityHandler.activityName;
|
||||
prevActivityDataType = window.ActivityHandler.activityDataType;
|
||||
window.ActivityHandler.currentlyHandling = true;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.ActivityHandler.activityName = prevActivityName;
|
||||
window.ActivityHandler.activityDataType = prevActivityDataType;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.ActivityHandler.currentlyHandling = prevCurrentlyHandling;
|
||||
});
|
||||
|
||||
test('> handling an activity', function() {
|
||||
ActivityHandler.isCancelable().then(() => {
|
||||
HeaderUI.updateHeader(true);
|
||||
// Settings is hidden
|
||||
assert.isTrue(HeaderUI.settingsButton.hidden);
|
||||
// Add contact is hidden
|
||||
assert.isTrue(HeaderUI.addButton.hidden);
|
||||
// Cancel is visible
|
||||
assert.equal(HeaderUI.header.getAttribute('action'), 'close');
|
||||
// Title shows CONTACTS
|
||||
assert.equal(HeaderUI.appTitleElement.getAttribute('data-l10n-id'),
|
||||
'contacts');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Select a contact from the list', function() {
|
||||
var theSelectedContact = {
|
||||
'id': '1',
|
||||
'name': ['John']
|
||||
};
|
||||
var navigation;
|
||||
setup(function() {
|
||||
navigation = window.navigationStack.firstCall.thisValue;
|
||||
this.sinon.stub(Loader, 'view', function(view, cb) {
|
||||
cb();
|
||||
});
|
||||
this.sinon.stub(ContactsService, 'get',
|
||||
function(id, cb) {
|
||||
cb(theSelectedContact, null);
|
||||
});
|
||||
|
||||
this.sinon.spy(ActivityHandler, 'dataPickHandler');
|
||||
this.sinon.spy(contacts.Details, 'render');
|
||||
this.sinon.spy(navigation, 'go');
|
||||
});
|
||||
|
||||
test('> initializing details', function() {
|
||||
Contacts.showContactDetail('1');
|
||||
|
||||
sinon.assert.called(Loader.view);
|
||||
sinon.assert.called(ContactsService.get);
|
||||
sinon.assert.called(contacts.Details.render);
|
||||
sinon.assert.calledWith(navigation.go,
|
||||
'view-contact-details', 'go-deeper');
|
||||
sinon.assert.notCalled(ActivityHandler.dataPickHandler);
|
||||
|
||||
});
|
||||
|
||||
test('> when handling pick activity, don\'t navigate, send result',
|
||||
function() {
|
||||
ActivityHandler.currentlyHandling = true;
|
||||
ActivityHandler.activityName = 'pick';
|
||||
Contacts.showContactDetail('1');
|
||||
|
||||
sinon.assert.called(ContactsService.get);
|
||||
sinon.assert.notCalled(contacts.Details.render);
|
||||
sinon.assert.notCalled(navigation.go);
|
||||
sinon.assert.called(ActivityHandler.dataPickHandler);
|
||||
|
||||
ActivityHandler.currentlyHandling = false;
|
||||
ActivityHandler.activityName = 'open';
|
||||
}
|
||||
);
|
||||
|
||||
test('> when handling import activity, navigate as normal',
|
||||
function() {
|
||||
ActivityHandler.currentlyHandling = true;
|
||||
ActivityHandler.activityName = 'import';
|
||||
Contacts.showContactDetail('1');
|
||||
|
||||
sinon.assert.called(ContactsService.get);
|
||||
sinon.assert.called(contacts.Details.render);
|
||||
sinon.assert.called(navigation.go);
|
||||
sinon.assert.notCalled(ActivityHandler.dataPickHandler);
|
||||
|
||||
ActivityHandler.currentlyHandling = false;
|
||||
ActivityHandler.activityName = 'open';
|
||||
}
|
||||
);
|
||||
|
||||
test('> in search navigate deeper from search', function() {
|
||||
sinon.stub(Search, 'isInSearchMode', function() {
|
||||
return true;
|
||||
});
|
||||
|
||||
Contacts.showContactDetail('1');
|
||||
|
||||
sinon.assert.called(contacts.Details.render);
|
||||
sinon.assert.called(Search.isInSearchMode);
|
||||
sinon.assert.calledWith(navigation.go,
|
||||
'view-contact-details', 'go-deeper-search');
|
||||
sinon.assert.notCalled(ActivityHandler.dataPickHandler);
|
||||
|
||||
Search.isInSearchMode.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Async scripts loading', function() {
|
||||
var lastParams;
|
||||
var handler;
|
||||
setup(function() {
|
||||
this.sinon.stub(ContactsService, 'addListener', function(evt, cb) {
|
||||
handler = cb;
|
||||
});
|
||||
this.sinon.stub(LazyLoader, 'load', function(p, cb) {
|
||||
lastParams = p;
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
handler = null;
|
||||
});
|
||||
|
||||
test('> normal load of the scripts', function() {
|
||||
Contacts.onLocalized().then(() => {
|
||||
sinon.assert.called(window.dispatchEvent);
|
||||
assert.isNotNull(handler);
|
||||
});
|
||||
});
|
||||
|
||||
test('> loading scripts while handling an open activity',
|
||||
function() {
|
||||
ActivityHandler.currentlyHandling = true;
|
||||
Contacts.onLocalized().then(() => {
|
||||
assert.isNotNull(handler);
|
||||
ActivityHandler.currentlyHandling = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Visibility changes', function() {
|
||||
var navigation;
|
||||
function fireVisibilityChange() {
|
||||
document.dispatchEvent(new CustomEvent('visibilitychange'));
|
||||
}
|
||||
setup(function() {
|
||||
navigation = window.navigationStack.firstCall.thisValue;
|
||||
this.sinon.spy(ActivityHandler, 'isCancelable');
|
||||
this.sinon.spy(ActivityHandler, 'postCancel');
|
||||
this.sinon.stub(Loader, 'view', function(view, cb) {
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
test('> in settings view, should refresh for new timestamp', function() {
|
||||
sinon.stub(navigation, 'currentView', function() {
|
||||
return 'view-settings';
|
||||
});
|
||||
sinon.spy(contacts.Settings, 'updateTimestamps');
|
||||
|
||||
fireVisibilityChange();
|
||||
|
||||
sinon.assert.called(contacts.Settings.updateTimestamps);
|
||||
sinon.assert.notCalled(ActivityHandler.postCancel);
|
||||
|
||||
navigation.currentView.restore();
|
||||
contacts.Settings.updateTimestamps.restore();
|
||||
});
|
||||
|
||||
suite('> going to the background', function() {
|
||||
var realHidden;
|
||||
suiteSetup(function() {
|
||||
realHidden = Object.getOwnPropertyDescriptor(document, 'hidden');
|
||||
Object.defineProperty(document, 'hidden', {
|
||||
configurable: true,
|
||||
get: function() { return true; }
|
||||
});
|
||||
});
|
||||
suiteTeardown(function() {
|
||||
if (realHidden) {
|
||||
Object.defineProperty(document, 'hidden', realHidden);
|
||||
} else {
|
||||
delete document.hidden;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
292
gaia/apps/communications/contacts/test/unit/datastore_migrator_test.js
Executable file
292
gaia/apps/communications/contacts/test/unit/datastore_migrator_test.js
Executable file
|
|
@ -0,0 +1,292 @@
|
|||
'use strict';
|
||||
/* global DatastoreMigration */
|
||||
/* global MockContactsListObj */
|
||||
/* global MockCookie */
|
||||
/* global MockFbContactsWriterObj */
|
||||
/* global MockIndexedDB */
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_fb_data.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_list_obj.js');
|
||||
require('/shared/test/unit/mocks/mock_indexedDB.js');
|
||||
requireApp('communications/contacts/test/unit/mock_cookie.js');
|
||||
requireApp('communications/contacts/js/fb/datastore_migrator.js');
|
||||
|
||||
|
||||
var realFbData, realContacts,
|
||||
realRemoveIdleObserver, realCookie, mockIndexedDB;
|
||||
|
||||
if (!window.realFbData) {
|
||||
window.realFbData = null;
|
||||
}
|
||||
|
||||
if (!window.fb) {
|
||||
window.fb = null;
|
||||
}
|
||||
|
||||
if (!window.contacts) {
|
||||
window.contacts = null;
|
||||
}
|
||||
|
||||
if (!window.realContacts) {
|
||||
window.realContacts = null;
|
||||
}
|
||||
|
||||
if (!window.realRemoveIdleObserver) {
|
||||
window.realRemoveIdleObserver = null;
|
||||
}
|
||||
|
||||
if (!window.realCookie) {
|
||||
window.realCookie = null;
|
||||
}
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
|
||||
if (!window.mockIndexedDB) {
|
||||
window.mockIndexedDB = null;
|
||||
}
|
||||
|
||||
suite('IndexedDB --> Datastore migration', function() {
|
||||
var idbShortData = {
|
||||
'123456': {
|
||||
uid: '123456'
|
||||
},
|
||||
'567890': {
|
||||
uid: '567890'
|
||||
}
|
||||
};
|
||||
|
||||
var idbLongData = {
|
||||
'123456': {
|
||||
uid: '123456'
|
||||
},
|
||||
'567890': {
|
||||
uid: '567890'
|
||||
},
|
||||
'987654': {
|
||||
uid: '987654'
|
||||
},
|
||||
'387643': {
|
||||
uid: '387643'
|
||||
},
|
||||
'999999': {
|
||||
uid: '999999'
|
||||
},
|
||||
'111111': {
|
||||
uid: '111111'
|
||||
}
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realFbData = window.fb && window.fb.contacts;
|
||||
window.fb = window.fb || {};
|
||||
|
||||
realContacts = window.contacts && window.contacts.List;
|
||||
window.contacts = window.contacts || {};
|
||||
window.contacts.List = MockContactsListObj;
|
||||
|
||||
realRemoveIdleObserver = navigator.removeIdleObserver;
|
||||
navigator.removeIdleObserver = function() { };
|
||||
|
||||
realCookie = window.utils && window.utils.cookie;
|
||||
window.utils = window.utils || {};
|
||||
window.utils.cookie = MockCookie;
|
||||
|
||||
mockIndexedDB = new MockIndexedDB();
|
||||
});
|
||||
|
||||
function testMigration(records, done) {
|
||||
var existingRecords = records.existing;
|
||||
var inputRecords = records.input;
|
||||
var inErrorRecords = records.inError;
|
||||
|
||||
var db;
|
||||
|
||||
var contactsWriter = new MockFbContactsWriterObj();
|
||||
window.fb.contacts = contactsWriter;
|
||||
contactsWriter.storedData = existingRecords || contactsWriter.storedData;
|
||||
MockCookie.data = {};
|
||||
|
||||
var numDeletedDBs = mockIndexedDB.deletedDbs.length;
|
||||
var deleteError = [];
|
||||
if (inErrorRecords && inErrorRecords.deleted) {
|
||||
deleteError = inErrorRecords.deleted;
|
||||
}
|
||||
|
||||
var saveError = [];
|
||||
if (inErrorRecords && inErrorRecords.saved) {
|
||||
saveError = inErrorRecords.saved;
|
||||
contactsWriter.savedError = saveError;
|
||||
}
|
||||
|
||||
var migrationDone = function migrationDone(saveErrors) {
|
||||
var deletedObjs = db.deletedData;
|
||||
var numAddedObjs = contactsWriter.getLength();
|
||||
|
||||
assert.equal(Object.keys(inputRecords).length,
|
||||
numAddedObjs + saveError.length);
|
||||
assert.equal(deletedObjs.length + deleteError.length, numAddedObjs);
|
||||
for (var aObjUid in contactsWriter.storedData) {
|
||||
assert.isTrue(deletedObjs.indexOf(aObjUid) !== -1 ||
|
||||
deleteError.indexOf(aObjUid) !== -1);
|
||||
}
|
||||
|
||||
assert.isTrue(db.isClosed === true);
|
||||
|
||||
if (!saveErrors) {
|
||||
// Check that cookies are correctly set
|
||||
assert.equal(MockCookie.data.fbMigrated, true);
|
||||
assert.isTrue(mockIndexedDB.deletedDbs.length === numDeletedDBs + 1);
|
||||
}
|
||||
else {
|
||||
assert.isTrue(mockIndexedDB.deletedDbs.length === numDeletedDBs);
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
var req = window.indexedDB.open('Fake_Database');
|
||||
|
||||
req.onsuccess = function() {
|
||||
db = req.result;
|
||||
db.storedData = JSON.parse(JSON.stringify(inputRecords));
|
||||
|
||||
var migrationObj = new DatastoreMigration(db);
|
||||
migrationObj.onmigrationdone = migrationDone;
|
||||
migrationObj.onerror = done;
|
||||
if (inErrorRecords && inErrorRecords.deleted) {
|
||||
db.options.deleteInError = inErrorRecords.deleted;
|
||||
}
|
||||
migrationObj.onidle();
|
||||
};
|
||||
req.onerror = done;
|
||||
}
|
||||
|
||||
test('Seamless migration. Total records < slice size. No failures',
|
||||
function(done) {
|
||||
testMigration({ input: idbShortData }, done);
|
||||
});
|
||||
|
||||
test('Seamless migration. Total records > slice size. No failures',
|
||||
function(done) {
|
||||
testMigration({ input: idbLongData }, done);
|
||||
});
|
||||
|
||||
test('If indexedDB does not contain records, nothing is done',
|
||||
function(done) {
|
||||
testMigration({ input: {} }, done);
|
||||
});
|
||||
|
||||
test('If indexedDB is in error, an error is reported', function(done) {
|
||||
var contactsWriter = new MockFbContactsWriterObj();
|
||||
window.fb.contacts = contactsWriter;
|
||||
MockCookie.data = {};
|
||||
|
||||
mockIndexedDB.options.inErrorDbs = ['Gaia_Facebook_Friends'];
|
||||
|
||||
var migrationObj = new DatastoreMigration();
|
||||
migrationObj.onerror = function() {
|
||||
assert.equal(contactsWriter.getLength(), 0);
|
||||
assert.isFalse((MockCookie.data.fbMigrated === true));
|
||||
done();
|
||||
};
|
||||
migrationObj.onmigrationdone = function() {
|
||||
assert.fail('Migration done');
|
||||
done();
|
||||
};
|
||||
migrationObj.onidle();
|
||||
});
|
||||
|
||||
test('If indexedDB does not exist, nothing is done', function(done) {
|
||||
var contactsWriter = new MockFbContactsWriterObj();
|
||||
window.fb.contacts = contactsWriter;
|
||||
MockCookie.data = {};
|
||||
|
||||
mockIndexedDB.options.upgradeNeededDbs = ['Gaia_Facebook_Friends'];
|
||||
mockIndexedDB.options.inErrorDbs = [];
|
||||
|
||||
var migrationObj = new DatastoreMigration();
|
||||
migrationObj.onmigrationdone = function() {
|
||||
assert.equal(contactsWriter.getLength(), 0);
|
||||
assert.equal(MockCookie.data.fbMigrated, true);
|
||||
done();
|
||||
};
|
||||
migrationObj.onidle();
|
||||
});
|
||||
|
||||
test('If a migrated record already exists the migration continues seamlessly',
|
||||
function(done) {
|
||||
var existing = Object.create(null);
|
||||
existing['123456'] = {
|
||||
uid: '123456'
|
||||
};
|
||||
testMigration({
|
||||
input: idbLongData,
|
||||
existing: existing
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('If a record cannot be deleted the migration continues seamlessly',
|
||||
function(done) {
|
||||
var inError = {
|
||||
deleted: ['987654']
|
||||
};
|
||||
testMigration({
|
||||
input: idbLongData,
|
||||
inError: inError
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('If cursor cannot be opened the process can resume later',
|
||||
function(done) {
|
||||
var contactsWriter = new MockFbContactsWriterObj();
|
||||
window.fb.contacts = contactsWriter;
|
||||
|
||||
var db;
|
||||
var req = window.indexedDB.open('Fake_Database');
|
||||
|
||||
req.onsuccess = function() {
|
||||
db = req.result;
|
||||
db.options.cursorOpenInError = true;
|
||||
var migratorObj = new DatastoreMigration(db);
|
||||
db.storedData = JSON.parse(JSON.stringify(idbShortData));
|
||||
migratorObj.onerror = function() {
|
||||
assert.ok('Migration error');
|
||||
migratorObj.onmigrationdone = function() {
|
||||
assert.ok('Migration done');
|
||||
done();
|
||||
};
|
||||
delete db.options.cursorOpenInError;
|
||||
// Need to restore the Database before calling onidle one more time
|
||||
migratorObj.db = db;
|
||||
migratorObj.onidle();
|
||||
};
|
||||
migratorObj.onmigrationdone = function() {
|
||||
assert.fail('Migration done', 'Shouldnt');
|
||||
};
|
||||
migratorObj.onidle();
|
||||
};
|
||||
|
||||
req.onerror = done;
|
||||
});
|
||||
|
||||
test(
|
||||
'If a record cannot be saved the process can continue without losing data',
|
||||
function(done) {
|
||||
var inError = {
|
||||
saved: ['387643']
|
||||
};
|
||||
testMigration({
|
||||
input: idbLongData,
|
||||
inError: inError
|
||||
}, done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.fb.contacts = realFbData;
|
||||
window.contacts.List = realContacts;
|
||||
window.utils.cookie = realCookie;
|
||||
navigator.removeIdleObserver = realRemoveIdleObserver;
|
||||
});
|
||||
});
|
||||
225
gaia/apps/communications/contacts/test/unit/deferred_actions_test.js
Executable file
225
gaia/apps/communications/contacts/test/unit/deferred_actions_test.js
Executable file
|
|
@ -0,0 +1,225 @@
|
|||
'use strict';
|
||||
/* global MockImportStatusData, Mockfb, MockContacts, MockNavigationStack,
|
||||
MockCookie, DeferredActions, fb */
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
requireApp('communications/contacts/test/unit/mock_import_status_data.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_list_obj.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_cookie.js');
|
||||
requireApp('communications/contacts/test/unit/mock_fb.js');
|
||||
requireApp('communications/contacts/js/deferred_actions.js');
|
||||
|
||||
|
||||
if (!navigator.addIdleObserver) {
|
||||
navigator.addIdleObserver = function() {};
|
||||
}
|
||||
|
||||
if (!navigator.removeIdleObserver) {
|
||||
navigator.removeIdleObserver = function() {};
|
||||
}
|
||||
|
||||
if (!window.ImportStatusData) {
|
||||
window.ImportStatusData = null;
|
||||
}
|
||||
|
||||
if (!window.contacts) {
|
||||
window.contacts = null;
|
||||
}
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
|
||||
if (!window.fb) {
|
||||
window.fb = null;
|
||||
}
|
||||
|
||||
|
||||
suite('Post rendering', function() {
|
||||
var realImportStatusData,
|
||||
realUtils,
|
||||
realFb,
|
||||
realFbLoader;
|
||||
|
||||
var mockNavigationStack;
|
||||
|
||||
suiteSetup(function() {
|
||||
realImportStatusData = window.ImportStatusData;
|
||||
window.ImportStatusData = MockImportStatusData;
|
||||
|
||||
window.Contacts = MockContacts;
|
||||
|
||||
realUtils = window.utils;
|
||||
window.utils = {};
|
||||
window.utils.cookie = MockCookie;
|
||||
|
||||
realFb = window.fb;
|
||||
window.fb = Mockfb;
|
||||
|
||||
mockNavigationStack = new MockNavigationStack();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.ImportStatusData = realImportStatusData;
|
||||
});
|
||||
|
||||
suite('Post rendering actions', function() {
|
||||
suiteSetup(function() {
|
||||
sinon.stub(navigator, 'addIdleObserver', function(idleObserver) {
|
||||
idleObserver.onidle();
|
||||
});
|
||||
|
||||
sinon.stub(navigator, 'removeIdleObserver', function() {});
|
||||
|
||||
realFbLoader = window.fbLoader;
|
||||
|
||||
window.fbLoader = {
|
||||
loaded: true
|
||||
};
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.addIdleObserver.restore();
|
||||
navigator.removeIdleObserver.restore();
|
||||
|
||||
window.fbLoader = realFbLoader;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockImportStatusData.clear();
|
||||
MockCookie.update({});
|
||||
});
|
||||
|
||||
test('FB sync scheduling when synced in ftu', function(done) {
|
||||
sinon.stub(Mockfb.sync, 'scheduleNextSync', function() {
|
||||
done(function() {
|
||||
Mockfb.sync.scheduleNextSync.restore();
|
||||
assert.ok('passed');
|
||||
});
|
||||
});
|
||||
|
||||
MockCookie.update({
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: true
|
||||
});
|
||||
|
||||
window.ImportStatusData.put(
|
||||
Mockfb.utils.SCHEDULE_SYNC_KEY, Date.now()).then(function() {
|
||||
DeferredActions.execute();
|
||||
});
|
||||
});
|
||||
|
||||
test('Facebook not yet loaded', function(done) {
|
||||
var currentFbLoader = window.fbLoader;
|
||||
|
||||
window.fbLoader = {
|
||||
loaded: false
|
||||
};
|
||||
|
||||
sinon.stub(Mockfb.sync, 'scheduleNextSync', function() {
|
||||
done(function() {
|
||||
Mockfb.sync.scheduleNextSync.restore();
|
||||
window.fbLoader = currentFbLoader;
|
||||
assert.ok('passed');
|
||||
});
|
||||
});
|
||||
|
||||
MockCookie.update({
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: true
|
||||
});
|
||||
|
||||
window.ImportStatusData.put(
|
||||
Mockfb.utils.SCHEDULE_SYNC_KEY, Date.now()).then(function() {
|
||||
DeferredActions.execute();
|
||||
window.dispatchEvent(new CustomEvent('facebookLoaded'));
|
||||
});
|
||||
});
|
||||
|
||||
test('Version migration triggered when needed', function(done) {
|
||||
sinon.stub(window.LazyLoader, 'load', function(file) {
|
||||
if (file.indexOf('migrator.js') > -1) {
|
||||
done(function() {
|
||||
window.LazyLoader.load.restore();
|
||||
assert.ok('passed');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
MockCookie.update({
|
||||
fbScheduleDone: true
|
||||
});
|
||||
|
||||
DeferredActions.execute();
|
||||
});
|
||||
|
||||
suite('Facebook sanity checks', function() {
|
||||
var spy;
|
||||
|
||||
suiteSetup(function() {
|
||||
fb.utils = {
|
||||
clearFbData: function() {
|
||||
return {
|
||||
result: {
|
||||
set onsuccess(cb2) {
|
||||
cb2();
|
||||
}
|
||||
},
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
spy = sinon.spy(fb.utils, 'clearFbData');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
// Left things as they were
|
||||
spy.restore();
|
||||
delete fb.utils;
|
||||
});
|
||||
|
||||
test('Not called when not needed', function() {
|
||||
spy.reset();
|
||||
|
||||
MockCookie.update({
|
||||
fbCleaningInProgress: 0
|
||||
});
|
||||
|
||||
DeferredActions.execute();
|
||||
|
||||
assert.isFalse(spy.calledOnce);
|
||||
assert.equal(MockCookie.data.fbCleaningInProgress, 0);
|
||||
});
|
||||
|
||||
test('Clear Facebook data called when needed', function() {
|
||||
MockCookie.update({
|
||||
fbCleaningInProgress: 1
|
||||
});
|
||||
|
||||
DeferredActions.execute();
|
||||
|
||||
assert.isTrue(spy.calledOnce);
|
||||
assert.equal(MockCookie.data.fbCleaningInProgress, 0);
|
||||
});
|
||||
|
||||
test('Not called when num retries exceeded', function() {
|
||||
var times = 5;
|
||||
spy.reset();
|
||||
|
||||
MockCookie.update({
|
||||
fbCleaningInProgress: times
|
||||
});
|
||||
|
||||
DeferredActions.execute();
|
||||
|
||||
assert.isFalse(spy.calledOnce);
|
||||
assert.equal(MockCookie.data.fbCleaningInProgress, times);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
245
gaia/apps/communications/contacts/test/unit/export/bt_test.js
Executable file
245
gaia/apps/communications/contacts/test/unit/export/bt_test.js
Executable file
|
|
@ -0,0 +1,245 @@
|
|||
'use strict';
|
||||
/* globals ContactsBTExport, MockContactToVcarBlob, MockgetDeviceStorage,
|
||||
MockGetStorageIfAvailable, MockGetStorageIfAvailableError,
|
||||
MockGetUnusedFilename, MocksHelper, MockMozActivity, MockMozL10n */
|
||||
|
||||
requireApp('communications/contacts/js/export/bt.js');
|
||||
requireApp('communications/contacts/test/unit/mock_mozActivity.js');
|
||||
requireApp('communications/contacts/test/unit/mock_get_device_storage.js');
|
||||
requireApp('communications/contacts/test/unit/export/mock_export_utils.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
|
||||
if (!window._) {
|
||||
window._ = null;
|
||||
}
|
||||
|
||||
if (!window.getStorageIfAvailable) {
|
||||
window.getStorageIfAvailable = null;
|
||||
}
|
||||
|
||||
if (!window.getUnusedFilename) {
|
||||
window.getUnusedFilename = null;
|
||||
}
|
||||
|
||||
if (!window.ContactToVcardBlob) {
|
||||
window.ContactToVcardBlob = null;
|
||||
}
|
||||
|
||||
var realUtils = null;
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
} else {
|
||||
realUtils = window.utils;
|
||||
}
|
||||
|
||||
var mocksHelperForExportBT = new MocksHelper([
|
||||
'MozActivity'
|
||||
]).init();
|
||||
|
||||
suite('BT export', function() {
|
||||
var real_,
|
||||
realMozL10n,
|
||||
realDeviceStorage,
|
||||
realgetUnusedFilename,
|
||||
realContactToVcardBlob,
|
||||
realgetStorageIfAvailable;
|
||||
|
||||
var mockContact1 = {
|
||||
familyName: ['surname1'],
|
||||
givenName: ['name1']
|
||||
},
|
||||
mockContact2 = {
|
||||
familyName: ['surname2'],
|
||||
givenName: ['name2']
|
||||
};
|
||||
|
||||
var subject,
|
||||
mockProgress,
|
||||
mocksHelper = mocksHelperForExportBT;
|
||||
|
||||
suiteSetup(function() {
|
||||
mocksHelper.suiteSetup();
|
||||
|
||||
// Device storage mock
|
||||
realDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockgetDeviceStorage;
|
||||
|
||||
// L10n mock
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
//getStorageIfAvailable mock
|
||||
realgetStorageIfAvailable = window.getStorageIfAvailable;
|
||||
window.getStorageIfAvailable = MockGetStorageIfAvailable;
|
||||
|
||||
//getUnusedFilename mock
|
||||
realgetUnusedFilename = window.getUnusedFilename;
|
||||
window.getUnusedFilename = MockGetUnusedFilename;
|
||||
|
||||
//ContactToVcardBlob mock
|
||||
realContactToVcardBlob = window.ContactToVcardBlob;
|
||||
window.ContactToVcardBlob = MockContactToVcarBlob;
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = {};
|
||||
}
|
||||
window.utils.overlay = {
|
||||
hideMenu: function() {}
|
||||
};
|
||||
|
||||
mockProgress = function() {};
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
mocksHelper.suiteTeardown();
|
||||
navigator.getDeviceStorage = realDeviceStorage;
|
||||
window._ = real_;
|
||||
window.getStorageIfAvailable = realgetStorageIfAvailable;
|
||||
window.getUnusedFilename = realgetUnusedFilename;
|
||||
window.ContactToVcardBlob = realContactToVcardBlob;
|
||||
window.utils = realUtils;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
mocksHelper.setup();
|
||||
subject = new ContactsBTExport();
|
||||
subject.setProgressStep(mockProgress);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
mocksHelper.teardown();
|
||||
});
|
||||
|
||||
test('Calling with 1 contact', function(done) {
|
||||
subject.setContactsToExport([mockContact1]);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
assert.equal(false, subject.hasDeterminativeProgress());
|
||||
assert.isNull(error);
|
||||
assert.equal(1, exported);
|
||||
done();
|
||||
});
|
||||
// Execute the onsuccess on demand
|
||||
MockMozActivity.currentActivity.onsuccess();
|
||||
});
|
||||
|
||||
test('Calling with several contacts', function(done) {
|
||||
var contacts = [mockContact1, mockContact2];
|
||||
subject.setContactsToExport(contacts);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
assert.isNull(error);
|
||||
assert.equal(contacts.length, exported);
|
||||
done();
|
||||
});
|
||||
// Execute the onsuccess on demand
|
||||
MockMozActivity.currentActivity.onsuccess();
|
||||
});
|
||||
|
||||
test('Calling with cancel flag activated', function(done) {
|
||||
var contacts = [mockContact1, mockContact2];
|
||||
subject.setContactsToExport(contacts);
|
||||
subject.cancelExport();
|
||||
subject.doExport(function onFinish(error, exported, isRecoverable) {
|
||||
assert.isNull(error);
|
||||
assert.equal(0, exported);
|
||||
assert.equal(isRecoverable, false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('BT export_error', function() {
|
||||
var real_,
|
||||
realMozL10n,
|
||||
realDeviceStorage,
|
||||
realgetUnusedFilename,
|
||||
realContactToVcardBlob,
|
||||
realgetStorageIfAvailable;
|
||||
|
||||
var mockContact1 = {
|
||||
familyName: ['surname1'],
|
||||
givenName: ['name1']
|
||||
},
|
||||
mockContact2 = {
|
||||
familyName: ['surname2'],
|
||||
givenName: ['name2']
|
||||
};
|
||||
|
||||
var subject,
|
||||
mockProgress,
|
||||
mocksHelper = mocksHelperForExportBT;
|
||||
|
||||
suiteSetup(function() {
|
||||
mocksHelper.suiteSetup();
|
||||
|
||||
// Device storage mock
|
||||
realDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockgetDeviceStorage;
|
||||
|
||||
// L10n mock
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
//getStorageIfAvailable mock
|
||||
realgetStorageIfAvailable = window.getStorageIfAvailable;
|
||||
window.getStorageIfAvailable = MockGetStorageIfAvailableError;
|
||||
|
||||
//getUnusedFilename mock
|
||||
realgetUnusedFilename = window.getUnusedFilename;
|
||||
window.getUnusedFilename = MockGetUnusedFilename;
|
||||
|
||||
//ContactToVcardBlob mock
|
||||
realContactToVcardBlob = window.ContactToVcardBlob;
|
||||
window.ContactToVcardBlob = MockContactToVcarBlob;
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = {};
|
||||
}
|
||||
window.utils.overlay = {
|
||||
hideMenu: function() {}
|
||||
};
|
||||
|
||||
mockProgress = function() {};
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
mocksHelper.suiteTeardown();
|
||||
navigator.getDeviceStorage = realDeviceStorage;
|
||||
window._ = real_;
|
||||
window.getStorageIfAvailable = realgetStorageIfAvailable;
|
||||
window.getUnusedFilename = realgetUnusedFilename;
|
||||
window.ContactToVcardBlob = realContactToVcardBlob;
|
||||
window.utils = realUtils;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
mocksHelper.setup();
|
||||
subject = new ContactsBTExport();
|
||||
subject.setProgressStep(mockProgress);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
mocksHelper.teardown();
|
||||
});
|
||||
|
||||
test('Calling with error', function(done) {
|
||||
var contacts = [mockContact1, mockContact2];
|
||||
subject.setContactsToExport(contacts);
|
||||
subject.doExport(function onFinish(error, exported, isRecoverable) {
|
||||
assert.isNotNull(error);
|
||||
assert.equal(error.reason, 'noSpace');
|
||||
assert.equal(0, exported);
|
||||
assert.equal(isRecoverable, false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
271
gaia/apps/communications/contacts/test/unit/export/generic_export_test.js
Executable file
271
gaia/apps/communications/contacts/test/unit/export/generic_export_test.js
Executable file
|
|
@ -0,0 +1,271 @@
|
|||
'use strict';
|
||||
/* global ContactsService */
|
||||
/* global MockContactsList */
|
||||
/* global MockConfirmDialog */
|
||||
/* global ContactsExporter */
|
||||
/* global MockExportStrategy */
|
||||
/* global MockMozContacts */
|
||||
/* global MockMozL10n */
|
||||
/* global MocksHelper */
|
||||
/* global MockLoader */
|
||||
|
||||
requireApp('communications/contacts/services/contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_export_strategy.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_list.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
|
||||
require('/shared/js/fb/fb_reader_utils.js');
|
||||
|
||||
requireApp('communications/contacts/js/export/contacts_exporter.js');
|
||||
|
||||
var realUtils = null;
|
||||
var realStatus = null;
|
||||
var realLoader = null;
|
||||
var real_ = null;
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
} else {
|
||||
realUtils = window.utils;
|
||||
}
|
||||
|
||||
if (!window.status) {
|
||||
window.status = null;
|
||||
} else {
|
||||
realStatus = window.status;
|
||||
}
|
||||
|
||||
if (!navigator.mozL10n) {
|
||||
navigator.mozL10n = null;
|
||||
}
|
||||
|
||||
if (!window._) {
|
||||
window._ = null;
|
||||
}
|
||||
|
||||
var mocksHelperForExporter = new MocksHelper([
|
||||
'Contacts',
|
||||
'ConfirmDialog',
|
||||
'Loader'
|
||||
]).init();
|
||||
|
||||
suite('Contacts Exporter', function() {
|
||||
|
||||
var subject;
|
||||
var ids = ['1', '3'];
|
||||
var realL10n;
|
||||
var menuOverlay;
|
||||
|
||||
function getContactsForIds(ids) {
|
||||
var contacts = MockContactsList();
|
||||
|
||||
var result = [];
|
||||
|
||||
ids.forEach(function onId(id) {
|
||||
for (var i = 0; i < contacts.length; i++) {
|
||||
if (contacts[i].id == id) {
|
||||
result.push(contacts[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
realLoader = window.Loader;
|
||||
window.Loader = MockLoader;
|
||||
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
|
||||
sinon.spy(MockExportStrategy, 'shouldShowProgress');
|
||||
sinon.spy(MockExportStrategy, 'doExport');
|
||||
sinon.spy(MockExportStrategy, 'hasDeterminativeProgress');
|
||||
sinon.spy(MockExportStrategy, 'setProgressStep');
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = {};
|
||||
}
|
||||
window.utils.time = {
|
||||
pretty: function(date) {
|
||||
return date;
|
||||
}
|
||||
};
|
||||
window.utils.overlay = {
|
||||
show: function() {
|
||||
return {
|
||||
setTotal: function(l) {}
|
||||
};
|
||||
},
|
||||
hide: function() {},
|
||||
showMenu: function() {}
|
||||
};
|
||||
window.utils.status = {
|
||||
show: function(msg) {},
|
||||
hide: function() {}
|
||||
};
|
||||
sinon.spy(window.utils.status, 'show');
|
||||
|
||||
mocksHelperForExporter.suiteSetup();
|
||||
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.navigator.mozL10n = realL10n;
|
||||
window.Loader = realLoader;
|
||||
|
||||
MockExportStrategy.shouldShowProgress.restore();
|
||||
MockExportStrategy.doExport.restore();
|
||||
MockExportStrategy.hasDeterminativeProgress.restore();
|
||||
MockExportStrategy.setProgressStep.restore();
|
||||
mocksHelperForExporter.suiteTeardown();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(ContactsService, 'getAll', function(cb) {
|
||||
var contacts = MockContactsList();
|
||||
setTimeout(function() {
|
||||
cb(null, contacts);
|
||||
});
|
||||
});
|
||||
menuOverlay = document.createElement('form');
|
||||
menuOverlay.innerHTML = '<menu>' +
|
||||
'<button data-l10n-id="cancel" id="cancel-overlay">Cancel</button>' +
|
||||
'</menu>';
|
||||
document.body.appendChild(menuOverlay);
|
||||
|
||||
subject = new ContactsExporter(MockExportStrategy);
|
||||
|
||||
MockExportStrategy.shouldShowProgress.reset();
|
||||
MockExportStrategy.doExport.reset();
|
||||
MockExportStrategy.hasDeterminativeProgress.reset();
|
||||
MockExportStrategy.setProgressStep.reset();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
menuOverlay.parentNode.removeChild(menuOverlay);
|
||||
});
|
||||
|
||||
test('Correct initialization given an array of ids', function(done) {
|
||||
subject.init(ids, function onInitDone(contacts) {
|
||||
var expectedContacts = getContactsForIds(ids);
|
||||
assert.lengthOf(contacts, 2);
|
||||
assert.notStrictEqual(expectedContacts, contacts);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Strategy with deterministic progress >', function() {
|
||||
|
||||
setup(function(done) {
|
||||
subject.init(ids, function onInitDone(contacts) {
|
||||
subject.start();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Progress bar is shown', function() {
|
||||
assert.ok(MockExportStrategy.shouldShowProgress.calledOnce);
|
||||
});
|
||||
|
||||
test('Export is attempted', function() {
|
||||
assert.ok(MockExportStrategy.doExport.calledOnce);
|
||||
});
|
||||
|
||||
test('The progress type is checked', function() {
|
||||
assert.ok(MockExportStrategy.hasDeterminativeProgress.calledOnce);
|
||||
});
|
||||
|
||||
test('Progress bar updates value', function() {
|
||||
assert.ok(MockExportStrategy.setProgressStep.calledOnce);
|
||||
});
|
||||
|
||||
test('Status shown', function() {
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Strategy with no deterministic progress >', function() {
|
||||
|
||||
setup(function(done) {
|
||||
subject.init(ids, function onInitDone(contacts) {
|
||||
MockExportStrategy.determinativeValue = false;
|
||||
subject.start();
|
||||
done();
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
MockExportStrategy.determinativeValue = true;
|
||||
});
|
||||
|
||||
test('Progress bar is shown', function() {
|
||||
assert.ok(MockExportStrategy.shouldShowProgress.calledOnce);
|
||||
});
|
||||
|
||||
test('Export is attempted', function() {
|
||||
assert.ok(MockExportStrategy.doExport.calledOnce);
|
||||
});
|
||||
|
||||
test('The progress type is checked', function() {
|
||||
assert.ok(MockExportStrategy.hasDeterminativeProgress.calledOnce);
|
||||
});
|
||||
|
||||
test('Progress bar never updated', function() {
|
||||
assert.ok(MockExportStrategy.setProgressStep.callCount === 0);
|
||||
});
|
||||
|
||||
test('Status shown', function() {
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Error handling >', function() {
|
||||
var error,
|
||||
errorName;
|
||||
|
||||
setup(function(done) {
|
||||
sinon.spy(MockConfirmDialog, 'show');
|
||||
subject.init(ids, function onInitDone(contacts) {
|
||||
error = {
|
||||
'reason': 'BIGerror'
|
||||
};
|
||||
errorName = 'exportError-' +
|
||||
MockExportStrategy.name + '-' +
|
||||
error.reason;
|
||||
MockExportStrategy.setError(error);
|
||||
subject.start();
|
||||
done();
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
MockConfirmDialog.show.restore();
|
||||
});
|
||||
|
||||
test('Error dialog is called', function() {
|
||||
assert.ok(MockConfirmDialog.show.calledOnce);
|
||||
});
|
||||
|
||||
test('The proper error shows', function() {
|
||||
// errors are called with the structure
|
||||
// {title, error, retry, cancel}
|
||||
assert.equal(MockConfirmDialog.show.args[0][1], errorName);
|
||||
});
|
||||
|
||||
test('Status shown', function() {
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
24
gaia/apps/communications/contacts/test/unit/export/mock_export_utils.js
Executable file
24
gaia/apps/communications/contacts/test/unit/export/mock_export_utils.js
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
/* exported MockContactToVcarBlob, MockGetStorageIfAvailable,
|
||||
MockGetUnusedFilename, MockGetStorageIfAvailableError */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockGetStorageIfAvailable = function(type, size, callback) {
|
||||
callback(navigator.getDeviceStorage());
|
||||
};
|
||||
|
||||
var MockGetStorageIfAvailableError = function(type, size, callback, cbErr) {
|
||||
if (cbErr) {
|
||||
cbErr(0); // Simulate no space error
|
||||
} else {
|
||||
callback(navigator.getDeviceStorage());
|
||||
}
|
||||
};
|
||||
|
||||
var MockGetUnusedFilename = function(storage, filename, callback) {
|
||||
callback(filename);
|
||||
};
|
||||
|
||||
var MockContactToVcarBlob = function(contacts, callback) {
|
||||
callback({ size: contacts.length });
|
||||
};
|
||||
223
gaia/apps/communications/contacts/test/unit/export/sd_test.js
Executable file
223
gaia/apps/communications/contacts/test/unit/export/sd_test.js
Executable file
|
|
@ -0,0 +1,223 @@
|
|||
/* globals ContactsSDExport, MockgetDeviceStorage, MockGetStorageIfAvailable,
|
||||
MockGetStorageIfAvailableError, MockGetUnusedFilename */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('communications/contacts/js/export/sd.js');
|
||||
requireApp('communications/contacts/test/unit/mock_get_device_storage.js');
|
||||
requireApp('communications/contacts/test/unit/export/mock_export_utils.js');
|
||||
|
||||
suite('Sd export', function() {
|
||||
|
||||
var subject;
|
||||
var realDeviceStorage = null;
|
||||
var c1 = {
|
||||
familyName: ['foo'],
|
||||
givenName: ['bar']
|
||||
};
|
||||
var c2 = { givenName: ['bar'] };
|
||||
var c3 = { familyName: ['foo'] };
|
||||
var c4 = {};
|
||||
|
||||
var updateSpy = null;
|
||||
var progressMock = function dummy() {};
|
||||
var realContactToVcard = null;
|
||||
var real_ = null;
|
||||
var realgetStorageIfAvailable = null;
|
||||
var realgetUnusedFilename = null;
|
||||
var menuOverlay = null;
|
||||
|
||||
suiteSetup(function() {
|
||||
// Device storage mock
|
||||
realDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockgetDeviceStorage;
|
||||
|
||||
// L10n mock
|
||||
real_ = window._;
|
||||
window._ = function() {};
|
||||
|
||||
// getStorageIfAvailable mock
|
||||
realgetStorageIfAvailable = window.getStorageIfAvailable;
|
||||
window.getStorageIfAvailable = MockGetStorageIfAvailable;
|
||||
|
||||
// getUnusedFilename mock
|
||||
realgetUnusedFilename = window.getUnusedFilename;
|
||||
window.getUnusedFilename = MockGetUnusedFilename;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.getDeviceStorage = realDeviceStorage;
|
||||
window._ = real_;
|
||||
window.getStorageIfAvailable = realgetStorageIfAvailable;
|
||||
window.getUnusedFilename = realgetUnusedFilename;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
menuOverlay = document.createElement('form');
|
||||
menuOverlay.innerHTML = '<menu>' +
|
||||
'<button data-l10n-id="cancel" id="cancel-overlay">Cancel</button>' +
|
||||
'</menu>';
|
||||
document.body.appendChild(menuOverlay);
|
||||
subject = new ContactsSDExport();
|
||||
subject.setProgressStep(progressMock);
|
||||
realContactToVcard = window.ContactToVcard;
|
||||
window.ContactToVcard = function() {};
|
||||
updateSpy = this.sinon.stub(
|
||||
window,
|
||||
'ContactToVcard',
|
||||
function(contacts, append, finish) {
|
||||
finish();
|
||||
append(' ', contacts.length);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.ContactToVcard = realContactToVcard;
|
||||
menuOverlay.parentNode.removeChild(menuOverlay);
|
||||
});
|
||||
|
||||
test('Calling with 1 contact', function(done) {
|
||||
subject.setContactsToExport([c1]);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
done(function() {
|
||||
assert.equal(false, subject.hasDeterminativeProgress());
|
||||
assert.equal(1, updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(1, exported);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with 1 contact with no given name', function(done) {
|
||||
subject.setContactsToExport([c2]);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
done(function() {
|
||||
assert.equal(false, subject.hasDeterminativeProgress());
|
||||
assert.equal(1, updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(1, exported);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with 1 contact with no family name', function(done) {
|
||||
subject.setContactsToExport([c3]);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
done(function() {
|
||||
assert.equal(false, subject.hasDeterminativeProgress());
|
||||
assert.equal(1, updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(1, exported);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with several contacts', function(done) {
|
||||
var contacts = [c1, c2, c3, c4];
|
||||
|
||||
subject.setContactsToExport(contacts);
|
||||
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
done(function() {
|
||||
assert.equal(1, updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(contacts.length, exported);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with cancel flag activated', function(done) {
|
||||
subject.setContactsToExport([c1]);
|
||||
subject.cancelExport();
|
||||
subject.doExport(function onFinish(error, exported, msg) {
|
||||
done(function() {
|
||||
assert.equal(1, updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(exported, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Sd export error', function() {
|
||||
|
||||
var subject;
|
||||
var realDeviceStorage = null;
|
||||
var c1 = {
|
||||
familyName: ['foo'],
|
||||
givenName: ['bar']
|
||||
};
|
||||
|
||||
var updateSpy = null;
|
||||
var progressMock = function dummy() {};
|
||||
var realContactToVcard = null;
|
||||
var real_ = null;
|
||||
var realgetStorageIfAvailable = null;
|
||||
var realgetUnusedFilename = null;
|
||||
var menuOverlay = null;
|
||||
|
||||
suiteSetup(function() {
|
||||
// Device storage mock
|
||||
realDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockgetDeviceStorage;
|
||||
|
||||
// L10n mock
|
||||
real_ = window._;
|
||||
window._ = function() {};
|
||||
|
||||
// getStorageIfAvailable mock
|
||||
realgetStorageIfAvailable = window.getStorageIfAvailable;
|
||||
window.getStorageIfAvailable = MockGetStorageIfAvailableError;
|
||||
|
||||
// getUnusedFilename mock
|
||||
realgetUnusedFilename = window.getUnusedFilename;
|
||||
window.getUnusedFilename = MockGetUnusedFilename;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.getDeviceStorage = realDeviceStorage;
|
||||
window._ = real_;
|
||||
window.getStorageIfAvailable = realgetStorageIfAvailable;
|
||||
window.getUnusedFilename = realgetUnusedFilename;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
menuOverlay = document.createElement('form');
|
||||
menuOverlay.innerHTML = '<menu>' +
|
||||
'<button data-l10n-id="cancel" id="cancel-overlay">Cancel</button>' +
|
||||
'</menu>';
|
||||
document.body.appendChild(menuOverlay);
|
||||
subject = new ContactsSDExport();
|
||||
subject.setProgressStep(progressMock);
|
||||
realContactToVcard = window.ContactToVcard;
|
||||
window.ContactToVcard = function() {};
|
||||
updateSpy = this.sinon.stub(
|
||||
window,
|
||||
'ContactToVcard',
|
||||
function(contacts, append, finish) {
|
||||
finish();
|
||||
append(' ', contacts.length);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.ContactToVcard = realContactToVcard;
|
||||
menuOverlay.parentNode.removeChild(menuOverlay);
|
||||
});
|
||||
|
||||
test('Calling with error', function(done) {
|
||||
subject.setContactsToExport([c1]);
|
||||
subject.doExport(function onFinish(error, exported, isRecoverable) {
|
||||
assert.isNotNull(error);
|
||||
assert.equal(error.reason, 'noSpace');
|
||||
assert.equal(0, exported);
|
||||
assert.equal(isRecoverable, true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
224
gaia/apps/communications/contacts/test/unit/export/sim_test.js
Executable file
224
gaia/apps/communications/contacts/test/unit/export/sim_test.js
Executable file
|
|
@ -0,0 +1,224 @@
|
|||
'use strict';
|
||||
/* global ContactsSIMExport */
|
||||
/* global MockMozContacts */
|
||||
|
||||
requireApp('communications/contacts/services/contacts.js');
|
||||
requireApp('communications/contacts/js/export/sim.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
|
||||
suite('Sim export', function() {
|
||||
var realMozContacts = null;
|
||||
var c1 = {}, c2 = {};
|
||||
var progressMock = function dummy() {};
|
||||
|
||||
var iccContactId = '1234567';
|
||||
var iccid = '999999999';
|
||||
|
||||
function getIccContactUrl(iccid, iccContactId) {
|
||||
return 'urn:uuid:' + iccid + '-' + iccContactId;
|
||||
}
|
||||
|
||||
function setupManagerAndSubject(toExport) {
|
||||
var iccManager = new IccManager();
|
||||
var updateSpy = sinon.spy(iccManager, 'updateContact');
|
||||
var subject = new ContactsSIMExport(iccManager);
|
||||
subject.setProgressStep(progressMock);
|
||||
subject.setContactsToExport(toExport);
|
||||
|
||||
return {
|
||||
subject: subject,
|
||||
manager: iccManager,
|
||||
updateSpy: updateSpy
|
||||
};
|
||||
}
|
||||
|
||||
function IccManager() {
|
||||
this.calledCount = 0,
|
||||
this.faulty = false,
|
||||
this.simFull = false,
|
||||
this.updateContact = function(type, contact) {
|
||||
var self = this;
|
||||
return {
|
||||
result: {
|
||||
id: iccContactId
|
||||
},
|
||||
set onsuccess(cb) {
|
||||
self.calledCount++;
|
||||
if ((!self.faulty && !self.simFull) || self.calledCount % 2 !== 0) {
|
||||
window.setTimeout(cb);
|
||||
}
|
||||
},
|
||||
set onerror(cb) {
|
||||
if (self.faulty && self.calledCount % 2 === 0) {
|
||||
this.error = {
|
||||
name: 'ContactTypeNotSupported'
|
||||
};
|
||||
window.setTimeout(function() {
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
}.bind(this));
|
||||
return;
|
||||
}
|
||||
if (self.simFull && self.calledCount % 2 === 0) {
|
||||
this.error = {
|
||||
name: 'NoFreeRecordFound'
|
||||
};
|
||||
window.setTimeout(function() {
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.iccInfo = {
|
||||
iccid: iccid
|
||||
};
|
||||
}
|
||||
|
||||
var iccContactIdUrl = {
|
||||
type: ['source', 'sim'],
|
||||
value: getIccContactUrl(iccid, iccContactId)
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozContacts = realMozContacts;
|
||||
});
|
||||
|
||||
test('Calling with 1 contact', function(done) {
|
||||
var obj = setupManagerAndSubject([c1]);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.equal(false, obj.subject.hasDeterminativeProgress());
|
||||
assert.ok(obj.updateSpy.calledOnce);
|
||||
assert.isNull(error);
|
||||
assert.equal(1, exported);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with several contacts', function(done) {
|
||||
var contacts = [c1, c2];
|
||||
var obj = setupManagerAndSubject(contacts);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.ok(obj.subject.hasDeterminativeProgress());
|
||||
assert.equal(contacts.length, obj.updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(contacts.length, exported);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('If SIM Card is full the error is reported properly', function(done) {
|
||||
var contacts = [c1, c2];
|
||||
|
||||
var obj = setupManagerAndSubject(contacts);
|
||||
obj.manager.simFull = true;
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported, recoverable) {
|
||||
assert.ok(obj.subject.hasDeterminativeProgress());
|
||||
assert.equal(error.reason, 'NoFreeRecordFound');
|
||||
assert.equal(recoverable, false);
|
||||
assert.equal(1, exported);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Recovering from error updating in IccManager', function(done) {
|
||||
var contacts = [c1, c2, c1, c2];
|
||||
var obj = setupManagerAndSubject(contacts);
|
||||
|
||||
obj.manager.faulty = true;
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.ok(obj.subject.hasDeterminativeProgress());
|
||||
assert.equal(contacts.length, obj.updateSpy.callCount);
|
||||
// We do not have an error
|
||||
assert.isNull(error);
|
||||
// The number of exported contacts is not the total
|
||||
assert.equal(contacts.length / 2, exported);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Updating a Contact that has not a previous iccContactId. URL created',
|
||||
function(done) {
|
||||
var obj = setupManagerAndSubject([c1]);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.deepEqual(c1.url[0], iccContactIdUrl);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Updating a Contact that has a previous iccContactId. URL kept as it is',
|
||||
function(done) {
|
||||
|
||||
var contactToExport = {
|
||||
url: [
|
||||
iccContactIdUrl
|
||||
]
|
||||
};
|
||||
var obj = setupManagerAndSubject([contactToExport]);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.equal(contactToExport.url.length, 1);
|
||||
assert.deepEqual(contactToExport.url[0], iccContactIdUrl);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
'Updating a Contact that has a previous iccContactId from a different SIM',
|
||||
function(done) {
|
||||
var contactToExport = {
|
||||
url: [{
|
||||
type: ['source', 'sim']
|
||||
}]
|
||||
};
|
||||
contactToExport.url[0].value = getIccContactUrl('98765', '77777');
|
||||
var contactToExportOriginalUrl = contactToExport.url[0];
|
||||
|
||||
var obj = setupManagerAndSubject([contactToExport]);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.equal(contactToExport.url.length, 2);
|
||||
assert.deepEqual(contactToExport.url[0], contactToExportOriginalUrl);
|
||||
assert.deepEqual(contactToExport.url[1], iccContactIdUrl);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Calling with cancel flag activated', function(done) {
|
||||
var contacts = [c1, c2, c1, c2, c1];
|
||||
var exportedContacts = 2;
|
||||
var callNum = 0;
|
||||
// Replacing the progress function to allow simulating the click of the
|
||||
// cancel button on the nth call
|
||||
var progressMockForCancel = function() {
|
||||
callNum++;
|
||||
if (callNum === exportedContacts) {
|
||||
obj.subject.cancelExport();
|
||||
}
|
||||
};
|
||||
|
||||
var obj = setupManagerAndSubject(contacts);
|
||||
obj.subject.setProgressStep(progressMockForCancel);
|
||||
|
||||
obj.subject.doExport(function onFinish(error, exported) {
|
||||
assert.equal(exportedContacts, obj.updateSpy.callCount);
|
||||
assert.isNull(error);
|
||||
assert.equal(exportedContacts, exported);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
455
gaia/apps/communications/contacts/test/unit/fb_data_test.js
Executable file
455
gaia/apps/communications/contacts/test/unit/fb_data_test.js
Executable file
|
|
@ -0,0 +1,455 @@
|
|||
'use strict';
|
||||
/* global fb */
|
||||
/* global MockDatastore */
|
||||
/* global MockNavigatorDatastore */
|
||||
/* global MockPhoneNumberService */
|
||||
/* global SimplePhoneMatcher */
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/js/simple_phone_matcher.js');
|
||||
require('/shared/js/fb/fb_request.js');
|
||||
require('/shared/js/contacts/import/facebook/fb_data.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_datastore.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_phone_number_service.js');
|
||||
|
||||
var realDatastore, realPhoneNumberService;
|
||||
|
||||
if (!window.realDatastore) {
|
||||
window.realDatastore = null;
|
||||
}
|
||||
|
||||
if (!window.realPhoneNumberService) {
|
||||
window.realPhoneNumberService = null;
|
||||
}
|
||||
|
||||
suite('Facebook datastore suite', function() {
|
||||
var mockUid = '456789';
|
||||
var mockTel = '+34676767676';
|
||||
|
||||
function createFbContact(uid, name, tel) {
|
||||
return {
|
||||
uid: uid,
|
||||
name: [name],
|
||||
tel: [{
|
||||
type: ['other'],
|
||||
value: tel
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
var MockFbFriendData = createFbContact(mockUid, 'Jose Manuel', mockTel);
|
||||
|
||||
function assertRemove(obj) {
|
||||
var uid = obj.uid;
|
||||
var index = fb.contacts.dsIndex;
|
||||
|
||||
assert.isUndefined(MockDatastore._records[uid]);
|
||||
|
||||
var variants = SimplePhoneMatcher.generateVariants(obj.tel[0].value);
|
||||
|
||||
variants.forEach(function(aTelVariant) {
|
||||
assert.isUndefined(index.byTel[aTelVariant]);
|
||||
});
|
||||
}
|
||||
|
||||
function assertFound(req) {
|
||||
var res = req.result;
|
||||
assert.isNotNull(res);
|
||||
assert.equal(res.uid, mockUid);
|
||||
}
|
||||
|
||||
function assertNotFound(req) {
|
||||
var res = req.result;
|
||||
assert.isNull(res);
|
||||
}
|
||||
|
||||
function assertNewIndex() {
|
||||
assert.equal(Object.keys(MockDatastore._records).length, 1,
|
||||
'Datastore must contain the persisted index');
|
||||
var index = fb.contacts.dsIndex;
|
||||
// Checking that the stored index is the same as the in memory index
|
||||
assert.deepEqual(index, MockDatastore._records[1]);
|
||||
|
||||
assert.equal(Object.keys(index.byTel).length, 0);
|
||||
}
|
||||
|
||||
function assertAdded(friend) {
|
||||
var uid = friend.uid;
|
||||
|
||||
var index = fb.contacts.dsIndex;
|
||||
|
||||
assert.equal(MockDatastore._records[uid].uid, uid);
|
||||
|
||||
// Testing that all telVariants have been captured in the index
|
||||
var mockTelVariants = SimplePhoneMatcher.generateVariants(
|
||||
friend.tel[0].value);
|
||||
mockTelVariants.forEach(function(aTelVariant) {
|
||||
assert.equal(index.byTel[aTelVariant], uid);
|
||||
});
|
||||
}
|
||||
|
||||
function doRemove(objToRemove, flush, done) {
|
||||
var toRemoveUid = objToRemove.uid;
|
||||
var toRemoveTel = objToRemove.tel[0].value;
|
||||
|
||||
var saveReq = fb.contacts.save(objToRemove);
|
||||
saveReq.onsuccess = function() {
|
||||
// Precondition
|
||||
assertAdded(objToRemove);
|
||||
// It is needed to flush as add does not automatically flush the index
|
||||
var flushReq = fb.contacts.flush();
|
||||
flushReq.onsuccess = function() {
|
||||
var req = fb.contacts.remove(toRemoveUid, flush);
|
||||
req.onsuccess = function() {
|
||||
if (flush) {
|
||||
assert.isUndefined(MockDatastore._records['1'].byTel[toRemoveTel]);
|
||||
}
|
||||
else {
|
||||
assert.equal(MockDatastore._records['1'].byTel[toRemoveTel],
|
||||
toRemoveUid);
|
||||
}
|
||||
assertRemove(objToRemove);
|
||||
done();
|
||||
};
|
||||
};
|
||||
flushReq.onerror = errorNotExpected.bind(flushReq, done);
|
||||
};
|
||||
saveReq.onerror = errorNotExpected.bind(saveReq, done);
|
||||
}
|
||||
|
||||
function errorNotExpected(done) {
|
||||
done(function() {
|
||||
assert.fail('Error not expected: ' + this.error.name);
|
||||
});
|
||||
}
|
||||
|
||||
function successNotExpected(done) {
|
||||
done(function() {
|
||||
assert.fail('Succcess not expected');
|
||||
});
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
realDatastore = navigator.getDataStores;
|
||||
navigator.getDataStores = MockNavigatorDatastore.getDataStores;
|
||||
MockNavigatorDatastore._records = {};
|
||||
|
||||
realPhoneNumberService = navigator.mozPhoneNumberService;
|
||||
navigator.mozPhoneNumberService = MockPhoneNumberService;
|
||||
});
|
||||
|
||||
|
||||
test('Initialization phase and index creation', function(done) {
|
||||
fb.contacts.init(function() {
|
||||
// When initialized index must be created
|
||||
assertNewIndex();
|
||||
// Testing that the DS is correctly assigned
|
||||
assert.equal(MockDatastore.name, fb.contacts.datastore.name);
|
||||
done();
|
||||
}, function(err) {
|
||||
done(function() {
|
||||
assert.fail('Error reported by initialization!: ' + err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Adding to the datastore indexes data correctly', function(done) {
|
||||
var req = fb.contacts.save(MockFbFriendData);
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertAdded(MockFbFriendData);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Adding to the datastore an existing obj raises error', function(done) {
|
||||
var req = fb.contacts.save(MockFbFriendData);
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, fb.contacts.ALREADY_EXISTS);
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore. By tel', function(done) {
|
||||
var req = fb.contacts.getByPhone(mockTel);
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertFound(req);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore. By tel not normalized',
|
||||
function(done) {
|
||||
var req = fb.contacts.getByPhone('67(67)67-67 6');
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertFound(req);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore. By tel. Not found',
|
||||
function(done) {
|
||||
var req = fb.contacts.getByPhone('987654321');
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertNotFound(req);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
|
||||
test('Retrieving a FB Friend from the datastore. By uid', function(done) {
|
||||
var req = fb.contacts.get(mockUid);
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertFound(req);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore by UID. Not found',
|
||||
function(done) {
|
||||
var req = fb.contacts.get('hhhhh');
|
||||
|
||||
req.onsuccess = function() {
|
||||
assertNotFound(req);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Removing a FB Friend from the datastore. No flush', function(done) {
|
||||
var objToRemove = createFbContact('678903', 'Carlos', '+34699999888');
|
||||
|
||||
doRemove(objToRemove, false, done);
|
||||
});
|
||||
|
||||
test('Removing a FB Friend from the datastore. Not Found', function(done) {
|
||||
var objToRemove = createFbContact('99999', 'Carlos', '+34699999888');
|
||||
|
||||
var req = fb.contacts.remove(objToRemove);
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, fb.contacts.UID_NOT_FOUND);
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Flushing the data', function(done) {
|
||||
var req = fb.contacts.flush();
|
||||
|
||||
req.onsuccess = function() {
|
||||
// There has been a flush, thus the "persistent" index is up to date
|
||||
assert.deepEqual(fb.contacts.dsIndex, MockDatastore._records[1]);
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Removing a FB Friend from the datastore. Flush', function(done) {
|
||||
var objToRemove = createFbContact('999999', 'Pedro', '+34611789654');
|
||||
|
||||
doRemove(objToRemove, true, done);
|
||||
});
|
||||
|
||||
test('Updating a FB friend from the datastore', function(done) {
|
||||
var updatedObj = createFbContact(MockFbFriendData.uid,
|
||||
MockFbFriendData.name, '+34657890876');
|
||||
|
||||
var req = fb.contacts.update(updatedObj);
|
||||
|
||||
req.onsuccess = function() {
|
||||
var index = fb.contacts.dsIndex;
|
||||
|
||||
assert.deepEqual(updatedObj,
|
||||
MockDatastore._records[MockFbFriendData.uid]);
|
||||
|
||||
var telVariants = SimplePhoneMatcher.generateVariants(
|
||||
updatedObj.tel[0].value);
|
||||
// Testing that all telVariants have been captured in the index
|
||||
telVariants.forEach(function(aTelVariant) {
|
||||
assert.equal(index.byTel[aTelVariant], MockFbFriendData.uid);
|
||||
});
|
||||
|
||||
var telMockVariants = SimplePhoneMatcher.generateVariants(
|
||||
MockFbFriendData.tel[0].value);
|
||||
// Testing that reindexing was ok
|
||||
telMockVariants.forEach(function(aTelVariant) {
|
||||
assert.isUndefined(index.byTel[aTelVariant]);
|
||||
});
|
||||
done();
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Updating a FB friend from the datastore. UID does not exist',
|
||||
function(done) {
|
||||
var updatedObj = createFbContact('9999',
|
||||
MockFbFriendData.name, '+34657890876');
|
||||
|
||||
var req = fb.contacts.update(updatedObj);
|
||||
|
||||
successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UIDNotFound');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Clearing all FB Data', function(done) {
|
||||
var clearReq = fb.contacts.clear();
|
||||
|
||||
clearReq.onsuccess = function() {
|
||||
assertNewIndex();
|
||||
done();
|
||||
};
|
||||
clearReq.onerror = errorNotExpected.bind(clearReq, done);
|
||||
});
|
||||
|
||||
test('If datastore is not found error is reported correctly', function(done) {
|
||||
MockNavigatorDatastore._notFound = true;
|
||||
MockDatastore._inError = false;
|
||||
fb.contacts.restart();
|
||||
|
||||
fb.contacts.init(successNotExpected.bind(null, done),
|
||||
function(err) {
|
||||
assert.equal(err.name, 'DatastoreNotFound');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore by UID. DS is in Error',
|
||||
function(done) {
|
||||
MockNavigatorDatastore._notFound = false;
|
||||
MockDatastore._inError = true;
|
||||
fb.contacts.restart();
|
||||
|
||||
var req = fb.contacts.get('hhhhh');
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Retrieving a FB Friend from the datastore by tel. DS is in Error',
|
||||
function(done) {
|
||||
MockNavigatorDatastore._notFound = false;
|
||||
MockDatastore._inError = true;
|
||||
|
||||
var req = fb.contacts.getByPhone('hhhhh');
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Adding a FB Friend to the Datastore. DS is in Error',
|
||||
function(done) {
|
||||
MockNavigatorDatastore._notFound = false;
|
||||
MockDatastore._inError = true;
|
||||
|
||||
var req = fb.contacts.save(MockFbFriendData);
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Updating a FB Friend to the Datastore. DS is in Error',
|
||||
function(done) {
|
||||
MockNavigatorDatastore._notFound = false;
|
||||
MockDatastore._inError = true;
|
||||
|
||||
var req = fb.contacts.update({});
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
test('Removing a FB Friend from the Datastore. DS is in Error',
|
||||
function(done) {
|
||||
MockNavigatorDatastore._notFound = false;
|
||||
MockDatastore._inError = true;
|
||||
|
||||
var req = fb.contacts.remove('45678');
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
suite('Initialization phase', function() {
|
||||
setup(function() {
|
||||
this.sinon.useFakeTimers();
|
||||
|
||||
// other tests are not independent, so let's restart in setup too
|
||||
fb.contacts.restart();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fb.contacts.restart();
|
||||
});
|
||||
|
||||
test('is bypassed if DataStore API is unavailable',
|
||||
function() {
|
||||
var savedAPI = navigator.getDataStores;
|
||||
navigator.getDataStores = null;
|
||||
|
||||
var success = sinon.stub();
|
||||
var error = sinon.stub();
|
||||
fb.contacts.init(success, error);
|
||||
|
||||
this.sinon.clock.tick();
|
||||
|
||||
sinon.assert.notCalled(success);
|
||||
sinon.assert.calledWith(error, { name: 'DatastoreNotFound' });
|
||||
|
||||
navigator.getDataStores = savedAPI;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.getDataStores = realDatastore;
|
||||
navigator.mozPhoneNumberService = realPhoneNumberService;
|
||||
});
|
||||
|
||||
});
|
||||
172
gaia/apps/communications/contacts/test/unit/fb_reader_utils_test.js
Executable file
172
gaia/apps/communications/contacts/test/unit/fb_reader_utils_test.js
Executable file
|
|
@ -0,0 +1,172 @@
|
|||
'use strict';
|
||||
/* global fb */
|
||||
/* global MockFbContactsObj */
|
||||
/* global MockMozContactsObj */
|
||||
|
||||
require('/shared/js/fb/fb_reader_utils.js');
|
||||
require('/shared/js/fb/fb_request.js');
|
||||
require('/shared/test/unit/mocks/mock_fb_data_reader.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
|
||||
var realFbContacts, realMozContacts;
|
||||
|
||||
if (!window.realFbContacts) {
|
||||
window.realFbContacts = null;
|
||||
}
|
||||
|
||||
if (!window.realMozContacts) {
|
||||
window.realMozContacts = null;
|
||||
}
|
||||
|
||||
suite('Facebook data reader utils suite', function() {
|
||||
var uid = '999999';
|
||||
var localName = 'José Carlos Fdez Avila';
|
||||
var localGivenName = 'José Carlos';
|
||||
var localFamilyName = 'Fdez Avila';
|
||||
var localNumber = '676767676';
|
||||
var fbNumber = '+34655555555';
|
||||
|
||||
var localContact = {
|
||||
id: '12345',
|
||||
name: [localName],
|
||||
givenName: [localGivenName],
|
||||
familyName: [localFamilyName],
|
||||
category: ['favorite', 'facebook', 'fb_not_linked', uid],
|
||||
tel: [{
|
||||
type: ['mobile'],
|
||||
value: localNumber
|
||||
}]
|
||||
};
|
||||
|
||||
var fbFriendData = {
|
||||
uid: uid,
|
||||
name: ['Carlos Fdez'],
|
||||
givenName: ['Carlos'],
|
||||
familyName: ['Fdez'],
|
||||
tel: [{
|
||||
type: ['personal'],
|
||||
value: fbNumber
|
||||
}],
|
||||
email: [{
|
||||
type: ['personal'],
|
||||
value: 'jj@@jj.com'
|
||||
}],
|
||||
photo: [{}]
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realFbContacts = fb.contacts;
|
||||
fb.contacts = new MockFbContactsObj(fbFriendData);
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = new MockMozContactsObj([localContact]);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
fb.contacts = realFbContacts;
|
||||
navigator.mozContacts = realMozContacts;
|
||||
});
|
||||
|
||||
test('It is Facebook Contact', function() {
|
||||
assert.isTrue(fb.isFbContact(localContact));
|
||||
});
|
||||
|
||||
test('It is not Facebook Contact', function() {
|
||||
var currentCat = localContact.category;
|
||||
localContact.category = null;
|
||||
assert.isTrue(!fb.isFbContact(localContact));
|
||||
localContact.category = currentCat;
|
||||
});
|
||||
|
||||
test('Get Friend UID', function() {
|
||||
assert.equal(fb.getFriendUid(localContact), uid);
|
||||
});
|
||||
|
||||
test('It is Facebook Contact: Not linked', function() {
|
||||
assert.isTrue(fb.isFbContact(localContact));
|
||||
assert.isFalse(fb.isFbLinked(localContact));
|
||||
});
|
||||
|
||||
test('Get LinkedTo. Not Linked', function() {
|
||||
assert.isUndefined(fb.getLinkedTo(localContact));
|
||||
});
|
||||
|
||||
test('Is Facebook Contact: Linked', function() {
|
||||
localContact.category[2] = 'fb_linked';
|
||||
assert.isTrue(fb.isFbLinked(localContact));
|
||||
});
|
||||
|
||||
test('Get LinkedTo. Linked', function() {
|
||||
localContact.category[2] = 'fb_linked';
|
||||
assert.equal(fb.getLinkedTo(localContact), uid);
|
||||
});
|
||||
|
||||
function assertFbMergedData(result) {
|
||||
assert.equal(result.givenName[0], localGivenName);
|
||||
assert.equal(result.familyName[0], localFamilyName);
|
||||
assert.equal(result.name[0], localName);
|
||||
assert.isTrue(Array.isArray(result.tel) && result.tel.length === 2);
|
||||
assert.equal(result.tel[0].value, localNumber);
|
||||
assert.equal(result.tel[1].value, fbNumber);
|
||||
assert.isTrue(Array.isArray(result.photo) && result.photo.length === 1);
|
||||
}
|
||||
|
||||
function errorNotExpected(done) {
|
||||
done(function() {
|
||||
assert.fail('Error not expected: ' + this.error.name);
|
||||
});
|
||||
}
|
||||
|
||||
function successNotExpected(done) {
|
||||
done(function() {
|
||||
assert.fail('Succcess not expected');
|
||||
});
|
||||
}
|
||||
|
||||
test('Get Data from Facebook. Linked Contact', function(done) {
|
||||
var req = fb.getData(localContact);
|
||||
|
||||
req.onsuccess = function() {
|
||||
done(function() {
|
||||
var result = req.result;
|
||||
assertFbMergedData(result);
|
||||
});
|
||||
};
|
||||
|
||||
req.onerror = errorNotExpected.bind(req, done);
|
||||
});
|
||||
|
||||
test('Get Contact by Number', function(done) {
|
||||
fb.getContactByNumber(fbNumber, function success(contact) {
|
||||
done(function() {
|
||||
assertFbMergedData(contact);
|
||||
});
|
||||
}, function error(err) {
|
||||
(errorNotExpected.bind(err, done))();
|
||||
});
|
||||
});
|
||||
|
||||
test('Get Contact by Number. In error', function(done) {
|
||||
fb.contacts.inError = true;
|
||||
|
||||
fb.getContactByNumber(fbNumber, function success(contact) {
|
||||
successNotExpected(done);
|
||||
},
|
||||
function error(err) {
|
||||
done(function() {
|
||||
assert.equal(err.name, 'UnknownError');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Get Data from Facebook. In Error', function(done) {
|
||||
var req = fb.getData(localContact);
|
||||
|
||||
req.onsuccess = successNotExpected.bind(null, done);
|
||||
|
||||
req.onerror = function() {
|
||||
assert.equal(req.error.name, 'UnknownError');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
143
gaia/apps/communications/contacts/test/unit/fb_utils_test.js
Executable file
143
gaia/apps/communications/contacts/test/unit/fb_utils_test.js
Executable file
|
|
@ -0,0 +1,143 @@
|
|||
'use strict';
|
||||
|
||||
/* global MockImportStatusData, fb */
|
||||
|
||||
require('/shared/js/contacts/import/facebook/fb_contact_utils.js');
|
||||
require('/shared/js/contacts/import/facebook/fb_utils.js');
|
||||
require('/shared/js/fb/fb_request.js');
|
||||
requireApp('communications/contacts/test/unit/mock_import_status_data.js');
|
||||
|
||||
suite('Fb Utils Tests', function() {
|
||||
var subject;
|
||||
var messageCallback;
|
||||
var pendingSchedule = false, timesToExecute = 0;
|
||||
var realImportStatusData;
|
||||
|
||||
// We need this as sinon.useFaketimers does not support partial stub of
|
||||
// setInterval and we need setTimeout to work as usual
|
||||
function tick(times) {
|
||||
pendingSchedule = true;
|
||||
timesToExecute = times;
|
||||
}
|
||||
|
||||
function resolveLogout(callback) {
|
||||
if (typeof callback !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.setTimeout(callback, 0, {
|
||||
origin: location.origin,
|
||||
data: 'closed',
|
||||
stopImmediatePropagation: function() {}
|
||||
});
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
subject = fb.utils;
|
||||
|
||||
sinon.stub(window, 'open', function() {
|
||||
resolveLogout(messageCallback);
|
||||
|
||||
return {
|
||||
closed: false
|
||||
};
|
||||
});
|
||||
|
||||
sinon.stub(window, 'addEventListener', function(event, cb) {
|
||||
if (event === 'message') {
|
||||
messageCallback = cb;
|
||||
}
|
||||
});
|
||||
|
||||
sinon.stub(window, 'setInterval', function(cb, interval) {
|
||||
if (pendingSchedule === true) {
|
||||
for (var j = 0; j < timesToExecute; j++) {
|
||||
window.setTimeout(cb);
|
||||
}
|
||||
}
|
||||
pendingSchedule = false; timesToExecute = 0;
|
||||
return 1;
|
||||
});
|
||||
|
||||
realImportStatusData = window.ImportStatusData;
|
||||
window.ImportStatusData = MockImportStatusData;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.open.restore();
|
||||
window.addEventListener.restore();
|
||||
window.setInterval.restore();
|
||||
|
||||
window.ImportStatusData = realImportStatusData;
|
||||
});
|
||||
|
||||
|
||||
setup(function() {
|
||||
MockImportStatusData.keys = {
|
||||
'tokenData': {
|
||||
access_token: '1234'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
test('Logout, everything goes well', function(done) {
|
||||
var req = subject.logout();
|
||||
|
||||
req.onsuccess = function(e) {
|
||||
done(function() {
|
||||
assert.ok('everything went well');
|
||||
});
|
||||
};
|
||||
|
||||
req.onerror = done.bind(null, req.error);
|
||||
|
||||
tick(1);
|
||||
});
|
||||
|
||||
|
||||
test('Logout, timeout happens. Error raised', function(done) {
|
||||
window.open.restore();
|
||||
sinon.stub(window, 'open', function() {
|
||||
return {
|
||||
closed: false
|
||||
};
|
||||
});
|
||||
|
||||
var req = subject.logout();
|
||||
|
||||
req.onsuccess = done;
|
||||
|
||||
req.onerror = function() {
|
||||
done(function() {
|
||||
assert.equal(req.error, 'Timeout');
|
||||
});
|
||||
};
|
||||
|
||||
tick(10);
|
||||
});
|
||||
|
||||
|
||||
test('Logout, window is closed. Error raised', function(done) {
|
||||
window.open.restore();
|
||||
sinon.stub(window, 'open', function() {
|
||||
return {
|
||||
closed: true
|
||||
};
|
||||
});
|
||||
|
||||
var req = subject.logout();
|
||||
|
||||
// If onsuccess is called done is called with params and the test fails
|
||||
req.onsuccess = done;
|
||||
|
||||
req.onerror = function() {
|
||||
done(function() {
|
||||
assert.equal(req.error, 'UserCancelled');
|
||||
});
|
||||
};
|
||||
|
||||
tick(1);
|
||||
});
|
||||
|
||||
});
|
||||
8
gaia/apps/communications/contacts/test/unit/helper.js
Executable file
8
gaia/apps/communications/contacts/test/unit/helper.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
/* exported triggerEvent */
|
||||
|
||||
var triggerEvent = function(element, eventName) {
|
||||
var event = document.createEvent('HTMLEvents');
|
||||
event.initEvent(eventName, true, true);
|
||||
element.dispatchEvent(event);
|
||||
};
|
||||
164
gaia/apps/communications/contacts/test/unit/image_loader_test.js
Executable file
164
gaia/apps/communications/contacts/test/unit/image_loader_test.js
Executable file
|
|
@ -0,0 +1,164 @@
|
|||
'use strict';
|
||||
|
||||
/* globals MocksHelper, MockLinkHtml, ImageLoader, UIEvent */
|
||||
|
||||
require('/shared/js/contacts/utilities/image_loader.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_link.html.js');
|
||||
require('/shared/test/unit/mocks/mock_image.js');
|
||||
|
||||
var mocksHelperForImageLoader = new MocksHelper([
|
||||
'Image'
|
||||
]).init();
|
||||
|
||||
suite('Image Loader Test Suite >', function() {
|
||||
|
||||
var mocksHelper = mocksHelperForImageLoader;
|
||||
var imageSpy, imgLoader;
|
||||
mocksHelper.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
imageSpy = this.sinon.spy(window, 'Image');
|
||||
});
|
||||
|
||||
suite('imgsLoading balance >', function() {
|
||||
|
||||
var stopSpy, item;
|
||||
|
||||
suiteSetup(function() {
|
||||
document.body.innerHTML = MockLinkHtml;
|
||||
item = document.querySelector('#friends-list');
|
||||
imgLoader = new ImageLoader('#mainContent',
|
||||
'.block-item:not([data-uuid="#uid#"])');
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
stopSpy = this.sinon.spy(window, 'stop');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
imgLoader.destroy();
|
||||
});
|
||||
|
||||
function simulateImageCallback(evt) {
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent(evt);
|
||||
}
|
||||
|
||||
function dispatchScroll() {
|
||||
var event = new UIEvent('scroll', {
|
||||
view: window,
|
||||
detail: 0
|
||||
});
|
||||
document.querySelector('#mainContent').dispatchEvent(event);
|
||||
}
|
||||
|
||||
test('defaultLoadImage calls new Image()', function() {
|
||||
imgLoader.defaultLoad(item);
|
||||
sinon.assert.calledOnce(imageSpy);
|
||||
});
|
||||
|
||||
test('item marked as visited', function() {
|
||||
simulateImageCallback('onload');
|
||||
assert.equal('true', item.dataset.visited);
|
||||
|
||||
simulateImageCallback('onabort');
|
||||
assert.equal('false', item.dataset.visited);
|
||||
|
||||
simulateImageCallback('onerror');
|
||||
assert.equal('false', item.dataset.visited);
|
||||
});
|
||||
|
||||
test('window.stop() not called without scroll event', function() {
|
||||
simulateImageCallback('onload');
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
|
||||
simulateImageCallback('onabort');
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
|
||||
simulateImageCallback('onerror');
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
});
|
||||
|
||||
test('window.stop() called with one pending request', function() {
|
||||
imgLoader.defaultLoad(item);
|
||||
dispatchScroll();
|
||||
sinon.assert.callCount(stopSpy, 1);
|
||||
});
|
||||
|
||||
test('window.stop() not called after onload', function() {
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent('onload');
|
||||
dispatchScroll();
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
});
|
||||
|
||||
test('window.stop() not called after onabort and onerror', function() {
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent('onabort');
|
||||
dispatchScroll();
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent('onerror');
|
||||
dispatchScroll();
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
});
|
||||
|
||||
test('window.stop() not called after onload and onerror', function() {
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent('onload');
|
||||
imgLoader.defaultLoad(item);
|
||||
imageSpy.lastCall.thisValue.triggerEvent('onerror');
|
||||
dispatchScroll();
|
||||
sinon.assert.callCount(stopSpy, 0);
|
||||
});
|
||||
|
||||
test('image loader not called anymore after unloading', function() {
|
||||
var containerSpy = this.sinon.spy(document.querySelector('#mainContent'),
|
||||
'removeEventListener');
|
||||
var documentSpy = this.sinon.spy(document, 'removeEventListener');
|
||||
imgLoader.defaultLoad(item);
|
||||
imgLoader.unload();
|
||||
sinon.assert.callCount(documentSpy, 1);
|
||||
sinon.assert.callCount(containerSpy, 1);
|
||||
documentSpy.restore();
|
||||
containerSpy.restore();
|
||||
});
|
||||
|
||||
test('image loader not called anymore after pausing', function() {
|
||||
var containerSpy = this.sinon.spy(document.querySelector('#mainContent'),
|
||||
'removeEventListener');
|
||||
var documentSpy = this.sinon.spy(document, 'removeEventListener');
|
||||
imgLoader.defaultLoad(item);
|
||||
window.dispatchEvent(new CustomEvent('image-loader-pause'));
|
||||
sinon.assert.callCount(documentSpy, 1);
|
||||
sinon.assert.callCount(containerSpy, 1);
|
||||
documentSpy.restore();
|
||||
containerSpy.restore();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('imgsLoader resuming >', function() {
|
||||
|
||||
suiteSetup(function() {
|
||||
document.body.innerHTML =
|
||||
'<ol>' +
|
||||
'<li><span data-type="img" data-src="http://www.a.com"></span></li>' +
|
||||
'</ol>';
|
||||
imgLoader = new ImageLoader('ol', 'li');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
imgLoader.destroy();
|
||||
});
|
||||
|
||||
test('resuming calls new Image()', function() {
|
||||
window.dispatchEvent(new CustomEvent('image-loader-resume'));
|
||||
sinon.assert.calledOnce(imageSpy);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
17
gaia/apps/communications/contacts/test/unit/import/.jshintrc
Executable file
17
gaia/apps/communications/contacts/test/unit/import/.jshintrc
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"require",
|
||||
"requireApp",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
/* globals MockNavigatorDatastore, MockDatastoreObj, ContactsDatastore */
|
||||
|
||||
require('/shared/js/contacts/contacts_datastore.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_datastore.js');
|
||||
|
||||
suite('Contacts Datastore', function() {
|
||||
var realDatastore;
|
||||
var datastoreOwner = 'app://gmailprovider.gaiamobile.org/manifest.webapp';
|
||||
|
||||
suiteSetup(function() {
|
||||
var datastore1 = new MockDatastoreObj('contacts', datastoreOwner, null);
|
||||
|
||||
MockNavigatorDatastore._datastores = [
|
||||
datastore1
|
||||
];
|
||||
|
||||
realDatastore = navigator.getDataStores;
|
||||
|
||||
navigator.getDataStores = MockNavigatorDatastore.getDataStores;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.getDataStores = realDatastore;
|
||||
});
|
||||
|
||||
test('it provides the datastore', function(done) {
|
||||
var subject = new ContactsDatastore(datastoreOwner);
|
||||
|
||||
subject.getStore().then(function(store) {
|
||||
done(function() {
|
||||
assert.equal(store.owner, datastoreOwner);
|
||||
});
|
||||
}).catch (done);
|
||||
});
|
||||
|
||||
test('if the provider name is incorrect promise is rejected', function(done) {
|
||||
var subject = new ContactsDatastore('undefinedprovider');
|
||||
|
||||
subject.getStore().then(function(store) {
|
||||
done('failed');
|
||||
}).catch (function(error) {
|
||||
done(function() {
|
||||
assert.equal(error.name, 'DatastoreNotFound');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('if navigator.getDatastores is not available promise is rejected',
|
||||
function(done) {
|
||||
navigator.getDataStores = null;
|
||||
|
||||
var subject = new ContactsDatastore(datastoreOwner);
|
||||
|
||||
subject.getStore().then(function(store) {
|
||||
done('failed');
|
||||
}).catch (function(error) {
|
||||
done(function() {
|
||||
assert.equal(error.name, 'DatastoreNotEnabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
17
gaia/apps/communications/contacts/test/unit/import/gmail/.jshintrc
Executable file
17
gaia/apps/communications/contacts/test/unit/import/gmail/.jshintrc
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"require",
|
||||
"requireApp",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
352
gaia/apps/communications/contacts/test/unit/import/gmail/gmail_connector_test.js
Executable file
352
gaia/apps/communications/contacts/test/unit/import/gmail/gmail_connector_test.js
Executable file
|
|
@ -0,0 +1,352 @@
|
|||
/* globals GmailConnector, MockGoogleEntry, MockGoogleEntryInvalidDate,
|
||||
MockGoogleEntryNoName, MockGoogleGroups, MockGoogleListing, MockRest,
|
||||
MockGoogleEntryNoFirstName */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/contacts/import/gmail/gmail_connector.js');
|
||||
requireApp('communications/contacts/test/unit/import/gmail/mock_contact1.js');
|
||||
requireApp('communications/contacts/test/unit/import/gmail/mock_listing.js');
|
||||
requireApp('communications/contacts/test/unit/import/mock_rest.js');
|
||||
requireApp('communications/contacts/test/unit/import/gmail/mock_groups.js');
|
||||
|
||||
if (!window.Rest) {
|
||||
window.Rest = null;
|
||||
}
|
||||
|
||||
suite('Gmail Connector', function() {
|
||||
|
||||
var subject,
|
||||
END_POINT = 'https://www.google.com/m8/feeds/contacts/' +
|
||||
'default/full/?max-results=10000',
|
||||
GROUP_ID = 'https://www.google.com/m8/feeds/groups/' +
|
||||
'mepartoconmigo%40gmail.com/base/6';
|
||||
|
||||
suiteSetup(function() {
|
||||
subject = GmailConnector;
|
||||
window.Rest = MockRest;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.Rest = null;
|
||||
});
|
||||
|
||||
suite('Parsing', function() {
|
||||
test('Check contacts listing from feed', function(done) {
|
||||
var callbacks = {
|
||||
'success': function onSuccess(result) {
|
||||
assert.isNotNull(result);
|
||||
assert.isNotNull(result.data);
|
||||
assert.lengthOf(result.data, 2);
|
||||
done();
|
||||
},
|
||||
'error': function onError(error) {
|
||||
assert.fail('We were no suppose to get an error',
|
||||
'We got an error while get');
|
||||
},
|
||||
'timeout': function onTimeout(to) {
|
||||
assert.fail('We were no suppose to get a timeout',
|
||||
'We got a timeout while get');
|
||||
}
|
||||
};
|
||||
|
||||
var contactsListUrl = END_POINT + '&group=' + GROUP_ID;
|
||||
var restConfigure = {
|
||||
'type': 'success',
|
||||
'https://www.google.com/m8/feeds/groups/default/full/': MockGoogleGroups
|
||||
};
|
||||
restConfigure[contactsListUrl] = MockGoogleListing;
|
||||
window.Rest.configure(restConfigure);
|
||||
|
||||
subject.listAllContacts('123456789', callbacks);
|
||||
});
|
||||
|
||||
test('Parse for display', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntry);
|
||||
var result = subject.adaptDataForShowing(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.equal(result.uid,
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974');
|
||||
assert.deepEqual(result.givenName, ['My']);
|
||||
assert.deepEqual(result.familyName, ['Contact']);
|
||||
assert.equal(result.email1, 'juan@palomo.es');
|
||||
});
|
||||
|
||||
test('Parse for display without name', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryNoName);
|
||||
var result = subject.adaptDataForShowing(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.equal(result.uid,
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974');
|
||||
assert.deepEqual(result.givenName, 'juan@palomo.es');
|
||||
assert.equal(result.email1, 'juan@palomo.es');
|
||||
});
|
||||
|
||||
test('Parse for display with invalid birthday date', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryInvalidDate);
|
||||
var result = subject.adaptDataForShowing(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.equal(result.uid,
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974');
|
||||
assert.isUndefined(result.bday);
|
||||
});
|
||||
|
||||
test('Parse for display with only last name', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryNoFirstName);
|
||||
var result = subject.adaptDataForShowing(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.equal(result.uid,
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974');
|
||||
assert.isUndefined(result.bday);
|
||||
});
|
||||
|
||||
test('Parse for saving', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntry);
|
||||
var result = subject.adaptDataForSaving(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.isNotNull(result.givenName);
|
||||
assert.lengthOf(result.givenName, 1);
|
||||
assert.equal(result.givenName[0], 'My');
|
||||
|
||||
assert.isNotNull(result.familyName);
|
||||
assert.lengthOf(result.familyName, 1);
|
||||
assert.equal(result.familyName[0], 'Contact');
|
||||
|
||||
assert.isNotNull(result.email);
|
||||
assert.lengthOf(result.email, 2);
|
||||
assert.equal('juan@palomo.es', result.email[0].value);
|
||||
assert.equal('home', result.email[0].type);
|
||||
assert.equal('workemail@email.com', result.email[1].value);
|
||||
assert.equal('work', result.email[1].type);
|
||||
|
||||
assert.isNotNull(result.adr);
|
||||
assert.lengthOf(result.adr, 1);
|
||||
assert.equal('This is the Street', result.adr[0].streetAddress);
|
||||
assert.equal('The City', result.adr[0].locality);
|
||||
assert.equal('The State', result.adr[0].region);
|
||||
assert.equal('The Zip', result.adr[0].postalCode);
|
||||
assert.equal('The Country', result.adr[0].countryName);
|
||||
|
||||
assert.isNotNull(result.tel);
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assert.equal('+1555111333444222', result.tel[0].value);
|
||||
assert.equal('work', result.tel[0].type);
|
||||
|
||||
assert.isNotNull(result.org);
|
||||
assert.lengthOf(result.org, 1);
|
||||
assert.equal('The Company', result.org[0]);
|
||||
|
||||
assert.isNotNull(result.jobTitle);
|
||||
assert.lengthOf(result.jobTitle, 1);
|
||||
assert.equal('Title in Company', result.jobTitle[0]);
|
||||
|
||||
assert.isNotNull(result.bday);
|
||||
assert.deepEqual(new Date('1990-01-01'), result.bday);
|
||||
|
||||
assert.isNotNull(result.note);
|
||||
assert.lengthOf(result.note, 1);
|
||||
assert.equal('This is a Note', result.note[0]);
|
||||
|
||||
assert.isNotNull(result.category);
|
||||
assert.lengthOf(result.category, 1);
|
||||
assert.equal('gmail', result.category[0]);
|
||||
|
||||
assert.isNotNull(result.url);
|
||||
assert.lengthOf(result.url, 1);
|
||||
assert.lengthOf(result.url[0].type, 1);
|
||||
assert.equal('source', result.url[0].type[0]);
|
||||
assert.equal('urn:service:gmail:uid:' +
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974',
|
||||
result.url[0].value);
|
||||
});
|
||||
|
||||
test('Parse for saving without name', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryNoName);
|
||||
var result = subject.adaptDataForSaving(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(!result.givenName);
|
||||
assert.isTrue(!result.familyName);
|
||||
|
||||
assert.isNotNull(result.email);
|
||||
assert.lengthOf(result.email, 2);
|
||||
assert.equal('juan@palomo.es', result.email[0].value);
|
||||
assert.equal('home', result.email[0].type);
|
||||
assert.equal('workemail@email.com', result.email[1].value);
|
||||
assert.equal('work', result.email[1].type);
|
||||
|
||||
assert.isNotNull(result.adr);
|
||||
assert.lengthOf(result.adr, 1);
|
||||
assert.equal('This is the Street', result.adr[0].streetAddress);
|
||||
assert.equal('The City', result.adr[0].locality);
|
||||
assert.equal('The State', result.adr[0].region);
|
||||
assert.equal('The Zip', result.adr[0].postalCode);
|
||||
assert.equal('The Country', result.adr[0].countryName);
|
||||
|
||||
assert.isNotNull(result.tel);
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assert.equal('+1555111333444222', result.tel[0].value);
|
||||
assert.equal('work', result.tel[0].type);
|
||||
|
||||
assert.isNotNull(result.org);
|
||||
assert.lengthOf(result.org, 1);
|
||||
assert.equal('The Company', result.org[0]);
|
||||
|
||||
assert.isNotNull(result.jobTitle);
|
||||
assert.lengthOf(result.jobTitle, 1);
|
||||
assert.equal('Title in Company', result.jobTitle[0]);
|
||||
|
||||
assert.isNotNull(result.bday);
|
||||
assert.deepEqual(new Date('1990-01-01'), result.bday);
|
||||
|
||||
assert.isNotNull(result.note);
|
||||
assert.lengthOf(result.note, 1);
|
||||
assert.equal('This is a Note', result.note[0]);
|
||||
|
||||
assert.isNotNull(result.category);
|
||||
assert.lengthOf(result.category, 1);
|
||||
assert.equal('gmail', result.category[0]);
|
||||
|
||||
assert.isNotNull(result.url);
|
||||
assert.lengthOf(result.url, 1);
|
||||
assert.lengthOf(result.url[0].type, 1);
|
||||
assert.equal('source', result.url[0].type[0]);
|
||||
assert.equal('urn:service:gmail:uid:' +
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974',
|
||||
result.url[0].value);
|
||||
|
||||
});
|
||||
|
||||
test('Parse for saving with invalid birthday date', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryInvalidDate);
|
||||
var result = subject.adaptDataForSaving(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.isNotNull(result.givenName);
|
||||
assert.lengthOf(result.givenName, 1);
|
||||
assert.equal(result.givenName[0], 'My');
|
||||
|
||||
assert.isNotNull(result.familyName);
|
||||
assert.lengthOf(result.familyName, 1);
|
||||
assert.equal(result.familyName[0], 'Contact');
|
||||
|
||||
assert.isNotNull(result.email);
|
||||
assert.lengthOf(result.email, 2);
|
||||
assert.equal('juan@palomo.es', result.email[0].value);
|
||||
assert.equal('home', result.email[0].type);
|
||||
assert.equal('workemail@email.com', result.email[1].value);
|
||||
assert.equal('work', result.email[1].type);
|
||||
|
||||
assert.isNotNull(result.adr);
|
||||
assert.lengthOf(result.adr, 1);
|
||||
assert.equal('This is the Street', result.adr[0].streetAddress);
|
||||
assert.equal('The City', result.adr[0].locality);
|
||||
assert.equal('The State', result.adr[0].region);
|
||||
assert.equal('The Zip', result.adr[0].postalCode);
|
||||
assert.equal('The Country', result.adr[0].countryName);
|
||||
|
||||
assert.isNotNull(result.tel);
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assert.equal('+1555111333444222', result.tel[0].value);
|
||||
assert.equal('work', result.tel[0].type);
|
||||
|
||||
assert.isNotNull(result.org);
|
||||
assert.lengthOf(result.org, 1);
|
||||
assert.equal('The Company', result.org[0]);
|
||||
|
||||
assert.isNotNull(result.jobTitle);
|
||||
assert.lengthOf(result.jobTitle, 1);
|
||||
assert.equal('Title in Company', result.jobTitle[0]);
|
||||
|
||||
assert.isUndefined(result.bday);
|
||||
|
||||
assert.isNotNull(result.note);
|
||||
assert.lengthOf(result.note, 1);
|
||||
assert.equal('This is a Note', result.note[0]);
|
||||
|
||||
assert.isNotNull(result.category);
|
||||
assert.lengthOf(result.category, 1);
|
||||
assert.equal('gmail', result.category[0]);
|
||||
|
||||
assert.isNotNull(result.url);
|
||||
assert.lengthOf(result.url, 1);
|
||||
assert.lengthOf(result.url[0].type, 1);
|
||||
assert.equal('source', result.url[0].type[0]);
|
||||
assert.equal('urn:service:gmail:uid:' +
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974',
|
||||
result.url[0].value);
|
||||
});
|
||||
|
||||
test('Parse for saving with no first name', function() {
|
||||
var contact = subject.gContactToJson(MockGoogleEntryNoFirstName);
|
||||
var result = subject.adaptDataForSaving(contact);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(!result.givenName);
|
||||
|
||||
assert.isNotNull(result.familyName);
|
||||
assert.lengthOf(result.familyName, 1);
|
||||
assert.equal(result.familyName[0], 'Contact');
|
||||
|
||||
assert.isNotNull(result.email);
|
||||
assert.lengthOf(result.email, 2);
|
||||
assert.equal('juan@palomo.es', result.email[0].value);
|
||||
assert.equal('home', result.email[0].type);
|
||||
assert.equal('workemail@email.com', result.email[1].value);
|
||||
assert.equal('work', result.email[1].type);
|
||||
|
||||
assert.isNotNull(result.adr);
|
||||
assert.lengthOf(result.adr, 1);
|
||||
assert.equal('This is the Street', result.adr[0].streetAddress);
|
||||
assert.equal('The City', result.adr[0].locality);
|
||||
assert.equal('The State', result.adr[0].region);
|
||||
assert.equal('The Zip', result.adr[0].postalCode);
|
||||
assert.equal('The Country', result.adr[0].countryName);
|
||||
|
||||
assert.isNotNull(result.tel);
|
||||
assert.lengthOf(result.tel, 1);
|
||||
assert.equal('+1555111333444222', result.tel[0].value);
|
||||
assert.equal('work', result.tel[0].type);
|
||||
|
||||
assert.isNotNull(result.org);
|
||||
assert.lengthOf(result.org, 1);
|
||||
assert.equal('The Company', result.org[0]);
|
||||
|
||||
assert.isNotNull(result.jobTitle);
|
||||
assert.lengthOf(result.jobTitle, 1);
|
||||
assert.equal('Title in Company', result.jobTitle[0]);
|
||||
|
||||
assert.isNotNull(result.bday);
|
||||
assert.deepEqual(new Date('1990-01-01'), result.bday);
|
||||
|
||||
assert.isNotNull(result.note);
|
||||
assert.lengthOf(result.note, 1);
|
||||
assert.equal('This is a Note', result.note[0]);
|
||||
|
||||
assert.isNotNull(result.category);
|
||||
assert.lengthOf(result.category, 1);
|
||||
assert.equal('gmail', result.category[0]);
|
||||
|
||||
assert.isNotNull(result.url);
|
||||
assert.lengthOf(result.url, 1);
|
||||
assert.lengthOf(result.url[0].type, 1);
|
||||
assert.equal('source', result.url[0].type[0]);
|
||||
assert.equal('urn:service:gmail:uid:' +
|
||||
'http://www.google.com/m8/feeds/contacts/' +
|
||||
'mepartoconmigo%40gmail.com/base/2fc27a388c2bd974',
|
||||
result.url[0].value);
|
||||
});
|
||||
});
|
||||
});
|
||||
46
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact1.js
Executable file
46
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact1.js
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockGoogleEntry, MockGoogleEntryNoName,
|
||||
MockGoogleEntryInvalidDate, MockGoogleEntryNoFirstName */
|
||||
|
||||
// refer to mock_contact1.xml for the entry XML we are getting.
|
||||
|
||||
var MockGoogleEntry = (function MockGoogleEntry() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_contact1.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(entryBuffer, 'text/xml');
|
||||
})();
|
||||
|
||||
var MockGoogleEntryNoName = (function MockGoogleEntryNoName() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_contact2.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(entryBuffer, 'text/xml');
|
||||
})();
|
||||
|
||||
var MockGoogleEntryInvalidDate = (function MockGoogleEntryWoName() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_contact3.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(entryBuffer, 'text/xml');
|
||||
})();
|
||||
|
||||
var MockGoogleEntryNoFirstName = (function MockGoogleEntryNoFirstName() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_contact4.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
return parser.parseFromString(entryBuffer, 'text/xml');
|
||||
})();
|
||||
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact1.xml
Executable file
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact1.xml
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""RXg9fDVSLit7I2A9WhBSGUsPQgU."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/base/2fc27a388c2bd974</id>
|
||||
<updated>2013-02-27T11:45:14.664Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T11:45:14.664Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>My Shiny Contact</title>
|
||||
<content>This is a Note</content>
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/mepartoconmigo%40gmail.com/2fc27a388c2bd974" gd:etag=""LhMgGHAHWit7I2BuPF4FFCt_B0ZEGiYpXwg."" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<gd:name>
|
||||
<gd:fullName>My Shiny Contact</gd:fullName>
|
||||
<gd:givenName>My</gd:givenName>
|
||||
<gd:additionalName>Shiny</gd:additionalName>
|
||||
<gd:familyName>Contact</gd:familyName>
|
||||
</gd:name>
|
||||
<gContact:birthday when="1990-01-01" />
|
||||
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
||||
<gd:orgName>The Company</gd:orgName>
|
||||
<gd:orgTitle>Title in Company</gd:orgTitle>
|
||||
</gd:organization>
|
||||
<gd:email rel="http://schemas.google.com/g/2005#home" address="juan@palomo.es" primary="true" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#work" address="workemail@email.com" />
|
||||
<gd:im address="instantmessaging" protocol="http://schemas.google.com/g/2005#GOOGLE_TALK" rel="http://schemas.google.com/g/2005#other" />
|
||||
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">+1555111333444222</gd:phoneNumber>
|
||||
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
||||
<gd:formattedAddress>This is the Street
|
||||
The PO Box
|
||||
The Nieghborhood, The City, The State The Zip
|
||||
The Country</gd:formattedAddress>
|
||||
<gd:street>This is the Street</gd:street>
|
||||
<gd:neighborhood>The Nieghborhood</gd:neighborhood>
|
||||
<gd:pobox>The PO Box</gd:pobox>
|
||||
<gd:postcode>The Zip</gd:postcode>
|
||||
<gd:city>The City</gd:city>
|
||||
<gd:region>The State</gd:region>
|
||||
<gd:country>The Country</gd:country>
|
||||
</gd:structuredPostalAddress>
|
||||
<gContact:website href="http://www.myurl.com" rel="profile" />
|
||||
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/6" />
|
||||
</entry>
|
||||
35
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact2.xml
Executable file
35
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact2.xml
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""RXg9fDVSLit7I2A9WhBSGUsPQgU."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/base/2fc27a388c2bd974</id>
|
||||
<updated>2013-02-27T11:45:14.664Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T11:45:14.664Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>My Shiny Contact</title>
|
||||
<content>This is a Note</content>
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/mepartoconmigo%40gmail.com/2fc27a388c2bd974" gd:etag=""LhMgGHAHWit7I2BuPF4FFCt_B0ZEGiYpXwg."" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<gContact:birthday when="1990-01-01" />
|
||||
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
||||
<gd:orgName>The Company</gd:orgName>
|
||||
<gd:orgTitle>Title in Company</gd:orgTitle>
|
||||
</gd:organization>
|
||||
<gd:email rel="http://schemas.google.com/g/2005#home" address="juan@palomo.es" primary="true" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#work" address="workemail@email.com" />
|
||||
<gd:im address="instantmessaging" protocol="http://schemas.google.com/g/2005#GOOGLE_TALK" rel="http://schemas.google.com/g/2005#other" />
|
||||
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">+1555111333444222</gd:phoneNumber>
|
||||
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
||||
<gd:formattedAddress>This is the Street
|
||||
The PO Box
|
||||
The Nieghborhood, The City, The State The Zip
|
||||
The Country</gd:formattedAddress>
|
||||
<gd:street>This is the Street</gd:street>
|
||||
<gd:neighborhood>The Nieghborhood</gd:neighborhood>
|
||||
<gd:pobox>The PO Box</gd:pobox>
|
||||
<gd:postcode>The Zip</gd:postcode>
|
||||
<gd:city>The City</gd:city>
|
||||
<gd:region>The State</gd:region>
|
||||
<gd:country>The Country</gd:country>
|
||||
</gd:structuredPostalAddress>
|
||||
<gContact:website href="http://www.myurl.com" rel="profile" />
|
||||
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/6" />
|
||||
</entry>
|
||||
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact3.xml
Executable file
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact3.xml
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""RXg9fDVSLit7I2A9WhBSGUsPQgU."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/base/2fc27a388c2bd974</id>
|
||||
<updated>2013-02-27T11:45:14.664Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T11:45:14.664Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>My Shiny Contact</title>
|
||||
<content>This is a Note</content>
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/mepartoconmigo%40gmail.com/2fc27a388c2bd974" gd:etag=""LhMgGHAHWit7I2BuPF4FFCt_B0ZEGiYpXwg."" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<gd:name>
|
||||
<gd:fullName>My Shiny Contact</gd:fullName>
|
||||
<gd:givenName>My</gd:givenName>
|
||||
<gd:additionalName>Shiny</gd:additionalName>
|
||||
<gd:familyName>Contact</gd:familyName>
|
||||
</gd:name>
|
||||
<gContact:birthday when="June 24" />
|
||||
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
||||
<gd:orgName>The Company</gd:orgName>
|
||||
<gd:orgTitle>Title in Company</gd:orgTitle>
|
||||
</gd:organization>
|
||||
<gd:email rel="http://schemas.google.com/g/2005#home" address="juan@palomo.es" primary="true" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#work" address="workemail@email.com" />
|
||||
<gd:im address="instantmessaging" protocol="http://schemas.google.com/g/2005#GOOGLE_TALK" rel="http://schemas.google.com/g/2005#other" />
|
||||
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">+1555111333444222</gd:phoneNumber>
|
||||
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
||||
<gd:formattedAddress>This is the Street
|
||||
The PO Box
|
||||
The Nieghborhood, The City, The State The Zip
|
||||
The Country</gd:formattedAddress>
|
||||
<gd:street>This is the Street</gd:street>
|
||||
<gd:neighborhood>The Nieghborhood</gd:neighborhood>
|
||||
<gd:pobox>The PO Box</gd:pobox>
|
||||
<gd:postcode>The Zip</gd:postcode>
|
||||
<gd:city>The City</gd:city>
|
||||
<gd:region>The State</gd:region>
|
||||
<gd:country>The Country</gd:country>
|
||||
</gd:structuredPostalAddress>
|
||||
<gContact:website href="http://www.myurl.com" rel="profile" />
|
||||
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/6" />
|
||||
</entry>
|
||||
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact4.xml
Executable file
41
gaia/apps/communications/contacts/test/unit/import/gmail/mock_contact4.xml
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""RXg9fDVSLit7I2A9WhBSGUsPQgU."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/base/2fc27a388c2bd974</id>
|
||||
<updated>2013-02-27T11:45:14.664Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T11:45:14.664Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>My Shiny Contact</title>
|
||||
<content>This is a Note</content>
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/mepartoconmigo%40gmail.com/2fc27a388c2bd974" gd:etag=""LhMgGHAHWit7I2BuPF4FFCt_B0ZEGiYpXwg."" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/mepartoconmigo%40gmail.com/full/2fc27a388c2bd974" />
|
||||
<gd:name>
|
||||
<gd:fullName>Contact</gd:fullName>
|
||||
<gd:givenName></gd:givenName>
|
||||
<gd:additionalName></gd:additionalName>
|
||||
<gd:familyName>Contact</gd:familyName>
|
||||
</gd:name>
|
||||
<gContact:birthday when="1990-01-01" />
|
||||
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
||||
<gd:orgName>The Company</gd:orgName>
|
||||
<gd:orgTitle>Title in Company</gd:orgTitle>
|
||||
</gd:organization>
|
||||
<gd:email rel="http://schemas.google.com/g/2005#home" address="juan@palomo.es" primary="true" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#work" address="workemail@email.com" />
|
||||
<gd:im address="instantmessaging" protocol="http://schemas.google.com/g/2005#GOOGLE_TALK" rel="http://schemas.google.com/g/2005#other" />
|
||||
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">+1555111333444222</gd:phoneNumber>
|
||||
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
||||
<gd:formattedAddress>This is the Street
|
||||
The PO Box
|
||||
The Nieghborhood, The City, The State The Zip
|
||||
The Country</gd:formattedAddress>
|
||||
<gd:street>This is the Street</gd:street>
|
||||
<gd:neighborhood>The Nieghborhood</gd:neighborhood>
|
||||
<gd:pobox>The PO Box</gd:pobox>
|
||||
<gd:postcode>The Zip</gd:postcode>
|
||||
<gd:city>The City</gd:city>
|
||||
<gd:region>The State</gd:region>
|
||||
<gd:country>The Country</gd:country>
|
||||
</gd:structuredPostalAddress>
|
||||
<gContact:website href="http://www.myurl.com" rel="profile" />
|
||||
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/6" />
|
||||
</entry>
|
||||
23
gaia/apps/communications/contacts/test/unit/import/gmail/mock_groups.js
Executable file
23
gaia/apps/communications/contacts/test/unit/import/gmail/mock_groups.js
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockGoogleGroups */
|
||||
|
||||
/*
|
||||
|
||||
This mock represents the following google contacts response
|
||||
for groups of contacts. See mock_groups.xml.
|
||||
|
||||
*/
|
||||
|
||||
var MockGoogleGroups = (function MockGoogleGroups() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_groups.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
var listing = parser.parseFromString(entryBuffer, 'text/xml');
|
||||
|
||||
return listing;
|
||||
|
||||
})();
|
||||
1
gaia/apps/communications/contacts/test/unit/import/gmail/mock_groups.xml
Executable file
1
gaia/apps/communications/contacts/test/unit/import/gmail/mock_groups.xml
Executable file
|
|
@ -0,0 +1 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/"DkUFSHgzeSt7I2A9WhBQGEs."'><id>mepartoconmigo@gmail.com</id><updated>2013-03-21T11:10:19.681Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/contact/2008#group'/><title>arcturus's Contact Groups</title><link rel='alternate' type='text/html' href='http://www.google.com/'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full'/><link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full'/><link rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full/batch'/><link rel='self' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full?max-results=25'/><author><name>arcturus</name><email>mepartoconmigo@gmail.com</email></author><generator version='1.0' uri='http://www.google.com/m8/feeds'>Contacts</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry gd:etag='"YDwreyM."'><id>https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/6</id><updated>1970-01-01T00:00:00.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/contact/2008#group'/><title>System Group: My Contacts</title><content>System Group: My Contacts</content><link rel='self' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full/6'/><gContact:systemGroup id='Contacts'/></entry><entry gd:etag='"YDwreyM."'><id>https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/base/d</id><updated>1970-01-01T00:00:00.000Z</updated><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/contact/2008#group'/><title>System Group: Friends</title><content>System Group: Friends</content><link rel='self' type='application/atom+xml' href='https://www.google.com/m8/feeds/groups/mepartoconmigo%40gmail.com/full/d'/><gContact:systemGroup id='Friends'/></entry></feed>
|
||||
23
gaia/apps/communications/contacts/test/unit/import/gmail/mock_listing.js
Executable file
23
gaia/apps/communications/contacts/test/unit/import/gmail/mock_listing.js
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockGoogleListing */
|
||||
|
||||
/*
|
||||
|
||||
This mock represents the following google contacts response
|
||||
for a list of contacts. See mock_listing.xml.
|
||||
|
||||
*/
|
||||
|
||||
var MockGoogleListing = (function MockGoogleListing() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/gmail/mock_listing.xml', false);
|
||||
req.send(null);
|
||||
|
||||
var entryBuffer = req.responseText;
|
||||
var parser = new DOMParser();
|
||||
var listing = parser.parseFromString(entryBuffer, 'text/xml');
|
||||
|
||||
return listing;
|
||||
|
||||
})();
|
||||
50
gaia/apps/communications/contacts/test/unit/import/gmail/mock_listing.xml
Executable file
50
gaia/apps/communications/contacts/test/unit/import/gmail/mock_listing.xml
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/"DkENRHY6fyt7I2A9WhBSGUU."">
|
||||
<id>someemail@gmail.com</id>
|
||||
<updated>2013-02-27T17:04:55.817Z</updated>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>someone's Contacts</title>
|
||||
<link rel="alternate" type="text/html" href="http://www.google.com/" />
|
||||
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full" />
|
||||
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full" />
|
||||
<link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full/batch" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full?max-results=25" />
|
||||
<link rel="next" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full?start-index=26&max-results=25" />
|
||||
<author>
|
||||
<name>someone</name>
|
||||
<email>someemail@gmail.com</email>
|
||||
</author>
|
||||
<generator version="1.0" uri="http://www.google.com/m8/feeds">Contacts</generator>
|
||||
<openSearch:totalResults>2</openSearch:totalResults>
|
||||
<openSearch:startIndex>1</openSearch:startIndex>
|
||||
<openSearch:itemsPerPage>25</openSearch:itemsPerPage>
|
||||
<entry gd:etag=""RXs7ejVSLit7I2A9WxNRFE4IQAY."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/base/1</id>
|
||||
<updated>2009-09-08T17:58:44.502Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-08T17:58:44.502Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title />
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/somegoogleemail%40gmail.com/1" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full/1" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full/1" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#other" address="another@gmail.com" primary="true" />
|
||||
<gd:email rel="http://schemas.google.com/g/2005#work" address="work@gmail.com" primary="true" />
|
||||
</entry>
|
||||
<entry gd:etag=""RHY4fTNRKyt7I2A9WhJbEkQDQgY."">
|
||||
<id>http://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/base/2</id>
|
||||
<updated>2012-09-22T07:38:45.835Z</updated>
|
||||
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-22T07:38:45.835Z</app:edited>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
|
||||
<title>John Doe</title>
|
||||
<gd:name>
|
||||
<gd:fullName>John Doe</gd:fullName>
|
||||
<gd:givenName>John</gd:givenName>
|
||||
<gd:additionalName></gd:additionalName>
|
||||
<gd:familyName>Doe</gd:familyName>
|
||||
</gd:name>
|
||||
<gContact:birthday when="1990-01-01" />
|
||||
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/somegoogleemail%40gmail.com/2" gd:etag=""UR5VJUMvbCt7I2BcOB46EypYQV4BJGx4YVc."" />
|
||||
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full/2" />
|
||||
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/somegoogleemail%40gmail.com/full/2" />
|
||||
</entry>
|
||||
</feed>
|
||||
229
gaia/apps/communications/contacts/test/unit/import/import_contacts_test.js
Executable file
229
gaia/apps/communications/contacts/test/unit/import/import_contacts_test.js
Executable file
|
|
@ -0,0 +1,229 @@
|
|||
'use strict';
|
||||
|
||||
/* global contacts */
|
||||
/* global LazyLoader */
|
||||
/* global MyLocks */
|
||||
/* global MockWakeLock */
|
||||
/* global MockasyncStorage */
|
||||
/* global MockMozL10n */
|
||||
/* global MockSdCard */
|
||||
/* global MocksHelper */
|
||||
/* global MockUtils */
|
||||
/* global MockContactsIndexHtml */
|
||||
/* global MockNavigatorMozMobileConnections */
|
||||
/* global MockSimContactsImporter */
|
||||
/* global MockVCFReader */
|
||||
/* global MockMozContacts */
|
||||
/* global MockAdvancedTelemetryHelper */
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
require('/shared/test/unit/mocks/mock_sdcard.js');
|
||||
require('/shared/test/unit/mocks/mock_vcard_parser.js');
|
||||
require('/shared/test/unit/mocks/mock_advanced_telemetry_helper.js');
|
||||
|
||||
requireApp('communications/contacts/services/contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_index.html.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_service_extensions.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_asyncstorage.js');
|
||||
requireApp('communications/contacts/test/unit/mock_fb.js');
|
||||
requireApp('communications/contacts/test/unit/mock_wakelock.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_event_listeners.js');
|
||||
requireApp('communications/contacts/test/unit/mock_sim_importer.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
|
||||
requireApp('communications/contacts/js/views/settings.js');
|
||||
requireApp('communications/contacts/js/utilities/icc_handler.js');
|
||||
requireApp('communications/contacts/js/utilities/sim_dom_generator.js');
|
||||
requireApp('communications/contacts/js/navigation.js');
|
||||
|
||||
if (!window._) { window._ = null; }
|
||||
if (!window.utils) { window.utils = null; }
|
||||
if (!navigator.mozMobileConnections) { navigator.mozMobileConnections = null; }
|
||||
|
||||
var mocksHelperForContactImport = new MocksHelper([
|
||||
'ExtServices', 'Contacts', 'fb', 'asyncStorage', 'ConfirmDialog',
|
||||
'VCFReader', 'WakeLock', 'SimContactsImporter'
|
||||
]);
|
||||
mocksHelperForContactImport.init();
|
||||
|
||||
suite('Import contacts >', function() {
|
||||
var mocksHelper = mocksHelperForContactImport;
|
||||
|
||||
var real_,
|
||||
realUtils,
|
||||
realWakeLock,
|
||||
realMozMobileConnections,
|
||||
realMozContacts,
|
||||
realATH;
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(window.utils.overlay, 'showMenu');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockasyncStorage.clear();
|
||||
});
|
||||
|
||||
suiteSetup(function(done) {
|
||||
mocksHelper.suiteSetup();
|
||||
|
||||
realMozMobileConnections = navigator.mozMobileConnections;
|
||||
navigator.mozMobileConnections = MockNavigatorMozMobileConnections;
|
||||
|
||||
realWakeLock = navigator.requestWakeLock;
|
||||
navigator.requestWakeLock = MockWakeLock;
|
||||
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
|
||||
real_ = window._;
|
||||
window._ = MockMozL10n.get;
|
||||
|
||||
realUtils = window.utils;
|
||||
window.utils = MockUtils;
|
||||
window.utils.overlay = {
|
||||
show: function() {},
|
||||
showMenu: function() {}
|
||||
};
|
||||
|
||||
window.utils.status = {
|
||||
show: function() {}
|
||||
};
|
||||
|
||||
window.utils.misc = {
|
||||
getTimestamp: function(element, cb) {
|
||||
cb();
|
||||
},
|
||||
setTimestamp: function(time, cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
window.utils.sdcard = MockSdCard;
|
||||
window.utils.time = {
|
||||
pretty: function() {}
|
||||
};
|
||||
|
||||
document.body.innerHTML = MockContactsIndexHtml;
|
||||
contacts.Settings.init();
|
||||
|
||||
LazyLoader.load(['/shared/js/contacts/import/utilities/status.js',
|
||||
'/shared/js/advanced_telemetry_helper.js'], () => {
|
||||
LazyLoader.load('/contacts/js/utilities/telemetry.js', () => {
|
||||
realATH = window.AdvancedTelemetryHelper;
|
||||
window.AdvancedTelemetryHelper = MockAdvancedTelemetryHelper;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozMobileConnections = realMozMobileConnections;
|
||||
navigator.requestWakeLock = realWakeLock;
|
||||
navigator.mozContacts = realMozContacts;
|
||||
|
||||
window.utils = realUtils;
|
||||
window._ = real_;
|
||||
window.AdvancedTelemetryHelper = realATH;
|
||||
|
||||
mocksHelper.suiteTeardown();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(window.utils.status, 'show');
|
||||
});
|
||||
|
||||
test('SD Import went well', function(done) {
|
||||
sinon.spy(window, 'AdvancedTelemetryHelper');
|
||||
contacts.Settings.importFromSDCard(function onImported() {
|
||||
assert.isTrue(window.utils.overlay.showMenu.called);
|
||||
assert.equal(window.utils.status.show.getCall(0).args.length, 2);
|
||||
assert.equal(false, MyLocks.cpu);
|
||||
window.TelemetryReady.then(() => {
|
||||
assert.isTrue(window.AdvancedTelemetryHelper.calledWithNew());
|
||||
var counter = window.AdvancedTelemetryHelper.getCall(0).returnValue;
|
||||
assert.equal(counter.name, 'telemetry_gaia_contacts_import_sd');
|
||||
assert.equal(window.AdvancedTelemetryHelper.HISTOGRAM_COUNT,
|
||||
counter.type);
|
||||
window.AdvancedTelemetryHelper.restore();
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('SD Import went well with duplicates found', function(done) {
|
||||
MockVCFReader.prototype.numDuplicated = 2;
|
||||
|
||||
contacts.Settings.importFromSDCard(function onImported() {
|
||||
assert.isTrue(window.utils.overlay.showMenu.called);
|
||||
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[0] !== null);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[1] !== null);
|
||||
|
||||
assert.equal(false, MyLocks.cpu);
|
||||
|
||||
delete MockVCFReader.prototype.numDuplicated;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('SD Import with error cause no files to import', function(done) {
|
||||
// Simulate not finding any files
|
||||
MockSdCard.failOnRetrieveFiles = true;
|
||||
contacts.Settings.importFromSDCard(function onImported() {
|
||||
assert.isTrue(window.utils.overlay.showMenu.called);
|
||||
assert.isFalse(window.utils.status.show.called);
|
||||
assert.equal(false, MyLocks.cpu);
|
||||
// Restore the mock
|
||||
MockSdCard.failOnRetrieveFiles = false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('SIM Import ', function() {
|
||||
suiteSetup(function() {
|
||||
contacts.Settings.init();
|
||||
});
|
||||
|
||||
test('If there are no Contacts to be imported a message appears',
|
||||
function(done) {
|
||||
MockSimContactsImporter.prototype.numImportedContacts = 0;
|
||||
MockSimContactsImporter.prototype.numDuplicated = 0;
|
||||
MockSimContactsImporter.prototype.number = 0;
|
||||
|
||||
contacts.Settings.importFromSIMCard('1234', function onImported() {
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[0] !== null);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[1] === null);
|
||||
|
||||
delete MockSimContactsImporter.prototype.numImportedContacts;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('SIM Import went well with duplicates found', function(done) {
|
||||
MockSimContactsImporter.prototype.numDuplicated = 1;
|
||||
MockSimContactsImporter.prototype.numImportedContacts = 3;
|
||||
MockSimContactsImporter.prototype.number = 3;
|
||||
|
||||
contacts.Settings.importFromSIMCard('1234', function onImported() {
|
||||
assert.isTrue(window.utils.status.show.called);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[0] !== null);
|
||||
assert.isTrue(window.utils.status.show.getCall(0).args[1] !== null);
|
||||
|
||||
assert.equal(false, MyLocks.cpu);
|
||||
|
||||
delete MockSimContactsImporter.prototype.numDuplicates;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
156
gaia/apps/communications/contacts/test/unit/import/import_sim_contacts_test.js
Executable file
156
gaia/apps/communications/contacts/test/unit/import/import_sim_contacts_test.js
Executable file
|
|
@ -0,0 +1,156 @@
|
|||
'use strict';
|
||||
/* global SimContactsImporter */
|
||||
/* global MockMozContacts, MocksHelper, MockIccManager */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_iccmanager.js');
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/simple_phone_matcher.js');
|
||||
require('/shared/js/contacts/contacts_merger.js');
|
||||
require('/shared/js/contacts/utilities/image_thumbnail.js');
|
||||
require('/shared/js/contacts/merger_adapter.js');
|
||||
require('/shared/js/contacts/import/utilities/misc.js');
|
||||
require('/shared/js/contacts/import/utilities/import_sim_contacts.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_contact.js');
|
||||
|
||||
var mocksHelperForImporter = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'mozContact'
|
||||
]).init();
|
||||
|
||||
suite('Sim import >', function() {
|
||||
mocksHelperForImporter.attachTestHelpers();
|
||||
var realMozContacts,
|
||||
iccManager,
|
||||
icc,
|
||||
importer;
|
||||
|
||||
// List of contacts result for the method icc.readContacts
|
||||
var mRequestResult = {
|
||||
adn: [
|
||||
{id : 'a572247', tel : [{value : '900900900'}], name : ['Peter']},
|
||||
{id : 'b572248', tel : [{value : '192192192'}], name : ['Jason']}
|
||||
],
|
||||
sdn: [
|
||||
{id : '105721', tel : [{value : '190'}], name : ['Police'] },
|
||||
{id : '105722', tel : [{value : '192'}], name : ['Ambulance'] },
|
||||
{id : '105723', tel : [{value : '193'}], name : ['Fire'] }
|
||||
]
|
||||
};
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realMozContacts = navigator.mozContacts;
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
require('/shared/js/contacts/contacts_matcher.js', done);
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockMozContacts.contacts = [];
|
||||
iccManager = new MockIccManager();
|
||||
icc = iccManager.getIccById('123');
|
||||
importer = new SimContactsImporter(icc);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozContacts = realMozContacts;
|
||||
});
|
||||
|
||||
test('Calling with adn and sdn contacts', function(done) {
|
||||
iccManager.adnContacts = mRequestResult.adn;
|
||||
iccManager.sdnContacts = mRequestResult.sdn;
|
||||
iccManager.isAdnOnError = false;
|
||||
iccManager.isSdnOnError = false;
|
||||
|
||||
var totalContactsToImport = mRequestResult.adn.length +
|
||||
mRequestResult.sdn.length;
|
||||
|
||||
importer.onfinish = function() {
|
||||
var mozContactsLength = navigator.mozContacts.contacts.length;
|
||||
assert.equal(mozContactsLength, totalContactsToImport);
|
||||
done();
|
||||
};
|
||||
importer.start();
|
||||
});
|
||||
|
||||
test('Calling without adn contacts', function(done) {
|
||||
iccManager.adnContacts = [];
|
||||
iccManager.sdnContacts = mRequestResult.sdn;
|
||||
iccManager.isAdnOnError = false;
|
||||
iccManager.isSdnOnError = false;
|
||||
|
||||
var totalContactsToImport = mRequestResult.sdn.length;
|
||||
|
||||
importer.onfinish = function() {
|
||||
var mozContactsLength = navigator.mozContacts.contacts.length;
|
||||
assert.equal(mozContactsLength, totalContactsToImport);
|
||||
done();
|
||||
};
|
||||
importer.start();
|
||||
});
|
||||
|
||||
test('Calling without sdn contacts', function(done) {
|
||||
iccManager.adnContacts = mRequestResult.adn;
|
||||
iccManager.sdnContacts = [];
|
||||
iccManager.isAdnOnError = false;
|
||||
iccManager.isSdnOnError = false;
|
||||
|
||||
var totalContactsToImport = mRequestResult.adn.length;
|
||||
|
||||
importer.onfinish = function() {
|
||||
var mozContactsLength = navigator.mozContacts.contacts.length;
|
||||
assert.equal(mozContactsLength, totalContactsToImport);
|
||||
done();
|
||||
};
|
||||
importer.start();
|
||||
});
|
||||
|
||||
test('Request adn contacts fails', function(done) {
|
||||
iccManager.adnContacts = mRequestResult.adn;
|
||||
iccManager.sdnContacts = mRequestResult.sdn;
|
||||
iccManager.isAdnOnError = true;
|
||||
iccManager.isSdnOnError = false;
|
||||
|
||||
importer.onerror = function() {
|
||||
var mozContactsLength = navigator.mozContacts.contacts.length;
|
||||
assert.equal(mozContactsLength, 0);
|
||||
done();
|
||||
};
|
||||
importer.start();
|
||||
});
|
||||
|
||||
test('Request sdn contacts fails, only import adn', function(done) {
|
||||
iccManager.adnContacts = mRequestResult.adn;
|
||||
iccManager.sdnContacts = mRequestResult.sdn;
|
||||
iccManager.isAdnOnError = false;
|
||||
iccManager.isSdnOnError = true;
|
||||
|
||||
var adnContactsLength = mRequestResult.adn.length;
|
||||
|
||||
importer.onfinish = function() {
|
||||
var mozContactsLength = navigator.mozContacts.contacts.length;
|
||||
assert.equal(mozContactsLength, adnContactsLength);
|
||||
done();
|
||||
};
|
||||
|
||||
importer.start();
|
||||
});
|
||||
|
||||
test('Imported Contacts are saved with the iccManager provided id',
|
||||
function(done) {
|
||||
iccManager.adnContacts = [mRequestResult.adn[0]];
|
||||
|
||||
var realMozContact = window.mozContact;
|
||||
|
||||
window.mozContact = function(contact) {
|
||||
assert.equal(contact.id, mRequestResult.adn[0].id);
|
||||
};
|
||||
|
||||
importer.onfinish = function() {
|
||||
window.mozContact = realMozContact;
|
||||
done();
|
||||
};
|
||||
|
||||
importer.start();
|
||||
});
|
||||
});
|
||||
486
gaia/apps/communications/contacts/test/unit/import/import_test.js
Executable file
486
gaia/apps/communications/contacts/test/unit/import/import_test.js
Executable file
|
|
@ -0,0 +1,486 @@
|
|||
'use strict';
|
||||
|
||||
/* global utils, importer, MockAlphaScroll, MockImageLoader */
|
||||
/* global MockSearch, MockasyncStorage, MockOauthflow, MockImportHtml */
|
||||
/* global MockConnector, MockImportedContacts, MockCurtain, MockLazyLoader */
|
||||
/* global MockConfirmDialog */
|
||||
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/contacts/search.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
require('/shared/js/contacts/import/importer_ui.js');
|
||||
require('/shared/js/contacts/import/utilities/misc.js');
|
||||
require('/shared/js/contacts/utilities/dom.js');
|
||||
require('/shared/js/contacts/utilities/templates.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/import/mock_import.html.js');
|
||||
requireApp('communications/contacts/test/unit/mock_asyncstorage.js');
|
||||
requireApp('communications/contacts/test/unit/mock_search.js');
|
||||
requireApp('communications/contacts/test/unit/mock_oauthflow.js');
|
||||
require('/shared/js/contacts/import/friends_list.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_shortcuts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_utils.js');
|
||||
requireApp('communications/facebook/test/unit/mock_curtain.js');
|
||||
requireApp('communications/contacts/test/unit/import/mock_connector.js');
|
||||
requireApp(
|
||||
'communications/contacts/test/unit/import/mock_imported_contacts.js');
|
||||
|
||||
var realSearch,
|
||||
realImageLoader,
|
||||
realAlphaScroll,
|
||||
realAsyncStorage,
|
||||
realOauthflow,
|
||||
realCurtain,
|
||||
realLazyLoader,
|
||||
realConfirmDialog,
|
||||
realParentLazyLoader,
|
||||
groupsListChild, groupsList;
|
||||
|
||||
if (!window.asyncStorage) {
|
||||
window.asyncStorage = null;
|
||||
}
|
||||
|
||||
if (!window.ImageLoader) {
|
||||
window.ImageLoader = null;
|
||||
}
|
||||
|
||||
if (!window.contacts) {
|
||||
window.contacts = null;
|
||||
}
|
||||
|
||||
if (!window.onrendered) {
|
||||
window.onrendered = true;
|
||||
}
|
||||
|
||||
if (!window.oauthflow) {
|
||||
window.oauthflow = null;
|
||||
}
|
||||
|
||||
if (!window.LazyLoader) {
|
||||
window.LazyLoader = null;
|
||||
}
|
||||
|
||||
if (!window.ConfirmDialog) {
|
||||
window.ConfirmDialog = null;
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
importer.reset();
|
||||
});
|
||||
|
||||
|
||||
|
||||
suite('Import Friends Test Suite', function() {
|
||||
suiteSetup(function() {
|
||||
realAlphaScroll = utils.AlphaScroll;
|
||||
utils.alphaScroll = MockAlphaScroll;
|
||||
|
||||
realCurtain = window.Curtain;
|
||||
window.Curtain = MockCurtain;
|
||||
|
||||
realImageLoader = window.ImageLoader;
|
||||
window.ImageLoader = MockImageLoader;
|
||||
|
||||
realSearch = window.Search;
|
||||
window.Search = MockSearch;
|
||||
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
|
||||
realOauthflow = window.oauthflow;
|
||||
window.oauthflow = MockOauthflow;
|
||||
|
||||
realLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
realConfirmDialog = window.ConfirmDialog;
|
||||
window.ConfirmDialog = MockConfirmDialog;
|
||||
|
||||
realParentLazyLoader = window.parent.LazyLoader;
|
||||
window.parent.LazyLoader = MockLazyLoader;
|
||||
|
||||
document.body.innerHTML = MockImportHtml;
|
||||
|
||||
groupsList = document.body.querySelector('#groups-list');
|
||||
groupsListChild = groupsList.firstElementChild;
|
||||
|
||||
importer.ui.init();
|
||||
});
|
||||
|
||||
|
||||
test('Import UI. items created. not already present', function(done) {
|
||||
var contactsLoadedCalled = false;
|
||||
MockConnector.oncontactsloaded = function() {
|
||||
contactsLoadedCalled = true;
|
||||
};
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
assert.equal(document.querySelectorAll('#groups-list li').length,
|
||||
MockImportedContacts.data.length);
|
||||
|
||||
// MockAsyncStorage is ordering by first name
|
||||
assert.isNotNull(document.
|
||||
querySelector('section#group-P li[data-uuid="1xz"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('section#group-A li[data-uuid="2abc"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('section#group-Ψ li[data-uuid="3cde"]'));
|
||||
|
||||
assert.equal(document.querySelectorAll('section#group-G *').length, 0);
|
||||
|
||||
assert.equal(document.querySelector('input[name="1xz"]').checked, false);
|
||||
assert.equal(document.querySelector('input[name="2abc"]').checked, false);
|
||||
assert.equal(document.querySelector('input[name="3cde"]').checked, false);
|
||||
|
||||
assert.isTrue(document.getElementById('deselect-all').disabled);
|
||||
assert.isFalse(document.getElementById('select-all').disabled);
|
||||
assert.isTrue(document.getElementById('import-action').disabled);
|
||||
|
||||
if (contactsLoadedCalled) {
|
||||
done();
|
||||
}
|
||||
else {
|
||||
assert.fail('contactsLoaded not Called', 'contactsLoadedCalled');
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Import UI with some contacts already imported', function(done) {
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
var listDeviceContacts = MockConnector.listDeviceContacts;
|
||||
|
||||
MockConnector.listDeviceContacts = function(callbacks) {
|
||||
callbacks.success([
|
||||
{
|
||||
uid: '1xz'
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
var check = document.querySelector(
|
||||
'li[data-uuid="1xz"] input[type="checkbox"]');
|
||||
|
||||
assert.isTrue(check.checked);
|
||||
|
||||
var otherCheck = document.querySelector(
|
||||
'li[data-uuid="2abc"] input[type="checkbox"]');
|
||||
|
||||
assert.isFalse(otherCheck.checked);
|
||||
|
||||
assert.isFalse(document.getElementById('deselect-all').disabled);
|
||||
assert.isFalse(document.getElementById('select-all').disabled);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
MockConnector.listDeviceContacts = listDeviceContacts;
|
||||
});
|
||||
|
||||
test('Import UI with all contacts already imported', function(done) {
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
var listDeviceContacts = MockConnector.listDeviceContacts;
|
||||
|
||||
MockConnector.listDeviceContacts = function(callbacks) {
|
||||
callbacks.success([
|
||||
{
|
||||
uid: '1xz'
|
||||
},
|
||||
{
|
||||
uid: '2abc'
|
||||
},
|
||||
{
|
||||
uid: '3cde'
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
var check = document.querySelector(
|
||||
'li[data-uuid="1xz"] input[type="checkbox"]');
|
||||
|
||||
assert.isTrue(check.checked);
|
||||
|
||||
var otherCheck = document.querySelector(
|
||||
'li[data-uuid="2abc"] input[type="checkbox"]');
|
||||
|
||||
assert.isTrue(otherCheck.checked);
|
||||
|
||||
var anotherCheck = document.querySelector(
|
||||
'li[data-uuid="3cde"] input[type="checkbox"]');
|
||||
|
||||
assert.isTrue(anotherCheck.checked);
|
||||
|
||||
assert.isTrue(document.getElementById('deselect-all').disabled === false);
|
||||
assert.isTrue(document.getElementById('select-all').disabled === true);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
MockConnector.listDeviceContacts = listDeviceContacts;
|
||||
});
|
||||
|
||||
test('Import UI, Importing then deleting contacts from Outlook/Gmail ' +
|
||||
'returns the correct result', function(done) {
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
var listDeviceContacts = MockConnector.listDeviceContacts;
|
||||
// Simulate contacts already imported from the connector
|
||||
MockConnector.listDeviceContacts = function(callbacks) {
|
||||
callbacks.success([
|
||||
{
|
||||
uid: '1xz'
|
||||
},
|
||||
{
|
||||
uid: '2abc'
|
||||
},
|
||||
{
|
||||
uid: '3cde'
|
||||
}
|
||||
]);
|
||||
};
|
||||
// Simulate the desktop deletion of all contacts
|
||||
this.sinon.stub(MockConnector, 'listAllContacts',
|
||||
function(access_token, callbacks) {
|
||||
callbacks.success({data: []});
|
||||
}
|
||||
);
|
||||
|
||||
var spy = sinon.spy(window.ConfirmDialog, 'show');
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
done(function() {
|
||||
assert.isTrue(spy.called);
|
||||
assert.isTrue(spy.calledWith(null, 'emptyAccount'));
|
||||
});
|
||||
});
|
||||
|
||||
spy.restore();
|
||||
MockConnector.listDeviceContacts = listDeviceContacts;
|
||||
});
|
||||
|
||||
test('Import UI with no contacts available to import', function(done) {
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
|
||||
var listAllContacts = MockConnector.listAllContacts;
|
||||
|
||||
MockConnector.listAllContacts = function(access_token, callbacks) {
|
||||
callbacks.success({ data: []});
|
||||
};
|
||||
|
||||
var spy = sinon.spy(window.ConfirmDialog, 'show');
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
done(function() {
|
||||
assert.isTrue(spy.called);
|
||||
assert.isTrue(spy.calledWith(null, 'emptyAccount'));
|
||||
});
|
||||
});
|
||||
|
||||
spy.restore();
|
||||
MockConnector.listAllContacts = listAllContacts;
|
||||
});
|
||||
|
||||
suite('Import process', function() {
|
||||
var stubFriendListRenderer;
|
||||
var listDeviceContacts;
|
||||
var mockCurtainHide;
|
||||
var stubImporterImportAll;
|
||||
var stubParentPostMessage;
|
||||
|
||||
suiteSetup(function() {
|
||||
stubFriendListRenderer = sinon.stub(window.FriendListRenderer, 'render',
|
||||
function(contacts, cb) {
|
||||
cb();
|
||||
});
|
||||
|
||||
mockCurtainHide = MockCurtain.hide;
|
||||
MockCurtain.hide = function (cb) {cb();};
|
||||
|
||||
listDeviceContacts = MockConnector.listDeviceContacts;
|
||||
MockConnector.listDeviceContacts = function(callbacks) {
|
||||
callbacks.success([{uid: '1xz'}]);
|
||||
};
|
||||
stubImporterImportAll = sinon.stub(importer, 'importAll', function(cb) {
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
groupsList.innerHTML = '';
|
||||
groupsList.appendChild(groupsListChild);
|
||||
});
|
||||
|
||||
test('Import UI is closed when process ends in FTU', function(done) {
|
||||
var stubGetContext = sinon.stub(importer, 'getContext', function() {
|
||||
return 'ftu';
|
||||
});
|
||||
|
||||
stubParentPostMessage = sinon.stub(window.parent, 'postMessage',
|
||||
function(msg) {
|
||||
if (msg.type === 'window_close') {
|
||||
done(function() {
|
||||
assert.ok('passed');
|
||||
stubGetContext.restore();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
importer.start('mock_token', MockConnector, '*', function() {
|
||||
importer.setSelected({contact1: null});
|
||||
importer.ui.importAll();
|
||||
});
|
||||
});
|
||||
|
||||
test('Import UI is closed when process ends in contacts', function(done) {
|
||||
stubParentPostMessage = sinon.stub(window.parent, 'postMessage',
|
||||
function(msg) {
|
||||
if (msg.type === 'import_updated') {
|
||||
window.postMessage({type: 'contacts_loaded'}, '*');
|
||||
} else if (msg.type === 'window_close') {
|
||||
done(function() {
|
||||
assert.ok('passed');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
importer.start('mock_token', MockConnector, window.location.origin,
|
||||
function() {
|
||||
importer.setSelected({contact1: null});
|
||||
importer.ui.importAll();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Number of contacts available to import', function() {
|
||||
var fbContacts;
|
||||
var deviceContacts;
|
||||
var observer;
|
||||
|
||||
function setObserver(callback) {
|
||||
observer = new MutationObserver(callback);
|
||||
var observerTarget = document.getElementById('friends-msg');
|
||||
observer.observe(observerTarget, {attributes: true});
|
||||
|
||||
var MockFbConnector = {
|
||||
name: 'facebook',
|
||||
listAllContacts: function(token, cb) {
|
||||
cb.success({data: fbContacts.map(name => ({ name, uid: name }))});
|
||||
},
|
||||
listDeviceContacts: function(cb) {
|
||||
cb.success(deviceContacts.map(name => ({ name, uid: name })));
|
||||
},
|
||||
adaptDataForShowing: function(data) {
|
||||
return data;
|
||||
},
|
||||
getContactUid: function(data) {
|
||||
return data.uid;
|
||||
}
|
||||
};
|
||||
|
||||
window.importer.start('test_token', MockFbConnector);
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
sinon.stub(window.Curtain, 'hide', function() {});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.Curtain.hide.restore();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
observer.disconnect();
|
||||
});
|
||||
|
||||
test('If fb contacts < device contacts, 0', function(done) {
|
||||
fbContacts = ['contact1', 'contact2'];
|
||||
deviceContacts = ['contact1', 'contact2', 'contact3'];
|
||||
|
||||
setObserver(function(mutations) {
|
||||
done(function() {
|
||||
var l10nAttrs =
|
||||
navigator.mozL10n.getAttributes(mutations[0].target);
|
||||
assert.deepEqual(l10nAttrs.args, { numFriends : 0 },
|
||||
'The number must be 0');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('If fb contacts = device contacts, 0', function(done) {
|
||||
fbContacts = ['contact1', 'contact2', 'contact3'];
|
||||
deviceContacts = ['contact1', 'contact2', 'contact3'];
|
||||
|
||||
setObserver(function(mutations) {
|
||||
done(function() {
|
||||
var l10nAttrs =
|
||||
navigator.mozL10n.getAttributes(mutations[0].target);
|
||||
assert.deepEqual(l10nAttrs.args, { numFriends : 0 },
|
||||
'The number must be 0');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('If fb contacts > device contacts, >0', function(done) {
|
||||
fbContacts = ['contact1', 'contact2', 'contact3'];
|
||||
deviceContacts = ['contact1', 'contact2'];
|
||||
|
||||
setObserver(function(mutations) {
|
||||
done(function() {
|
||||
var l10nAttrs =
|
||||
navigator.mozL10n.getAttributes(mutations[0].target);
|
||||
assert.deepEqual(l10nAttrs.args, { numFriends : 1 },
|
||||
'The number must be 1');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubParentPostMessage.restore();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockConnector.listDeviceContacts = listDeviceContacts;
|
||||
stubImporterImportAll.restore();
|
||||
stubFriendListRenderer.restore();
|
||||
MockCurtain.hide = mockCurtainHide;
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
utils.alphaScroll = realAlphaScroll;
|
||||
window.ImageLoader = realImageLoader;
|
||||
window.Search = realSearch;
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
window.oauthflow = realOauthflow;
|
||||
window.curtain = realCurtain;
|
||||
window.LazyLoader = realLazyLoader;
|
||||
window.ConfirmDialog = realConfirmDialog;
|
||||
window.parent.LazyLoader = realParentLazyLoader;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('HTML format', function() {
|
||||
test('Contact name is tagged with the right class', function() {
|
||||
function loadImportHTML() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/shared/pages/import/import.html', false);
|
||||
req.send(null);
|
||||
return req.responseText;
|
||||
}
|
||||
|
||||
document.body.innerHTML = loadImportHTML();
|
||||
assert.ok(document.getElementsByClassName('contact-text'), 'Some element' +
|
||||
'with class contact-text should exist for search highlighting to work');
|
||||
});
|
||||
});
|
||||
42
gaia/apps/communications/contacts/test/unit/import/mock_connector.js
Executable file
42
gaia/apps/communications/contacts/test/unit/import/mock_connector.js
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
'use strict';
|
||||
|
||||
/* global MockImportedContacts */
|
||||
/* exported MockConnector */
|
||||
|
||||
var MockConnector = {
|
||||
listAllContacts: function(access_token, callbacks) {
|
||||
callbacks.success(MockImportedContacts);
|
||||
},
|
||||
|
||||
listDeviceContacts: function(callbacks) {
|
||||
callbacks.success([]);
|
||||
},
|
||||
|
||||
getImporter: function(contactsList, access_token) {
|
||||
},
|
||||
|
||||
getCleaner: function(contactsList, access_token) {
|
||||
},
|
||||
|
||||
adaptDataForShowing: function(source) {
|
||||
return source;
|
||||
},
|
||||
|
||||
adaptDataForSaving: function live2MozContact(liveContact) {
|
||||
},
|
||||
|
||||
getContactUid: function(deviceContact) {
|
||||
return deviceContact.uid || '-1';
|
||||
},
|
||||
|
||||
get name() {
|
||||
return 'mock';
|
||||
},
|
||||
|
||||
downloadContactPicture: function(contact, access_token, callbacks) {
|
||||
callbacks.success();
|
||||
},
|
||||
|
||||
startSync: function() {
|
||||
}
|
||||
};
|
||||
53
gaia/apps/communications/contacts/test/unit/import/mock_import.html
Executable file
53
gaia/apps/communications/contacts/test/unit/import/mock_import.html
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<section role="region" id="content" class="import">
|
||||
<gaia-header id="link-header" action="close">
|
||||
<h1 data-l10n-id="fbFriends">Facebook Friends</h1>
|
||||
<button id="import-action" data-l10n-id="import" disabled>
|
||||
Import
|
||||
</button>
|
||||
</gaia-header>
|
||||
|
||||
<section id="main">
|
||||
<section id="mainContent" data-state="selection">
|
||||
<form id="search-container" role="search" class="search">
|
||||
<p>
|
||||
<label for="search" id="search-start">
|
||||
<input type="search" name="search" class="textfield" placeholder="Search" data-l10n-id="search-contact">
|
||||
</label>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<section class="friends-msg">
|
||||
<output id="num-friends" hidden></output>
|
||||
<p id="friends-msg"></p>
|
||||
</section>
|
||||
<section id="groups-list" class="unbordered import-list" data-type="list">
|
||||
<section id="group-#group#" data-template>
|
||||
<header>#group#</header>
|
||||
<ol id="contacts-list-#group#">
|
||||
<li data-template data-uuid="#uid#" data-search="#search#" aria-disabled="false" class="block-item">
|
||||
<label class="pack-checkbox">
|
||||
<input type="checkbox" name="#uid#"></input>
|
||||
<span></span>
|
||||
</label>
|
||||
<aside class="pack-end">
|
||||
<img data-src="https://graph.facebook.com/#uid#/picture?type=square"></img>
|
||||
</aside>
|
||||
<p data-order-by="firstName"><strong>#givenName#</strong> #familyName#</p>
|
||||
<p data-order-by="lastName">#givenName# <strong>#familyName#</strong></p>
|
||||
<p>#email1#</p>
|
||||
</li>
|
||||
</ol>
|
||||
</section> <!-- group template content -->
|
||||
</section> <!-- groupsList -->
|
||||
|
||||
<form role="dialog" data-type="confirm" class="no-overlay">
|
||||
<menu id="select-all-wrapper">
|
||||
<button id="deselect-all" class="edit-button" data-l10n-id="deselectAll">
|
||||
Deselect all
|
||||
</button>
|
||||
<button id="select-all" class="edit-button" data-l10n-id="selectAll">
|
||||
Select all
|
||||
</button>
|
||||
</menu>
|
||||
</form>
|
||||
</section> <!-- mainContent -->
|
||||
11
gaia/apps/communications/contacts/test/unit/import/mock_import.html.js
Executable file
11
gaia/apps/communications/contacts/test/unit/import/mock_import.html.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockImportHtml */
|
||||
|
||||
var MockImportHtml = (function MockGoogleListing() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/import/mock_import.html', false);
|
||||
req.send(null);
|
||||
|
||||
return req.responseText;
|
||||
})();
|
||||
121
gaia/apps/communications/contacts/test/unit/import/mock_imported_contacts.js
Executable file
121
gaia/apps/communications/contacts/test/unit/import/mock_imported_contacts.js
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockImportedContacts */
|
||||
|
||||
var MockImportedContacts = {
|
||||
data: [
|
||||
{
|
||||
'uid': '1xz',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Germany',
|
||||
'locality': 'Chemnitz',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'Gotthardstrasse 22'
|
||||
}
|
||||
],
|
||||
'bday': '1978-12-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test@test.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['Grillo'],
|
||||
'givenName': ['Pepito'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Pepito Grillo'
|
||||
],
|
||||
'org': ['Test'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+346578888888',
|
||||
'type': 'Mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'category': [
|
||||
'favorite'
|
||||
],
|
||||
'note': [
|
||||
'Note 1'
|
||||
],
|
||||
'photo': ['test.png']
|
||||
}
|
||||
,
|
||||
{
|
||||
'uid': '2abc',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Spain',
|
||||
'locality': 'Burgos',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'El Espolón, 25'
|
||||
}
|
||||
],
|
||||
'bday': '1932-12-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test2@test2.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['Gonzo'],
|
||||
'givenName': ['Alfonso'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Alfonso Gonzo'
|
||||
],
|
||||
'org': ['Retired 2.0'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+34612456789',
|
||||
'type': 'Mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'photo': ['test2.png']
|
||||
}
|
||||
,
|
||||
{
|
||||
'uid': '3cde',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Spain',
|
||||
'locality': 'Lugo',
|
||||
'postalCode': '19034',
|
||||
'streetAddress': 'Mallorca, 25'
|
||||
}
|
||||
],
|
||||
'bday': '1965-11-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test3@test3.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['Lucca'],
|
||||
'givenName': ['Ψoca'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Ψoca Lucca'
|
||||
],
|
||||
'org': ['Testing'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+34555666777',
|
||||
'type': 'Mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'photo': ['test3.png']
|
||||
}
|
||||
]
|
||||
};
|
||||
48
gaia/apps/communications/contacts/test/unit/import/mock_rest.js
Executable file
48
gaia/apps/communications/contacts/test/unit/import/mock_rest.js
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockRest */
|
||||
|
||||
/*
|
||||
Mocking the Rest utility class, it's configurable to behave
|
||||
differently via the configure method
|
||||
*/
|
||||
var MockRest = (function MockRest() {
|
||||
|
||||
var config = {
|
||||
// Values are success, error, timeout (the possible callbacks)
|
||||
'type': 'success'
|
||||
// Follow with a series of 'urls' and the values returned
|
||||
};
|
||||
|
||||
var configure = function configure(conf) {
|
||||
config = conf;
|
||||
};
|
||||
|
||||
var get = function get(url, callbacks, options) {
|
||||
if (!config[url]) {
|
||||
callbacks.error('No matching for url ' + url);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (config.type) {
|
||||
case 'success':
|
||||
callbacks.success(config[url]);
|
||||
break;
|
||||
case 'error':
|
||||
callbacks.error(config[url]);
|
||||
break;
|
||||
case 'timeout':
|
||||
callbacks.timeout(config[url]);
|
||||
break;
|
||||
default:
|
||||
callbacks.timeout(config[url]);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
'get': get,
|
||||
'configure': configure
|
||||
};
|
||||
|
||||
})();
|
||||
80
gaia/apps/communications/contacts/test/unit/import/redirect_test.js
Executable file
80
gaia/apps/communications/contacts/test/unit/import/redirect_test.js
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
|
||||
/* global Redirect */
|
||||
|
||||
require('/shared/pages/import/redirects/redirect.js');
|
||||
|
||||
|
||||
suite('OAuth redirect', function() {
|
||||
|
||||
var openerDefinition;
|
||||
|
||||
var myOpenerObject = {
|
||||
postMessage: function() {}
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
openerDefinition = Object.getOwnPropertyDescriptor(window, 'opener');
|
||||
|
||||
Object.defineProperty(window, 'opener', {
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
value: myOpenerObject
|
||||
});
|
||||
|
||||
sinon.stub(window, 'close', function() {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
window.close.reset();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
Object.defineProperty(window, 'opener', openerDefinition);
|
||||
window.close.restore();
|
||||
});
|
||||
|
||||
suite('> Recirect with valid access token', function() {
|
||||
test('> Check token', function() {
|
||||
this.sinon.spy(window.opener, 'postMessage');
|
||||
document.location.hash = 'access_token=ok';
|
||||
Redirect.init();
|
||||
|
||||
sinon.assert.pass(window.close.calledOnce);
|
||||
sinon.assert.pass(myOpenerObject.postMessage.calledOnce);
|
||||
sinon.assert.calledWith(myOpenerObject.postMessage,
|
||||
{'access_token': 'ok'});
|
||||
});
|
||||
|
||||
test('> Check parameters', function() {
|
||||
this.sinon.spy(window.opener, 'postMessage');
|
||||
document.location.hash = 'access_token=ok¶m1=1¶m2=2';
|
||||
Redirect.init();
|
||||
|
||||
sinon.assert.pass(window.close.calledOnce);
|
||||
sinon.assert.pass(myOpenerObject.postMessage.calledOnce);
|
||||
sinon.assert.calledWith(myOpenerObject.postMessage,
|
||||
{
|
||||
'access_token': 'ok',
|
||||
'param1': '1',
|
||||
'param2': '2'
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('> Redirect with invalid access token', function() {
|
||||
test('No access token', function() {
|
||||
this.sinon.spy(window.opener, 'postMessage');
|
||||
document.location.hash = 'invalid';
|
||||
Redirect.init();
|
||||
|
||||
sinon.assert.pass(window.close.calledOnce);
|
||||
sinon.assert.callCount(myOpenerObject.postMessage, 0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
199
gaia/apps/communications/contacts/test/unit/import_vcard_test.js
Executable file
199
gaia/apps/communications/contacts/test/unit/import_vcard_test.js
Executable file
|
|
@ -0,0 +1,199 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockLoader,
|
||||
MockMozL10n, utils, MockMatcher, MockMozContacts */
|
||||
|
||||
require('/shared/js/contacts/import/utilities/import_from_vcard.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_contact.js');
|
||||
require('/shared/test/unit/mocks/mock_mozContacts.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_contacts_match.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/contacts/test/unit/mock_vcard_reader.js');
|
||||
requireApp('communications/contacts/test/unit/mock_file_reader.js');
|
||||
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
|
||||
requireApp('communications/contacts/test/unit/mock_navigation.js');
|
||||
requireApp('communications/contacts/test/unit/mock_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_loader.js');
|
||||
requireApp('/shared/test/unit/mocks/mock_moz_contact.js');
|
||||
|
||||
if (!window._) {
|
||||
window._ = null;
|
||||
}
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = null;
|
||||
}
|
||||
|
||||
var mocksHelperForImportVcard = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'mozContact',
|
||||
'Contacts',
|
||||
'VCardReader',
|
||||
'ConfirmDialog',
|
||||
'FileReader'
|
||||
]).init();
|
||||
|
||||
var vcardSingle = 'BEGIN:VCARD\n' +
|
||||
'VERSION:2.1\n' +
|
||||
'N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Gump;F=C3=B3rrest\n' +
|
||||
'ORG;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:B=C3=B3bba Gump Shrimp Co.\n' +
|
||||
'TITLE;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Shr=C3=B3mp Man\n' +
|
||||
'PHOTO;GIF:http://www.example.com/dir_photos/my_photo.gif\n' +
|
||||
'TEL;WORK;VOICE:(111) 555-1212\n' +
|
||||
'TEL;HOME;VOICE:(404) 555-1212\n' +
|
||||
'ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;100 W=C3=A1ters Edge;Baytown;LA;' +
|
||||
'30314;United States of America\n' +
|
||||
'LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America\n' +
|
||||
'LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'EMAIL;PREF;INTERNET:forrestgump@example.com\n' +
|
||||
'REV:20080424T195243Z\n' +
|
||||
'END:VCARD';
|
||||
|
||||
var vcardMultiple = 'BEGIN:VCARD\n' +
|
||||
'VERSION:2.1\n' +
|
||||
'N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Gump;F=C3=B3rrest\n' +
|
||||
'ORG;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:B=C3=B3bba Gump Shrimp Co.\n' +
|
||||
'TITLE;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Shr=C3=B3mp Man\n' +
|
||||
'PHOTO;GIF:http://www.example.com/dir_photos/my_photo.gif\n' +
|
||||
'TEL;WORK;VOICE:(111) 555-1212\n' +
|
||||
'TEL;HOME;VOICE:(404) 555-1212\n' +
|
||||
'ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;100 W=C3=A1ters Edge;Baytown;LA;' +
|
||||
'30314;United States of America\n' +
|
||||
'LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America\n' +
|
||||
'LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'EMAIL;PREF;INTERNET:forrestgump@example.com\n' +
|
||||
'REV:20080424T195243Z\n' +
|
||||
'END:VCARD' +
|
||||
'BEGIN:VCARD\n' +
|
||||
'VERSION:2.1\n' +
|
||||
'N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Gump;F=C3=B3rrest\n' +
|
||||
'ORG;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:B=C3=B3bba Gump Shrimp Co.\n' +
|
||||
'TITLE;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:Shr=C3=B3mp Man\n' +
|
||||
'PHOTO;GIF:http://www.example.com/dir_photos/my_photo.gif\n' +
|
||||
'TEL;WORK;VOICE:(111) 555-1212\n' +
|
||||
'TEL;HOME;VOICE:(404) 555-1212\n' +
|
||||
'ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;100 W=C3=A1ters Edge;Baytown;LA;' +
|
||||
'30314;United States of America\n' +
|
||||
'LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America\n' +
|
||||
'LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, ' +
|
||||
'LA 30314=0D=0AUnited States of America\n' +
|
||||
'EMAIL;PREF;INTERNET:forrestgump@example.com\n' +
|
||||
'REV:20080424T195243Z\n' +
|
||||
'END:VCARD';
|
||||
|
||||
var vcardError = 'error';
|
||||
|
||||
var contact1 = {
|
||||
id: '0'
|
||||
};
|
||||
|
||||
suite('Import from vcard', function() {
|
||||
var realMozL10n,
|
||||
real_,
|
||||
realStatus,
|
||||
realMatcher,
|
||||
realOverlay,
|
||||
realLoader;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockMozL10n;
|
||||
|
||||
real_ = window._;
|
||||
window._ = navigator.mozL10n.get;
|
||||
|
||||
realStatus = window.utils.status;
|
||||
realOverlay = window.utils.overlay;
|
||||
|
||||
navigator.mozContacts = MockMozContacts;
|
||||
sinon.stub(navigator.mozContacts, 'find', function mockMozContactsFind() {
|
||||
var self = this;
|
||||
var req = {
|
||||
set onsuccess(cb) {
|
||||
req.result = self.contacts;
|
||||
cb();
|
||||
},
|
||||
set onerror(cb) {},
|
||||
};
|
||||
return req;
|
||||
});
|
||||
|
||||
window.contacts = window.contacts || {};
|
||||
realMatcher = window.Matcher;
|
||||
window.Matcher = MockMatcher;
|
||||
|
||||
realLoader = window.Loader;
|
||||
window.Loader = MockLoader;
|
||||
|
||||
window.utils.overlay = {
|
||||
total: 0,
|
||||
show: function() {
|
||||
return this;
|
||||
},
|
||||
hide: function() {},
|
||||
showMenu: function() {},
|
||||
update: function() {},
|
||||
setClass: function() {},
|
||||
setTotal: function(n) {
|
||||
this.total = n;
|
||||
},
|
||||
setHeaderMsg: function() {}
|
||||
};
|
||||
|
||||
window.utils.status = {
|
||||
show: function() {}
|
||||
};
|
||||
|
||||
mocksHelperForImportVcard.suiteSetup();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
window.utils.overlay.total = 0;
|
||||
navigator.mozContacts.contacts = [];
|
||||
mocksHelperForImportVcard.setup();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realMozL10n;
|
||||
window._ = real_;
|
||||
window.Matcher = realMatcher;
|
||||
window.utils.status = realStatus;
|
||||
window.utils.overlay = realOverlay;
|
||||
window.Loader = realLoader;
|
||||
mocksHelperForImportVcard.suiteTeardown();
|
||||
});
|
||||
|
||||
test('Import single contact', function(done) {
|
||||
utils.importFromVcard(vcardSingle, function(numberOfContacts, id) {
|
||||
assert.equal(id, contact1.id, 'return id of the contact imported');
|
||||
assert.equal(window.utils.overlay.total, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Import multiple contacts', function(done) {
|
||||
utils.importFromVcard(vcardMultiple, function(numberOfContacts, id) {
|
||||
assert.equal(id, contact1.id, 'returns id of the first contact imported');
|
||||
assert.equal(window.utils.overlay.total, 2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Error while importing', function(done) {
|
||||
utils.importFromVcard(vcardError, function(numberOfContacts, id) {
|
||||
assert.isUndefined(id, 'returns no id as there was an error');
|
||||
assert.equal(window.utils.overlay.total, 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
259
gaia/apps/communications/contacts/test/unit/link_test.js
Executable file
259
gaia/apps/communications/contacts/test/unit/link_test.js
Executable file
|
|
@ -0,0 +1,259 @@
|
|||
'use strict';
|
||||
/* global fb */
|
||||
/* global MockAllFacebookContacts:true */
|
||||
/* global MockasyncStorage */
|
||||
/* global Mockfb */
|
||||
/* global MockImageLoader */
|
||||
/* global MockLinkedContacts:true */
|
||||
/* global MockLinkHtml */
|
||||
/* global MockOauthflow */
|
||||
/* global MockCurtain */
|
||||
|
||||
require('/shared/js/text_normalizer.js');
|
||||
require('/shared/js/binary_search.js');
|
||||
require('/shared/js/contacts/import/utilities/misc.js');
|
||||
require('/shared/js/contacts/utilities/dom.js');
|
||||
require('/shared/js/contacts/utilities/templates.js');
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_link.html.js');
|
||||
requireApp('communications/contacts/test/unit/mock_l10n.js');
|
||||
requireApp('communications/facebook/test/unit/mock_curtain.js');
|
||||
requireApp('communications/contacts/test/unit/mock_utils.js');
|
||||
requireApp('communications/contacts/test/unit/mock_asyncstorage.js');
|
||||
requireApp('communications/contacts/test/unit/mock_linked_contacts.js');
|
||||
requireApp('communications/contacts/test/unit/mock_fb.js');
|
||||
requireApp('communications/contacts/test/unit/mock_oauthflow.js');
|
||||
requireApp('communications/contacts/js/fb/fb_link.js');
|
||||
|
||||
var realImageLoader,
|
||||
realAsyncStorage,
|
||||
realFb,
|
||||
realOauthflow,
|
||||
realCurtain,
|
||||
linkProposal,
|
||||
linkProposalChild;
|
||||
|
||||
|
||||
if (!window.asyncStorage) {
|
||||
window.asyncStorage = null;
|
||||
}
|
||||
|
||||
if (!window.ImageLoader) {
|
||||
window.ImageLoader = null;
|
||||
}
|
||||
|
||||
if (!window.fb) {
|
||||
window.fb = null;
|
||||
}
|
||||
|
||||
if (!window.oauthflow) {
|
||||
window.oauthflow = null;
|
||||
}
|
||||
|
||||
suite('Link Friends Test Suite', function() {
|
||||
|
||||
var spy;
|
||||
|
||||
suiteSetup(function() {
|
||||
realImageLoader = window.ImageLoader;
|
||||
window.ImageLoader = MockImageLoader;
|
||||
|
||||
realCurtain = window.Curtain;
|
||||
window.Curtain = MockCurtain;
|
||||
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
|
||||
realFb = window.fb;
|
||||
window.fb = Mockfb;
|
||||
window.fb.link = realFb.link;
|
||||
|
||||
realOauthflow = window.oauthflow;
|
||||
window.oauthflow = MockOauthflow;
|
||||
|
||||
spy = sinon.spy(fb.utils, 'setCachedNumFriends').withArgs(
|
||||
MockAllFacebookContacts.data.length);
|
||||
|
||||
document.body.innerHTML = MockLinkHtml;
|
||||
|
||||
linkProposal = document.body.querySelector('#friends-list');
|
||||
|
||||
linkProposalChild = linkProposal.firstElementChild;
|
||||
|
||||
fb.link.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
spy.reset();
|
||||
});
|
||||
|
||||
test('Link UI. Proposal Calculated', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
fb.utils.result = {
|
||||
givenName: ['Jose'],
|
||||
tel: [{
|
||||
type: ['home'],
|
||||
value: '678956345'
|
||||
}]
|
||||
};
|
||||
|
||||
fb.link.start('mock_token', '123456', function() {
|
||||
// As the template itself also counts
|
||||
assert.equal(document.querySelectorAll('#friends-list li').length, 3);
|
||||
|
||||
// Here we check for the UIDs of the MockLinkedContacts
|
||||
// which are defined on the mock_linked_contacts.js source
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="1xz"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="2abc"]'));
|
||||
|
||||
// Check that the total number of friends is properly cached (bug 838605)
|
||||
assert.isTrue(spy.calledOnce);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Link UI. No proposals. Showing All', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
var oldMockLinkedContacts = MockLinkedContacts;
|
||||
|
||||
MockLinkedContacts = {
|
||||
data: []
|
||||
};
|
||||
|
||||
fb.link.start('mock_token', '123456', function() {
|
||||
// As the template itself also counts
|
||||
assert.equal(document.querySelectorAll('#friends-list li').length, 5);
|
||||
|
||||
// Here we check for the UIDs of the MockAllFacebookContacts
|
||||
// which are defined on the mock_linked_contacts.js source
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="5678x"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="56zwt"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="kjh2389"]'));
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="aa45bb"]'));
|
||||
|
||||
MockLinkedContacts = oldMockLinkedContacts;
|
||||
|
||||
// Check that the total number of friends is properly cached (bug 838605)
|
||||
assert.isTrue(spy.calledOnce);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Link UI. Matching by givenName >accents in proposal', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
fb.utils.result = {
|
||||
givenName: ['Angela']
|
||||
};
|
||||
|
||||
fb.link.start('mock_token', '123456', function() {
|
||||
// As the template itself also counts
|
||||
assert.equal(document.querySelectorAll('#friends-list li').length, 2);
|
||||
|
||||
// Here we check for the id of the MockLinkedContact whose first_name
|
||||
// is 'Ángela'
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="kjh2389"]'));
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Link UI. Matching by givenName >accents in local data', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
var oldMockAllFacebookContacts = MockAllFacebookContacts;
|
||||
|
||||
MockAllFacebookContacts.data[2].name = 'Angela Cuts';
|
||||
MockAllFacebookContacts.data[2].first_name = 'Angela';
|
||||
|
||||
// To enable the accents match
|
||||
fb.utils.result = {
|
||||
givenName: ['Ángela']
|
||||
};
|
||||
|
||||
fb.link.start('mock_token', '123456', function() {
|
||||
// As the template itself also counts
|
||||
assert.equal(document.querySelectorAll('#friends-list li').length, 2);
|
||||
|
||||
// Here we check for the id of the MockLinkedContact whose first_name
|
||||
// is 'Angela'
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="kjh2389"]'));
|
||||
|
||||
MockAllFacebookContacts = oldMockAllFacebookContacts;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Link UI. Matching by familyName > accents in both', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
fb.utils.result = {
|
||||
familyName: ['González']
|
||||
};
|
||||
|
||||
fb.link.start('mock_token', '123456', function() {
|
||||
// As the template itself also counts
|
||||
assert.equal(document.querySelectorAll('#friends-list li').length, 2);
|
||||
|
||||
// Here we check for the id of the MockLinkedContact whose lasr_name
|
||||
// is 'González'
|
||||
assert.isNotNull(document.
|
||||
querySelector('li[data-uuid="aa45bb"]'));
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Link UI process', function() {
|
||||
test('Link UI process ends as expected', function(done) {
|
||||
linkProposal.innerHTML = '';
|
||||
linkProposal.appendChild(linkProposalChild);
|
||||
|
||||
sinon.stub(window.Curtain, 'hide', function(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
|
||||
sinon.stub(window.parent, 'postMessage', function(msg) {
|
||||
done(function() {
|
||||
window.Curtain.hide.restore();
|
||||
window.parent.postMessage.restore();
|
||||
assert.equal(msg.type, 'ready', 'Sent message is of type \'ready\'.');
|
||||
});
|
||||
});
|
||||
|
||||
fb.link.start('mock_token', '123456');
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.ImageLoader = realImageLoader;
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
window.fb = realFb;
|
||||
window.oauthflow = realOauthflow;
|
||||
window.Curtain = realCurtain;
|
||||
});
|
||||
|
||||
});
|
||||
146
gaia/apps/communications/contacts/test/unit/migrator_test.js
Executable file
146
gaia/apps/communications/contacts/test/unit/migrator_test.js
Executable file
|
|
@ -0,0 +1,146 @@
|
|||
'use strict';
|
||||
|
||||
/* global Migrator, MockImportStatusData, Mockfb, MockDatastoreMigration,
|
||||
MockasyncStorage */
|
||||
|
||||
requireApp('communications/contacts/test/unit/mock_import_status_data.js');
|
||||
requireApp('communications/contacts/test/unit/mock_asyncstorage.js');
|
||||
requireApp('communications/contacts/test/unit/mock_fb.js');
|
||||
requireApp('communications/contacts/test/unit/mock_datastore_migrator.js');
|
||||
requireApp('communications/contacts/js/migrator.js');
|
||||
|
||||
if (!window.LazyLoader) {
|
||||
var LazyLoader = {load: function(){}};
|
||||
}
|
||||
|
||||
if (!window.ImportStatusData) {
|
||||
window.ImportStatusData = null;
|
||||
}
|
||||
|
||||
if (!window.fb) {
|
||||
window.fb = null;
|
||||
}
|
||||
|
||||
if (!window.DatastoreMigration) {
|
||||
window.DatastoreMigration = null;
|
||||
}
|
||||
|
||||
if (!window.asyncStorage) {
|
||||
window.asyncStorage = null;
|
||||
}
|
||||
|
||||
if (!window.utils) {
|
||||
window.utils = {
|
||||
cookie: {update: function() {}}
|
||||
};
|
||||
}
|
||||
|
||||
suite('Migrator module', function() {
|
||||
var realImportStatusData,
|
||||
realFb,
|
||||
realDatastoreMigration,
|
||||
realAsyncStorage;
|
||||
|
||||
suiteSetup(function() {
|
||||
realImportStatusData = window.ImportStatusData;
|
||||
window.ImportStatusData = MockImportStatusData;
|
||||
|
||||
realFb = window.fb;
|
||||
window.fb = Mockfb;
|
||||
|
||||
realDatastoreMigration = window.DatastoreMigration;
|
||||
window.DatastoreMigration = MockDatastoreMigration;
|
||||
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.ImportStatusData = realImportStatusData;
|
||||
window.fb = realFb;
|
||||
window.DatastoreMigration = realDatastoreMigration;
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockasyncStorage.clear();
|
||||
MockImportStatusData.clear();
|
||||
});
|
||||
|
||||
test('Don\'t migrate anything', function() {
|
||||
var spy = sinon.spy(LazyLoader, 'load');
|
||||
|
||||
Migrator.start({
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: true
|
||||
});
|
||||
|
||||
assert.isFalse(spy.called, 'A migration was not triggered.');
|
||||
LazyLoader.load.restore();
|
||||
});
|
||||
|
||||
test('Trigger facebook contacts migration only', function(done) {
|
||||
sinon.stub(LazyLoader, 'load', function(files, callback) {
|
||||
callback();
|
||||
});
|
||||
|
||||
window.DatastoreMigration = function() {
|
||||
return {
|
||||
start: function() {
|
||||
window.DatastoreMigration = MockDatastoreMigration;
|
||||
LazyLoader.load.restore();
|
||||
done();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Migrator.start({
|
||||
fbMigrated: false,
|
||||
accessTokenMigrated: true
|
||||
});
|
||||
});
|
||||
|
||||
test('Trigger facebook token migration only', function(done) {
|
||||
sinon.stub(LazyLoader, 'load', function(files, callback) {
|
||||
callback();
|
||||
});
|
||||
|
||||
window.fb.utils = {
|
||||
get TOKEN_DATA_KEY() {
|
||||
window.fb.utils = {TOKEN_DATA_KEY: null};
|
||||
window.fb = Mockfb;
|
||||
LazyLoader.load.restore();
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
Migrator.start({
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: false
|
||||
});
|
||||
});
|
||||
|
||||
test('Don\'t migrate fb token if it is not in asyncStorage', function() {
|
||||
MockasyncStorage.keys[Mockfb.utils.TOKEN_DATA_KEY] = true;
|
||||
|
||||
sinon.stub(LazyLoader, 'load', function(files, callback) {
|
||||
callback();
|
||||
});
|
||||
|
||||
var spy = sinon.spy(window.utils.cookie, 'update');
|
||||
|
||||
sinon.stub(window.asyncStorage, 'removeItem', function(key) {
|
||||
window.asyncStorage.removeItem.restore();
|
||||
LazyLoader.load.restore();
|
||||
assert.isTrue(spy.called);
|
||||
spy.restore();
|
||||
assert.equal(key, Mockfb.utils.TOKEN_DATA_KEY);
|
||||
});
|
||||
|
||||
Migrator.start({
|
||||
fbMigrated: true,
|
||||
accessTokenMigrated: false
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
22
gaia/apps/communications/contacts/test/unit/mock_action_menu.js
Executable file
22
gaia/apps/communications/contacts/test/unit/mock_action_menu.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
/* exported ActionMenu */
|
||||
|
||||
function ActionMenu() {
|
||||
return {
|
||||
data: {
|
||||
list: []
|
||||
},
|
||||
show: function() {
|
||||
this.data.list[0].callback();
|
||||
},
|
||||
hide: function() {
|
||||
this.data.list = [];
|
||||
},
|
||||
addToList: function(labelL10n, callback) {
|
||||
this.data.list.push({
|
||||
'type': [labelL10n],
|
||||
'callback': callback
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
23
gaia/apps/communications/contacts/test/unit/mock_activities.js
Executable file
23
gaia/apps/communications/contacts/test/unit/mock_activities.js
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
/* exported MockActivityHandler */
|
||||
'use strict';
|
||||
|
||||
var MockActivityHandler = {
|
||||
currentlyHandling: false,
|
||||
activityName: 'view',
|
||||
currentActivityIs: function(list) {
|
||||
return this.currentlyHandling && list.indexOf(this.activityName) !== -1;
|
||||
},
|
||||
currentActivityIsNot: function(list) {
|
||||
return this.currentlyHandling && list.indexOf(this.activityName) === -1;
|
||||
},
|
||||
postPickSuccess: function(data) {},
|
||||
postCancel: function() {},
|
||||
dataPickHandler: function() {},
|
||||
isCancelable: function() {
|
||||
return {
|
||||
then: function(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
29
gaia/apps/communications/contacts/test/unit/mock_asyncstorage.js
Executable file
29
gaia/apps/communications/contacts/test/unit/mock_asyncstorage.js
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
'use strict';
|
||||
/* exported MockasyncStorage */
|
||||
|
||||
var MockasyncStorage = {
|
||||
keys: {},
|
||||
|
||||
getItem: function(key, cb) {
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
cb(this.keys[key]);
|
||||
},
|
||||
|
||||
setItem: function(key, value, cb) {
|
||||
this.keys[key] = value;
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
},
|
||||
|
||||
removeItem: function(key) {
|
||||
delete this.keys[key];
|
||||
},
|
||||
|
||||
clear: function(key) {
|
||||
this.keys = {};
|
||||
}
|
||||
};
|
||||
38
gaia/apps/communications/contacts/test/unit/mock_cache.js
Executable file
38
gaia/apps/communications/contacts/test/unit/mock_cache.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockCache */
|
||||
|
||||
var MockCache = {
|
||||
active: false,
|
||||
enabled: false,
|
||||
setFirstChunk(content) {
|
||||
|
||||
},
|
||||
hasContact: function(uuid) {
|
||||
|
||||
},
|
||||
hasFavorite: function(uuid) {
|
||||
|
||||
},
|
||||
getContact: function(uuid) {
|
||||
|
||||
},
|
||||
getFavorite: function(uuid) {
|
||||
|
||||
},
|
||||
get headers() {
|
||||
return {};
|
||||
},
|
||||
verify: function() {
|
||||
|
||||
},
|
||||
cleanup: function() {
|
||||
|
||||
},
|
||||
evict: function() {
|
||||
|
||||
},
|
||||
maybeEvict: function() {
|
||||
|
||||
}
|
||||
};
|
||||
33
gaia/apps/communications/contacts/test/unit/mock_confirm_dialog.js
Executable file
33
gaia/apps/communications/contacts/test/unit/mock_confirm_dialog.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
'use strict';
|
||||
/* exported MockConfirmDialog */
|
||||
|
||||
var MockConfirmDialog = {
|
||||
showing: false,
|
||||
title: null,
|
||||
text: null,
|
||||
noObject: null,
|
||||
yesObject: null,
|
||||
show: function(title, text, no, yes) {
|
||||
this.showing = true;
|
||||
this.title = title;
|
||||
this.text = text;
|
||||
this.noObject = no;
|
||||
this.yesObject = yes;
|
||||
},
|
||||
hide: function() {
|
||||
this.showing = false;
|
||||
this.title = null;
|
||||
this.text = null;
|
||||
this.button = null;
|
||||
},
|
||||
executeNo: function() {
|
||||
if (this.noObject && this.noObject.callback) {
|
||||
this.noObject.callback();
|
||||
}
|
||||
},
|
||||
executeYes: function() {
|
||||
if (this.yesObject && this.yesObject.callback) {
|
||||
this.yesObject.callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
50
gaia/apps/communications/contacts/test/unit/mock_contact_list_dom.js.html
Executable file
50
gaia/apps/communications/contacts/test/unit/mock_contact_list_dom.js.html
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
var ContactListDom =
|
||||
' <!-- Contacts List Section -->' +
|
||||
' <section id="view-contacts-list" role="region" data-state="active" class="view view-noscroll view-contacts-list">' +
|
||||
' <gaia-header id="activity-header" action="close">' +
|
||||
' <h1 id="app-title" data-l10n-id="contacts">Contacts</h1>' +
|
||||
' <button id="add-contact-button" data-icon="add" data-l10n-id="addButton"></button>' +
|
||||
' <button id="settings-button" data-icon="settings" data-l10n-id="settingsButton"></button>' +
|
||||
' </gaia-header>' +
|
||||
|
||||
' <article class="view-body">' +
|
||||
' <div id="no-contacts" class="hide">' +
|
||||
' <div class="arrow small">' +
|
||||
' <p class="small" data-l10n-id="create-new">Create a new contact</p>' +
|
||||
' </div>' +
|
||||
' <div class="arrow big">' +
|
||||
' <p class="small" data-l10n-id="import-now">Import your contacts from your SIM card or from Facebook</p>' +
|
||||
' </div>' +
|
||||
' <div class="info">' +
|
||||
' <p data-l10n-id="no-contacts">no contacts</p>' +
|
||||
' <p data-l10n-id="start-adding">start adding them now </p>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' <nav data-type="scrollbar">' +
|
||||
' <p></p>' +
|
||||
' <ol>' +
|
||||
' <li data-anchor="search-container" data-img="magnifier_icon_big.png">' +
|
||||
' <a href="#"><span class="pack-icon-search">Search</span></a>' +
|
||||
' </li>' +
|
||||
' <li data-anchor="group-favorites" data-img="star_icon_big.png">' +
|
||||
' <a href="#"><span class="pack-icon-favorites">Favorites</span></a>' +
|
||||
' </li>' +
|
||||
' <li data-template data-anchor="group-#anchor#" data-letter="#anchor#">' +
|
||||
' <a href="#">#anchor#</a>' +
|
||||
' </li>' +
|
||||
' </ol>' +
|
||||
' </nav>' +
|
||||
' <div id="groups-container" class="view-body-inner">' +
|
||||
' <form id="search-container" class="search" role="search">' +
|
||||
' <p>' +
|
||||
' <label for="search" id="search-start">' +
|
||||
' <input type="search" name="search" class="textfield" placeholder="Search" data-l10n-id="search-contact">' +
|
||||
' </label>' +
|
||||
' </p>' +
|
||||
' </form>' +
|
||||
' <section id="groups-list" data-type="list">' +
|
||||
' <!-- Group template here -->' +
|
||||
' </section>' +
|
||||
' </div>' +
|
||||
' </article>' +
|
||||
' </section>';
|
||||
51
gaia/apps/communications/contacts/test/unit/mock_contacts.js
Executable file
51
gaia/apps/communications/contacts/test/unit/mock_contacts.js
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
/* exported MockContacts */
|
||||
/* exported COMMS_APP_ORIGIN */
|
||||
|
||||
var COMMS_APP_ORIGIN = location.origin;
|
||||
|
||||
var loadAsyncScriptsDeferred = {};
|
||||
loadAsyncScriptsDeferred.promise = new Promise((resolve) => {
|
||||
loadAsyncScriptsDeferred.resolve = resolve;
|
||||
});
|
||||
|
||||
var MockContacts = {
|
||||
isEmpty: function(prop) {
|
||||
return false;
|
||||
},
|
||||
hideOverlay: function() {
|
||||
},
|
||||
loadFacebook: function(cb) {
|
||||
cb();
|
||||
},
|
||||
cardStateChanged: function() {
|
||||
},
|
||||
cancel: function() {},
|
||||
utility: function(view, callback, type) {
|
||||
callback();
|
||||
},
|
||||
view: function(view, callback) {
|
||||
callback();
|
||||
},
|
||||
showOverlay: function(title, id) {
|
||||
return {
|
||||
'setClass': function(clazz) {},
|
||||
'setHeaderMsg': function(msg) {},
|
||||
'setTotal': function(total) {},
|
||||
'update': function() {}
|
||||
};
|
||||
},
|
||||
goBack: function(cb) {
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
},
|
||||
setCurrent: function(ct) {
|
||||
|
||||
},
|
||||
get asyncScriptsLoaded() {
|
||||
loadAsyncScriptsDeferred.resolve();
|
||||
return loadAsyncScriptsDeferred.promise;
|
||||
},
|
||||
showForm: function() {}
|
||||
};
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockAdaptAndMerge */
|
||||
|
||||
var MockAdaptAndMerge = function (contact, matches, callbacks) {
|
||||
callbacks.error();
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
var MockContactsButtonsDom = `<section id="contact-detail">
|
||||
<section id="phone-details">
|
||||
<li data-phone id='phone-details-template-#i#' data-template>
|
||||
<h2>
|
||||
<span data-l10n-id="#type_l10n_id#">#type#</span>
|
||||
<span class="carrier-wrapper" hidden>
|
||||
<span data-l10n-id="separator"></span>
|
||||
<span class="carrier">#carrier#</span>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="item">
|
||||
<div class="item-media pull-right">
|
||||
<button id="send-sms-button-#i#"
|
||||
class="activity send-sms icon icon-message"
|
||||
data-l10n-id="send-sms-button" aria-label="SMS"></button>
|
||||
</div>
|
||||
<div class="item-body-exp">
|
||||
<button class="activity call-action icon icon-call"
|
||||
id="call-or-pick-#i#">
|
||||
<b>#value#</b>
|
||||
<span class="js-sim-indication"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</section>
|
||||
<section id="email-details">
|
||||
<li data-mail id='email-details-template-#i#' data-template>
|
||||
<h2 data-l10n-id="#type_l10n_id#">#type#</h2>
|
||||
<div class="item">
|
||||
<div class="item-body-exp">
|
||||
<button id="email-or-pick-#i#" class="activity icon icon-email">
|
||||
<b>#value#</b>
|
||||
</button>
|
||||
</div>
|
||||
<div class="item-media pull-right">
|
||||
<button id="send-sms-to-email-button-#i#"
|
||||
class="activity send-sms icon icon-message"
|
||||
data-l10n-id="send-sms-button" aria-label="SMS"></button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</section>
|
||||
<ul id="list-details"></ul>
|
||||
</section>`;
|
||||
8
gaia/apps/communications/contacts/test/unit/mock_contacts_details.js
Executable file
8
gaia/apps/communications/contacts/test/unit/mock_contacts_details.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
/* exported MockContactDetails */
|
||||
|
||||
var MockContactDetails = {
|
||||
'init': function init() {},
|
||||
'render': function render() {},
|
||||
'setContact': function setContact(c) {}
|
||||
};
|
||||
10
gaia/apps/communications/contacts/test/unit/mock_contacts_exporter.js
Executable file
10
gaia/apps/communications/contacts/test/unit/mock_contacts_exporter.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
/* exported MockContactsExporter */
|
||||
|
||||
var MockContactsExporter = function() {
|
||||
return {
|
||||
'init': function(ids, cb) {},
|
||||
'setExportStrategy': function(st) {},
|
||||
'start': function() {}
|
||||
};
|
||||
}();
|
||||
6
gaia/apps/communications/contacts/test/unit/mock_contacts_form.js
Executable file
6
gaia/apps/communications/contacts/test/unit/mock_contacts_form.js
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
/* exported MockContactsForm */
|
||||
|
||||
var MockContactsForm = {
|
||||
'init': function init() {}
|
||||
};
|
||||
549
gaia/apps/communications/contacts/test/unit/mock_contacts_index.html
Executable file
549
gaia/apps/communications/contacts/test/unit/mock_contacts_index.html
Executable file
|
|
@ -0,0 +1,549 @@
|
|||
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="en-US">
|
||||
<link rel="localization" href="locales/contacts.{locale}.properties">
|
||||
<link rel="localization" href="../dialer/locales/shared.{locale}.properties">
|
||||
<link rel="localization" href="/shared/locales/import_contacts/import_contacts.{locale}.properties">
|
||||
<!-- Contacts List Section -->
|
||||
<section id='view-contacts-list' role="region" data-state="active" class="view view-noscroll view-contacts-list">
|
||||
<gaia-header id="activity-header" action="close">
|
||||
<h1 id="app-title" data-l10n-id="contacts">Contacts</h1>
|
||||
<button id="add-contact-button" data-icon="add" data-l10n-id="addButton"></button>
|
||||
<button id="settings-button" data-icon="settings" data-l10n-id="settingsButton"></button>
|
||||
</gaia-header>
|
||||
|
||||
<article class="view-body">
|
||||
<div id="no-contacts" class="hide">
|
||||
<div class="info">
|
||||
<p data-l10n-id="no-contacts">no contacts</p>
|
||||
<p data-l10n-id="start-adding">start adding them now </p>
|
||||
<div class="icon create">
|
||||
<p class="small" data-l10n-id="create-new">Create a new contact</p>
|
||||
</div>
|
||||
<div class="icon import">
|
||||
<p class="small" data-l10n-id="import-now">Import your contacts from your SIM card or from Facebook</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav data-type="scrollbar">
|
||||
<p></p>
|
||||
<ol>
|
||||
<li data-anchor="search-container" data-img="magnifier_icon_big.png">
|
||||
<a href="#"><span class="pack-icon-search">Search</span></a>
|
||||
</li>
|
||||
<li data-anchor="group-favorites" data-img="star_icon_big.png">
|
||||
<a href="#"><span class="pack-icon-favorites">Favorites</span></a>
|
||||
</li>
|
||||
<li data-template data-anchor="group-#anchor#" data-letter="#anchor#">
|
||||
<a href="#">#anchor#</a>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div id="groups-container" class="view-body-inner">
|
||||
<form id="search-container" class="search" role="search">
|
||||
<p>
|
||||
<label for="search" id="search-start">
|
||||
<input type="search" name="search" class="textfield" placeholder="Search" data-l10n-id="search-contact">
|
||||
</label>
|
||||
</p>
|
||||
</form>
|
||||
<section id="groups-list" data-type="list">
|
||||
<!-- Group template here -->
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section id="search-view" class="view">
|
||||
<form id="searchview-container" class="search" role="search">
|
||||
<button id='cancel-search' data-l10n-id="cancel" type="submit">Cancel</button>
|
||||
<p>
|
||||
<label for="search-contact">
|
||||
<input type="search" name="search" class="textfield" placeholder="Search"
|
||||
id="search-contact" data-l10n-id="search-contact">
|
||||
<button type="reset">Clear</button>
|
||||
</label>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<section id="groups-list-search">
|
||||
<ol id="search-list" data-type="list">
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p id="no-result" class="hide" data-l10n-id="noResults">No contacts found</p>
|
||||
<p id="search-progress" class="hidden" role="status">
|
||||
<progress class="small"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</section> <!-- Search view -->
|
||||
|
||||
<section id='view-screenshot' role="region" class="view hide">
|
||||
<gaia-header id="activity-header" action="close">
|
||||
<h1 id="app-title" data-l10n-id="contacts">Contacts</h1>
|
||||
<button id="add-contact-button" data-icon="add" data-l10n-id="addButton"></button>
|
||||
<button id="settings-button" data-icon="settings" data-l10n-id="settingsButton"></button>
|
||||
</gaia-header>
|
||||
<article id="view-screenshot-body">
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<!-- Contact Details Section -->
|
||||
<section id='view-contact-details' role="region" class="view view-right view-contact-profile">
|
||||
<gaia-header id='details-view-header' action="back">
|
||||
<h1 id='contact-name-title'><bdi></bdi></h1>
|
||||
<button id="edit-contact-button" data-icon="edit-contact" data-l10n-id="editButton"></button>
|
||||
</gaia-header>
|
||||
|
||||
<article id="contact-detail-wrapper" class="view-body">
|
||||
<div id="cover-img"></div>
|
||||
<section id="contact-detail" class="view-body-inner">
|
||||
<!-- Phone Template -->
|
||||
<li data-phone id='phone-details-template-#i#' data-template>
|
||||
<h2 data-l10n-id="#type_l10n_id#">#type#</h2>
|
||||
<div class="item">
|
||||
<div class="item-media pull-right">
|
||||
<button id="send-sms-button-#i#" class="activity send-sms icon icon-message"></button>
|
||||
</div>
|
||||
<div class="item-body-exp">
|
||||
<button class="activity icon icon-call" id="call-or-pick-#i#">
|
||||
<b>
|
||||
#value#
|
||||
<em>#carrier#</em>
|
||||
</b>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li id="birthday-template-#i#" data-template>
|
||||
<h2 data-l10n-id="birthday">Birthday</h2>
|
||||
<p><strong>#bday#</strong></p>
|
||||
</li>
|
||||
|
||||
<!-- Email Template -->
|
||||
<li data-mail id='email-details-template-#i#' data-template>
|
||||
<h2 data-l10n-id="#type_l10n_id#">#type#</h2>
|
||||
<div class="item">
|
||||
<div class="item-body-exp">
|
||||
<button id="email-or-pick-#i#" class="activity icon icon-email">
|
||||
<b>#value#</b>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Social Template -->
|
||||
<li data-social class="social-actions" id="social-template-#i#" data-template>
|
||||
<h2 data-l10n-id="social-network" id="social-label">Social Network</h2>
|
||||
<div class="fillflow-twocols">
|
||||
<button id="msg_button" data-l10n-id="msg-send" class="activity icon icon-message">
|
||||
Message
|
||||
</button>
|
||||
<button id="wall_button" data-l10n-id="wall-post" class="activity icon icon-email">
|
||||
Wall Post
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button id="profile_button" data-l10n-id="show-fb-profile" class="fillflow-row activity icon icon-fb-profile">
|
||||
View Facebook profile
|
||||
</button>
|
||||
|
||||
<button id="link_button" class="activity icon icon-link">
|
||||
#action#
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<!-- Address Template -->
|
||||
<li data-address id='address-details-template-#i#' data-template>
|
||||
<h2 data-l10n-id="#type_l10n_id#">#type#</h2>
|
||||
<div class="item">
|
||||
<div class="item-body-exp">
|
||||
<a href="#" class="action action-block">
|
||||
<span role="button" class="icon-address bb-button" data-l10n-id="legendAddress">Address</span>
|
||||
<b>
|
||||
<span>#streetAddress#</span>
|
||||
#postalCode#
|
||||
#locality#
|
||||
#countryName#
|
||||
</b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Comment Template -->
|
||||
<p data-comment id='note-details-template-#i#' data-template class="comment-notes">#note#</p>
|
||||
<div id='contact-detail-inner'>
|
||||
<h1 id='org-title'></h1>
|
||||
<ul id='details-list'>
|
||||
<!-- Iterating mails, phones, addresses adn comments here -->
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<button id='toggle-favorite' class="fillflow-row icon icon-fav">
|
||||
Add as favorite
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Edit Section -->
|
||||
<section id='view-contact-form' role="region" class="view view-bottom view-edit-contact">
|
||||
<gaia-header id="contact-form-header" action="close">
|
||||
<h1 id='contact-form-title' data-l10n-id="addContact">Add contact</h1>
|
||||
<button id="save-button" data-l10n-id="done">Done</button>
|
||||
</gaia-header>
|
||||
|
||||
<!-- PHONE TEMPLATE -->
|
||||
<div id='add-phone-#i#' data-template class='phone-template' data-index="#i#">
|
||||
<fieldset class="fillflow-row">
|
||||
<legend class="action">
|
||||
<span data-taglist="phone-type" name="tel" data-value="#type_value#" id="tel_type_#i#" data-field="type" data-l10n-id=#type_l10n_id#>#type#</span>
|
||||
</legend>
|
||||
<section>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Phone" data-field="value" data-l10n-id="tel" name="tel[#i#][value]" class="textfield" type="tel" value="#value#" id="number_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Carrier" data-field="carrier" data-l10n-id="carrier" name="tel[#i#][carrier]" class="textfield" type="text" x-inputmode="latin-prose" value="#carrier#" id="carrier_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</section>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- EMAIL TEMPLATE -->
|
||||
<div id='add-email-#i#' data-template class='email-template' data-index="#i#">
|
||||
<fieldset class="fillflow-row">
|
||||
<legend class="action">
|
||||
<span data-taglist="email-type" name="email[#i#][type]" data-value="#type_value#" id="email_type_#i#" data-field="type" data-l10n-id="#type_l10n_id#">#type#</span>
|
||||
</legend>
|
||||
<section>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Email" data-l10n-id="email" name="email[#i#][value]" class="textfield" type="email" value="#value#" id="email_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</section>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- ADDRESS TEMPLATE -->
|
||||
<div id='add-address-#i#' data-template class='address-template' data-index="#i#">
|
||||
<fieldset class="fillflow-row">
|
||||
<legend class="action">
|
||||
<span data-taglist="address-type" name="adr[#i#][type]" data-value="#type_value#" id="address_type_#i#" data-field="type" data-l10n-id="#type_l10n_id#">#type#</span>
|
||||
</legend>
|
||||
<section>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Street" data-field="streetAddress" data-l10n-id="streetAddress" name="adr[#i#][streetAddress]" class="textfield" type="text" x-inputmode="latin-prose" value="#streetAddress#" id="streetAddress_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Zip Code" data-field="postalCode" data-l10n-id="postalCode" name="adr[#i#][postalCode]" class="textfield" type="text" value="#postalCode#" id="postalCode_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="City" data-field="locality" data-l10n-id="locality" name="adr[#i#][locality]" class="textfield" type="text" x-inputmode="latin-prose" value="#locality#" id="locality_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Country" data-field="countryName" data-l10n-id="countryName" name="adr[#i#][countryName]" class="textfield" type="text" x-inputmode="latin-prose" value="#countryName#" id="countryName_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</section>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- COMMENTS TEMPLATE -->
|
||||
<div id='add-note-#i#' data-template class='note-template' data-index="#i#">
|
||||
<dl class="setbox fillflow-row">
|
||||
<dd class="setbox-body">
|
||||
<p class="setbox-item">
|
||||
<input placeholder="Comment" data-l10n-id="comment" name="comment[#i#]" class="textfield" type="text" x-inputmode="latin-prose" value="#note#" id="note_#i#">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
||||
<article class="view-body">
|
||||
<div class="view-body-inner">
|
||||
<form id="contact-form" action="#" class="fill-flow">
|
||||
<input name="id" id="contact-form-id" type="hidden" value="">
|
||||
<section class="item first">
|
||||
<a id="thumbnail-action" href="#" class="item-media fillflow-media">
|
||||
<p>
|
||||
<span role="button" class="icon-addimage bb-button"></span>
|
||||
<em data-l10n-id="addPhoto"> Add photo</em>
|
||||
</p>
|
||||
<p class="edit-photo">
|
||||
<em data-l10n-id="edit">Edit</em>
|
||||
</p>
|
||||
<img id="thumbnail-photo" alt="">
|
||||
</a>
|
||||
<div class="item-body-exp">
|
||||
<p class="fillflow-row">
|
||||
<input placeholder="Name" data-l10n-id="givenName" name="givenName" class="textfield" type="text" x-inputmode="latin-prose" value="" id="givenName">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
<p class="fillflow-row">
|
||||
<input placeholder="Last name" data-l10n-id="familyName" name="familyName" class="textfield" type="text" x-inputmode="latin-prose" value="" id="familyName">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</div>
|
||||
<p class="fillflow-row">
|
||||
<input placeholder="Company Name" data-l10n-id="org" name="org" class="textfield" type="text" x-inputmode="latin-prose" value="" id="org">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<section>
|
||||
<div id="contacts-form-phones">
|
||||
<!-- Iterating over phone template here -->
|
||||
</div>
|
||||
</section>
|
||||
<button data-field-type="tel" id='add-new-phone' data-l10n-id="addPhone" class="fillflow-row action action-add icon icon-add">
|
||||
Add phone number
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<section>
|
||||
<div id="contacts-form-emails">
|
||||
<!-- Iterating over email template here -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button data-field-type="email" id='add-new-email' data-l10n-id="addEmail" class="fillflow-row action action-add icon icon-add">
|
||||
Add email address
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<section>
|
||||
<div id="contacts-form-addresses">
|
||||
<!-- Iterating over address template here -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button data-field-type="adr" id='add-new-address' data-l10n-id="addAddress" class="fillflow-row action action-add icon icon-add">
|
||||
Add new address
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<section>
|
||||
<div id="contacts-form-notes">
|
||||
<!-- Iterating over comment template here -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button data-field-type="note" id='add-new-note' data-l10n-id="addComment" class="fillflow-row action action-add icon icon-add">
|
||||
Add comment
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
|
||||
<footer class="tail-actions hide">
|
||||
<button id='delete-contact' class="fillflow-row action action-delete danger">
|
||||
<b data-l10n-id="deleteContact">Delete contact</b>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<!-- Tag selection -->
|
||||
<section id="view-select-tag" role="region" class="view view-right view-select-tag">
|
||||
<gaia-header id="settings-header" action="back">
|
||||
<h1 data-l10n-id="label">Label</h1>
|
||||
<button id="settings-done" data-l10n-id="done">Done</button>
|
||||
</gaia-header>
|
||||
|
||||
<article class="view-body">
|
||||
<form class="view-body-inner">
|
||||
<ul id="tags-list" class="selection-list compact">
|
||||
</ul>
|
||||
<p>
|
||||
<input class="textfield" type="text" placeholder="Custom Tag" value="" id='custom-tag' data-l10n-id="customTag">
|
||||
<button type="reset">Clear</button>
|
||||
</p>
|
||||
</form>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section data-theme="organic" id="view-settings" role="region" class="skin-organic view view-bottom theme-settings">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="settings">Settings</h1>
|
||||
<button id="settings-close" data-l10n-id="done">Done</button>
|
||||
</gaia-header>
|
||||
|
||||
<article class="view-body" id="settings-article">
|
||||
<section role="region" class="view-body-inner">
|
||||
<ul data-type="list">
|
||||
<li id="settingsOrder">
|
||||
<gaia-switch name="order.lastname">
|
||||
<label data-l10n-id="contactsOrderBy"></label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
</ul>
|
||||
<header>
|
||||
<h2 data-l10n-id="transferContactsTitle">Transfer Contacts</h2>
|
||||
</header>
|
||||
<ul data-type="list" id="sources">
|
||||
<li id="importContacts" data-source="sim">
|
||||
<button class="icon icon-import" data-l10n-id="importContactsButton">
|
||||
Import Contacts
|
||||
</button>
|
||||
</li>
|
||||
<li id="exportContacts" data-source="sd">
|
||||
<button class="icon icon-export" data-l10n-id="exportContactsButton">
|
||||
Export Contacts
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<header>
|
||||
<h2 data-l10n-id="ContactManagementTitle">Contacts Management</h2>
|
||||
</header>
|
||||
<ul data-type="list" id="contactsManagement">
|
||||
<li>
|
||||
<button id="set-ice" class="action action-delete" data-l10n-id="setICEButton">
|
||||
Set ICE Contacts
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button id="bulkDelete" class=" fillflow-row action action-delete danger bulkdelete">
|
||||
<b data-l10n-id="bulkDeleteButton">Bulk delete</b>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
<section data-theme="organic" id="import-settings" role="region" class="skin-organic view view-right theme-settings">
|
||||
<gaia-header id="import-settings-header" action="back">
|
||||
<h1 id='import-settings-title'></h1>
|
||||
</gaia-header>
|
||||
<article class="view-body">
|
||||
<section role="region" class="view-body-inner">
|
||||
<ul data-type="list" id="import-options">
|
||||
<li id="import-sim-option" data-source="sim">
|
||||
<button class="icon icon-sim">
|
||||
<span data-l10n-id="importSim2">SIM card</span>
|
||||
<p><span></span><time></time></p>
|
||||
</button>
|
||||
<p class="error-message" data-l10n-id="noSimMsg"></p>
|
||||
</li>
|
||||
<li id="import-sd-option" data-source="sd">
|
||||
<button class="icon icon-sd">
|
||||
<span data-l10n-id="importMemoryCard">Memory card</span>
|
||||
<p><span></span><time></time></p>
|
||||
</button>
|
||||
<p class="error-message" data-l10n-id="noMemoryCardMsg"></p>
|
||||
</li>
|
||||
<li id="import-gmail-option" class="importService" data-source="gmail">
|
||||
<button class="icon icon-gmail">
|
||||
<span data-l10n-id="importGmail">Gmail</span>
|
||||
<p><span></span><time></time></p>
|
||||
</button>
|
||||
</li>
|
||||
<li id="import-live-option" class="importService" data-source="live">
|
||||
<button class="icon icon-live">
|
||||
<span data-l10n-id="importOutlook">Outlook</span>
|
||||
<p><span></span><time></time></p>
|
||||
</button>
|
||||
<p class="error-message" data-l10n-id="genericNoConnection"></p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul data-type="list" id="export-options">
|
||||
<li id="export-sim-option" data-source="sim">
|
||||
<button class="icon icon-sim" data-l10n-id="simCard">
|
||||
SIM card
|
||||
</button>
|
||||
<p class="error-message" data-l10n-id="noSimMsgExport"></p>
|
||||
</li>
|
||||
<li id="export-sd-option" data-source="sd">
|
||||
<button class="icon icon-sd" data-l10n-id="memoryCard">
|
||||
Memory card
|
||||
</button>
|
||||
<p class="error-message" data-l10n-id="noMemoryCardMsgExport"></p>
|
||||
</li>
|
||||
<li id="export-bluetooth-option" data-source="bluetooth">
|
||||
<button class="icon icon-bluetooth" data-l10n-id="bluetooth">
|
||||
Bluetooth
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
<section data-theme="organic" id="ice-settings" role="region" class="skin-organic view view-right theme-settings">
|
||||
<gaia-header id="ice-settings-header" action="back">
|
||||
<h1 id='ice-settings-title' data-l10n-id="ICESettingTitle">ICE Contacts</h1>
|
||||
</gaia-header>
|
||||
<article class="view-body">
|
||||
<section role="region" class="view-body-inner">
|
||||
<p class="description" data-l10n-id="ICEDescription">
|
||||
Add two contacts for making “In Case of Emergency” calls.
|
||||
</p>
|
||||
<ul data-type="list">
|
||||
<li id="ice-contacts-1-switch">
|
||||
<gaia-switch name="ice-contact-1-enabled">
|
||||
<label data-l10n-id="ICEContact1"></label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li>
|
||||
<button id="select-ice-contact-1" class="icon icon-view" data-l10n-id="ICESelectContact" disabled>
|
||||
Select a contact
|
||||
</button>
|
||||
</li>
|
||||
<li id="ice-contacts-2-switch">
|
||||
<gaia-switch name="ice-contact-2-enabled">
|
||||
<label data-l10n-id="ICEContact2"></label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li>
|
||||
<button id="select-ice-contact-2" class="icon icon-view" data-l10n-id="ICESelectContact" disabled>
|
||||
Select a contact
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
<form data-type="confirm" id="loading-overlay" class="hide no-opacity" role="dialog">
|
||||
<section id="progress-activity" class="hide">
|
||||
<h1 id="progress-title"></h1>
|
||||
<p role="status">
|
||||
<span id="progress-msg"></span>
|
||||
<progress id="progress-element" class="pack-activity" value="0" max="100"></progress>
|
||||
</p>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
<section id="statusMsg" role="status">
|
||||
<p></p>
|
||||
</section>
|
||||
|
||||
<form id="confirmation-message" class="hide" role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<h1>Confirmation title</h1>
|
||||
<p>Confirmation message</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Action 1</button>
|
||||
<button>Action 2</button>
|
||||
</menu>
|
||||
</form>
|
||||
10
gaia/apps/communications/contacts/test/unit/mock_contacts_index.html.js
Executable file
10
gaia/apps/communications/contacts/test/unit/mock_contacts_index.html.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
/* exported MockContactsIndexHtml */
|
||||
|
||||
var MockContactsIndexHtml = (function MockLinkHtml() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/mock_contacts_index.html', false);
|
||||
req.send(null);
|
||||
|
||||
return req.responseText;
|
||||
})();
|
||||
124
gaia/apps/communications/contacts/test/unit/mock_contacts_list.js
Executable file
124
gaia/apps/communications/contacts/test/unit/mock_contacts_list.js
Executable file
|
|
@ -0,0 +1,124 @@
|
|||
'use strict';
|
||||
/* exported MockContactsList */
|
||||
|
||||
function MockContactsList() {
|
||||
return [
|
||||
{
|
||||
'id': '1',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Germany',
|
||||
'locality': 'Chemnitz',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'Gotthardstrasse 22'
|
||||
}
|
||||
],
|
||||
'bday': '1978-12-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test@test.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['AD'],
|
||||
'givenName': ['Pepito'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Pepito A'
|
||||
],
|
||||
'org': ['Test'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+346578888881',
|
||||
'type': 'mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'category': [],
|
||||
'note': [
|
||||
'Note 1'
|
||||
],
|
||||
'photo': ['test.png']
|
||||
},
|
||||
{
|
||||
'id': '2',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Germany',
|
||||
'locality': 'Chemnitz',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'Gotthardstrasse 22'
|
||||
}
|
||||
],
|
||||
'bday': '1978-12-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test@test.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['BA'],
|
||||
'givenName': ['Pepito'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Pepito BA'
|
||||
],
|
||||
'org': ['Test'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+346578888882',
|
||||
'type': 'mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'category': [],
|
||||
'note': [
|
||||
'Note 1'
|
||||
],
|
||||
'photo': ['test.png']
|
||||
},
|
||||
{
|
||||
'id': '3',
|
||||
'updated': new Date(),
|
||||
'additionalName': [''],
|
||||
'adr': [
|
||||
{
|
||||
'countryName': 'Germany',
|
||||
'locality': 'Chemnitz',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'Gotthardstrasse 22'
|
||||
}
|
||||
],
|
||||
'bday': '1978-12-20',
|
||||
'email': [
|
||||
{
|
||||
'type': 'Personal',
|
||||
'value': 'test@test.com'
|
||||
}
|
||||
],
|
||||
'familyName': ['CC'],
|
||||
'givenName': ['Antonio'],
|
||||
'jobTitle': [''],
|
||||
'name': [
|
||||
'Antonio CC'
|
||||
],
|
||||
'org': ['Test'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+346578888883',
|
||||
'type': 'mobile',
|
||||
'carrier': 'TEF'
|
||||
}
|
||||
],
|
||||
'category': [],
|
||||
'note': [
|
||||
'Note 1'
|
||||
],
|
||||
'photo': ['test.png']
|
||||
}
|
||||
];
|
||||
}
|
||||
19
gaia/apps/communications/contacts/test/unit/mock_contacts_list_obj.js
Executable file
19
gaia/apps/communications/contacts/test/unit/mock_contacts_list_obj.js
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
/* exported MockContactsListObj */
|
||||
|
||||
var MockContactsListObj = {
|
||||
init: function() {},
|
||||
load: function() {},
|
||||
refresh: function() {},
|
||||
refreshFb: function() {},
|
||||
getContactById: function() {},
|
||||
getAllContacts: function() {},
|
||||
handleClick: function() {},
|
||||
remove: function() {},
|
||||
loaded: true,
|
||||
clearClickHandlers: function() {},
|
||||
setOrderByLastName: function() {},
|
||||
initAlphaScroll: function() {},
|
||||
isSelecting: false,
|
||||
toggleICEGroup: function() {}
|
||||
};
|
||||
8
gaia/apps/communications/contacts/test/unit/mock_contacts_match.js
Executable file
8
gaia/apps/communications/contacts/test/unit/mock_contacts_match.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
/* exported MockMatcher */
|
||||
|
||||
var MockMatcher = {
|
||||
match: function(contact, mode, cbs) {
|
||||
cbs.onmismatch();
|
||||
}
|
||||
};
|
||||
7
gaia/apps/communications/contacts/test/unit/mock_contacts_nfc.js
Executable file
7
gaia/apps/communications/contacts/test/unit/mock_contacts_nfc.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
/* exported MockContactsNfc */
|
||||
|
||||
var MockContactsNfc = {
|
||||
startListening: function() {},
|
||||
stopListening: function() {}
|
||||
};
|
||||
15
gaia/apps/communications/contacts/test/unit/mock_contacts_search.js
Executable file
15
gaia/apps/communications/contacts/test/unit/mock_contacts_search.js
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
/* exported MockContactsSearch */
|
||||
|
||||
var MockContactsSearch = {
|
||||
'init': function(s, d, n) {},
|
||||
'invalidateCache': function() {},
|
||||
'appendNodes': function(nodes) {},
|
||||
'removeContact': function(id) {},
|
||||
'search': function(cb) { cb(); },
|
||||
'enterSearchMode': function(evt) {},
|
||||
'exitSearchMode': function(evt) {},
|
||||
'isInSearchMode': function() { return false; },
|
||||
'enableSearch': function() {},
|
||||
'selectRow': function(id, value) {}
|
||||
};
|
||||
22
gaia/apps/communications/contacts/test/unit/mock_contacts_service.js
Executable file
22
gaia/apps/communications/contacts/test/unit/mock_contacts_service.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockContactsService */
|
||||
|
||||
var MockContactsService = {
|
||||
addListener: function(event, handler) {
|
||||
},
|
||||
removeListener: function(event, handler) {
|
||||
},
|
||||
isEmpty: function(callback) {
|
||||
},
|
||||
save: function(contact, callback) {
|
||||
},
|
||||
remove: function(contact, callback) {
|
||||
},
|
||||
get: function (contactID, successCb, errorCb) {
|
||||
},
|
||||
getAll: function(callback) {
|
||||
},
|
||||
getAllStreamed: function(sortBy, onContactCB, onErrorCB, onCompleteCB) {
|
||||
}
|
||||
};
|
||||
13
gaia/apps/communications/contacts/test/unit/mock_contacts_settings.js
Executable file
13
gaia/apps/communications/contacts/test/unit/mock_contacts_settings.js
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
'use strict';
|
||||
/* exported MockContactsSettings */
|
||||
|
||||
var MockContactsSettings = {
|
||||
init: function() {},
|
||||
close: function() {},
|
||||
refresh: function() {},
|
||||
cardStateChanged: function() {},
|
||||
updateTimestamps: function() {},
|
||||
navigation: {
|
||||
go: function() {}
|
||||
}
|
||||
};
|
||||
17
gaia/apps/communications/contacts/test/unit/mock_contacts_shortcuts.js
Executable file
17
gaia/apps/communications/contacts/test/unit/mock_contacts_shortcuts.js
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
/* exported MockAlphaScroll */
|
||||
|
||||
var MockAlphaScroll = {
|
||||
init: function(params) {
|
||||
return;
|
||||
},
|
||||
toggleFormat: function() {
|
||||
return;
|
||||
},
|
||||
showGroup: function(name) {
|
||||
|
||||
},
|
||||
hideGroup: function(name) {
|
||||
|
||||
}
|
||||
};
|
||||
11
gaia/apps/communications/contacts/test/unit/mock_contacts_tag.js
Executable file
11
gaia/apps/communications/contacts/test/unit/mock_contacts_tag.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
/* exported MockContactsTag */
|
||||
|
||||
var MockContactsTag = {
|
||||
filterTags: function (type, currentNode, tags) {
|
||||
return tags;
|
||||
},
|
||||
setCustomTag: function (element) {},
|
||||
setCustomTagVisibility: function (value) {},
|
||||
fillTagOptions: function (target, _originalTag, options) {}
|
||||
};
|
||||
12
gaia/apps/communications/contacts/test/unit/mock_cookie.js
Executable file
12
gaia/apps/communications/contacts/test/unit/mock_cookie.js
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
/* exported MockCookie */
|
||||
|
||||
var MockCookie = {
|
||||
data: {},
|
||||
load: function() {
|
||||
return this.data;
|
||||
},
|
||||
update: function(obj) {
|
||||
this.data = obj;
|
||||
}
|
||||
};
|
||||
7
gaia/apps/communications/contacts/test/unit/mock_datastore_migrator.js
Executable file
7
gaia/apps/communications/contacts/test/unit/mock_datastore_migrator.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockDatastoreMigration */
|
||||
|
||||
var MockDatastoreMigration = function() {
|
||||
this.start = function() {};
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue