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
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() {};
|
||||
};
|
||||
107
gaia/apps/communications/contacts/test/unit/mock_details_dom.js.html
Executable file
107
gaia/apps/communications/contacts/test/unit/mock_details_dom.js.html
Executable file
|
|
@ -0,0 +1,107 @@
|
|||
'use strict';
|
||||
|
||||
var MockDetailsDom = '<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>#type# <span class="carrier">#carrier#</span></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#' +
|
||||
'</b>' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</li>' +
|
||||
|
||||
'<!-- Dates template -->' +
|
||||
'<li id="dates-template-#i#" data-template>' +
|
||||
'<h2>#type#</h2>' +
|
||||
'<p><strong>#date#</strong></p>' +
|
||||
'</li>' +
|
||||
|
||||
'<!-- Email Template -->' +
|
||||
'<li data-mail id="email-details-template-#i#" data-template>' +
|
||||
'<h2>#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>' +
|
||||
'<button id="share_button" class="activity icon icon-share">' +
|
||||
'Share' +
|
||||
'</button>' +
|
||||
'</li>' +
|
||||
'<li class="duplicate-actions" id="duplicate-contacts-template" data-template>' +
|
||||
'<h2 data-l10n-id="duplicate-contacts">Organise Contacts</h2>' +
|
||||
'<button id="find-merge-button" data-l10n-id="find-merge-contacts" class="activity no-icon">' +
|
||||
'Find duplicate contacts' +
|
||||
'</button>' +
|
||||
'</li>' +
|
||||
'<!-- Address Template -->' +
|
||||
'<li data-address id="address-details-template-#i#" data-template>' +
|
||||
'<h2>#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>' +
|
||||
'<gaia-sim-picker id="sim-picker" tabindex="-1"></gaia-sim-picker>';
|
||||
39
gaia/apps/communications/contacts/test/unit/mock_event_listeners.js
Executable file
39
gaia/apps/communications/contacts/test/unit/mock_event_listeners.js
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockUtils */
|
||||
/*jshint -W083 */
|
||||
|
||||
var MockUtils = {
|
||||
listeners: {
|
||||
dom: null,
|
||||
add: function(config) {
|
||||
try {
|
||||
var doc = this.dom || document;
|
||||
for (var id in config) {
|
||||
var handler = config[id];
|
||||
var nodes = doc.querySelectorAll(id);
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
if (Array.isArray(handler)) {
|
||||
handler.forEach(function handle(item) {
|
||||
if (!item.hasOwnProperty('event') &&
|
||||
!item.hasOwnProperty('handler')) {
|
||||
return;
|
||||
}
|
||||
node.addEventListener(item.event, item.handler);
|
||||
});
|
||||
} else {
|
||||
node.addEventListener('click', handler);
|
||||
}
|
||||
} // nodes
|
||||
} // Handlers
|
||||
}
|
||||
catch (e) {
|
||||
window.console.error('Error while registering listener for: ', id, e);
|
||||
}
|
||||
} // Add function
|
||||
},
|
||||
cookie: {
|
||||
|
||||
}
|
||||
};
|
||||
21
gaia/apps/communications/contacts/test/unit/mock_export_strategy.js
Executable file
21
gaia/apps/communications/contacts/test/unit/mock_export_strategy.js
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
/* exported MockExportStrategy */
|
||||
|
||||
var MockExportStrategy = function() {
|
||||
return {
|
||||
'setContactsToExport': function(c) { this.contacts = c; },
|
||||
'shouldShowProgress': function() { return true; },
|
||||
'determinativeValue': true,
|
||||
'hasDeterminativeProgress': function() { return this.determinativeValue; },
|
||||
'getExportTitle': function() { return 'export'; },
|
||||
'doExport': function(callback) {
|
||||
callback(this.error, this.contacts, this.isRecoverable);
|
||||
},
|
||||
'setProgressStep': function(e) {},
|
||||
'setError': function(error, isRecoverable) {
|
||||
this.error = error;
|
||||
this.isRecoverable = isRecoverable || false;
|
||||
},
|
||||
get name() { return 'MOCK'; }
|
||||
};
|
||||
}();
|
||||
7
gaia/apps/communications/contacts/test/unit/mock_external_services.js
Executable file
7
gaia/apps/communications/contacts/test/unit/mock_external_services.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
/* exported MockExtServices */
|
||||
'use strict';
|
||||
|
||||
var MockExtServices = {
|
||||
importGmail: function() {},
|
||||
importLive: function() {}
|
||||
};
|
||||
7
gaia/apps/communications/contacts/test/unit/mock_extfb.js
Executable file
7
gaia/apps/communications/contacts/test/unit/mock_extfb.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
/* exported MockExtFb */
|
||||
|
||||
var MockExtFb = {
|
||||
importFB: function() {},
|
||||
initEventHandlers: function(node, contact, linked) {}
|
||||
};
|
||||
410
gaia/apps/communications/contacts/test/unit/mock_fb.js
Executable file
410
gaia/apps/communications/contacts/test/unit/mock_fb.js
Executable file
|
|
@ -0,0 +1,410 @@
|
|||
'use strict';
|
||||
/* global fb */
|
||||
/* global MockAllFacebookContacts */
|
||||
/* global MockContactAllFields */
|
||||
/* global MockLinkedContacts */
|
||||
/* global MockImportStatusData */
|
||||
/* global utils */
|
||||
|
||||
var FB_ID = 220439;
|
||||
|
||||
var Mockfb = {
|
||||
fbContact: false,
|
||||
fbLinked: false,
|
||||
isEnabled: true,
|
||||
|
||||
CATEGORY: 'facebook',
|
||||
NOT_LINKED: 'not_linked',
|
||||
LINKED: 'fb_linked',
|
||||
|
||||
// Default, can be changed by specific tests
|
||||
operationsTimeout: 20000,
|
||||
|
||||
// mocks the saved data
|
||||
savedData: [],
|
||||
utils: {
|
||||
getImportChecked: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
Mockfb.init = function(callback) {
|
||||
callback();
|
||||
};
|
||||
|
||||
Mockfb.setEmptyContacts = function() {
|
||||
this.contacts = [];
|
||||
};
|
||||
|
||||
Mockfb.setIsFbContact = function(isFB) {
|
||||
this.fbContact = isFB;
|
||||
};
|
||||
|
||||
Mockfb.setIsFbLinked = function(isLinked) {
|
||||
this.fbLinked = isLinked;
|
||||
};
|
||||
|
||||
// This function redirects to the implementation
|
||||
// inside the Mockfb.Contact. Purpose is to allow
|
||||
// reuse of this mock by the contacts_test.js
|
||||
// and to allow the existing tests to work.
|
||||
Mockfb.getData = function(con) {
|
||||
var fbContact = new Mockfb.Contact(con);
|
||||
return fbContact.getData();
|
||||
};
|
||||
|
||||
Mockfb.getContactByNumber = function(number, onsuccess, onerror) {
|
||||
if(this.contacts.length === 0) {
|
||||
return onsuccess(null);
|
||||
} else {
|
||||
return onsuccess(this.contacts);
|
||||
}
|
||||
};
|
||||
|
||||
Mockfb.setIsEnabled = function(isEnabled) {
|
||||
this.isEnabled = isEnabled;
|
||||
};
|
||||
|
||||
Mockfb.contacts = function() {
|
||||
var getAll = function getAll() {
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
// Fetch FB data, that is returning a contact info
|
||||
this.result = {};
|
||||
this.result[FB_ID] = new MockContactAllFields();
|
||||
this.result[FB_ID].id = '567';
|
||||
this.result[FB_ID].familyName = ['Taylor'];
|
||||
this.result[FB_ID].givenName = ['Bret'];
|
||||
this.result[FB_ID].name = [this.result[FB_ID].givenName + ' ' +
|
||||
this.result[FB_ID].familyName];
|
||||
this.result[FB_ID].org[0] = 'FB';
|
||||
this.result[FB_ID].adr = Mockfb.getAddresses();
|
||||
|
||||
callback.call(this);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
'getAll': getAll
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
Mockfb.Contact = function(devContact, mozCid) {
|
||||
var deviceContact = devContact;
|
||||
var contactData;
|
||||
|
||||
if (devContact) {
|
||||
setFacebookUid(FB_ID);
|
||||
}
|
||||
|
||||
function markAsFb(deviceContact) {
|
||||
if (!deviceContact.category) {
|
||||
deviceContact.category = [];
|
||||
}
|
||||
|
||||
if (deviceContact.category.indexOf(Mockfb.CATEGORY) === -1) {
|
||||
deviceContact.category.push(Mockfb.CATEGORY);
|
||||
deviceContact.category.push(Mockfb.NOT_LINKED);
|
||||
}
|
||||
|
||||
return deviceContact;
|
||||
}
|
||||
|
||||
function doGetFacebookUid(data) {
|
||||
var out = data.uid;
|
||||
if (!out) {
|
||||
if (Mockfb.isFbLinked(data)) {
|
||||
out = getLinkedTo(data);
|
||||
} else if (data.category) {
|
||||
var idx = data.category.indexOf(fb.CATEGORY);
|
||||
if (idx !== -1) {
|
||||
out = data.category[idx + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getLinkedTo(c) {
|
||||
var out;
|
||||
|
||||
if (c.category) {
|
||||
var idx = c.category.indexOf(fb.LINKED);
|
||||
if (idx !== -1) {
|
||||
out = c.category[idx + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function doSetFacebookUid(deviceContact, value) {
|
||||
if (!deviceContact.category) {
|
||||
deviceContact.category = [];
|
||||
}
|
||||
|
||||
if (deviceContact.category.indexOf(fb.CATEGORY) === -1) {
|
||||
markAsFb(deviceContact);
|
||||
}
|
||||
|
||||
var idx = deviceContact.category.indexOf(fb.CATEGORY);
|
||||
|
||||
deviceContact.category[idx + 2] = value;
|
||||
}
|
||||
|
||||
function getFacebookUid() {
|
||||
return doGetFacebookUid(deviceContact);
|
||||
}
|
||||
|
||||
function setFacebookUid(value) {
|
||||
doSetFacebookUid(deviceContact, value);
|
||||
}
|
||||
|
||||
this.getData = function getData() {
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
// Fetch FB data, that is returning a contact info
|
||||
this.result = new MockContactAllFields();
|
||||
deviceContact = this.result;
|
||||
setFacebookUid(FB_ID);
|
||||
this.result.id = '567';
|
||||
this.result.familyName = ['Taylor'];
|
||||
this.result.givenName = ['Bret'];
|
||||
this.result.name = [this.result.givenName + ' ' +
|
||||
this.result.familyName];
|
||||
this.result.org[0] = 'FB';
|
||||
this.result.adr = Mockfb.getAddresses();
|
||||
|
||||
callback.call(this);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.setData = function(data) {
|
||||
contactData = data;
|
||||
};
|
||||
|
||||
this.save = function() {
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
Mockfb.savedData.push(contactData);
|
||||
callback.call(this);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.merge = function(deviceContact) {
|
||||
deviceContact.id = '567';
|
||||
deviceContact.familyName = ['Taylor'];
|
||||
deviceContact.givenName = ['Bret'];
|
||||
deviceContact.name = [deviceContact.givenName + ' ' +
|
||||
deviceContact.familyName];
|
||||
deviceContact.org[0] = 'FB';
|
||||
deviceContact.adr = Mockfb.getAddresses();
|
||||
|
||||
return deviceContact;
|
||||
};
|
||||
|
||||
this.getDataAndValues = function getDataAndValues() {
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
// Fetch FB data, that is returning a contact info
|
||||
this.result = [];
|
||||
this.result[0] = new MockContactAllFields();
|
||||
this.result[0].adr = Mockfb.getAddresses();
|
||||
var date = new Date(0).toString();
|
||||
this.result[1] = {
|
||||
'+346578888888': true,
|
||||
'test@test.com': true,
|
||||
'Palencia': true,
|
||||
'Castilla y León': true,
|
||||
'España': true,
|
||||
'Test ORG': true
|
||||
};
|
||||
this.result[1][date] = true;
|
||||
|
||||
callback.call(this);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.promoteToLinked = function promoteToLinked() {
|
||||
Mockfb.promoteToLinked();
|
||||
};
|
||||
|
||||
Object.defineProperty(this, 'uid', {
|
||||
get: getFacebookUid,
|
||||
set: setFacebookUid,
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Mockfb.isFbContact = function(contact) {
|
||||
return this.fbContact;
|
||||
};
|
||||
|
||||
Mockfb.promoteToLinked = function() {
|
||||
this.fbLinked = true;
|
||||
};
|
||||
|
||||
Mockfb.setPropagatedFlag = function(field, contact) {
|
||||
// Do nothing...
|
||||
};
|
||||
|
||||
Mockfb.removePropagatedFlag = function(field, contact) {
|
||||
// Do nothing...
|
||||
};
|
||||
|
||||
Mockfb.isFbLinked = function(contact) {
|
||||
return this.fbLinked;
|
||||
};
|
||||
|
||||
Mockfb.getWorksAt = function(fbData) {
|
||||
return 'Telefónica';
|
||||
};
|
||||
|
||||
Mockfb.getAddresses = function(fbData) {
|
||||
var out = [];
|
||||
|
||||
out.push({
|
||||
'type': ['home'],
|
||||
'locality': 'Palencia',
|
||||
'region': 'Castilla y León',
|
||||
'countryName': 'España'
|
||||
});
|
||||
out.push({
|
||||
'type': ['current'],
|
||||
'locality': 'Greater London',
|
||||
'region': 'London',
|
||||
'countryName': 'United Kingdom'
|
||||
});
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
Mockfb.utils = (function() {
|
||||
var value;
|
||||
|
||||
return {
|
||||
getContactData: function() {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
},
|
||||
get result() {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
set result(r) {
|
||||
value = r;
|
||||
},
|
||||
|
||||
runQuery: function(query, cbs) {
|
||||
var ALL_QUERY = ['SELECT uid, name, last_name, first_name,',
|
||||
' middle_name, email from user ',
|
||||
' WHERE uid IN (SELECT uid1 FROM friend WHERE uid2=me()) ',
|
||||
' ORDER BY name'
|
||||
];
|
||||
|
||||
if (query === ALL_QUERY.join('')) {
|
||||
cbs.success(MockAllFacebookContacts);
|
||||
}
|
||||
else {
|
||||
cbs.success(MockLinkedContacts);
|
||||
}
|
||||
},
|
||||
|
||||
getImportChecked: function(cb) {
|
||||
MockImportStatusData.get('tokenData').then(function(data){
|
||||
if (data && data.access_token) {
|
||||
cb('logged-in');
|
||||
} else {
|
||||
cb('logged-out');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
TOKEN_DATA_KEY: 'tokenData',
|
||||
|
||||
SCHEDULE_SYNC_KEY: 'facebookShouldHaveScheduledAt',
|
||||
|
||||
setLastUpdate: function(date, callback) {
|
||||
typeof callback === 'function' && callback();
|
||||
},
|
||||
setCachedNumFriends: function() {
|
||||
|
||||
},
|
||||
|
||||
_fbData: [],
|
||||
|
||||
getNumFbContacts: function() {
|
||||
return {
|
||||
result: 25,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
numFbFriendsData: function(cbl) {
|
||||
var localCb = cbl.local;
|
||||
var remoteCb = cbl.remote;
|
||||
|
||||
if (typeof localCb == 'function'){
|
||||
localCb(50);
|
||||
}
|
||||
if (typeof remoteCb == 'function'){
|
||||
remoteCb(50);
|
||||
}
|
||||
},
|
||||
|
||||
getAllFbContacts: function() {
|
||||
return {
|
||||
result: Mockfb.utils._fbData,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
Mockfb.contacts = {
|
||||
_importedContacts: 40,
|
||||
getLength: function() {
|
||||
return {
|
||||
result: this._importedContacts,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Mockfb.sync = {
|
||||
scheduleNextSync: function() {}
|
||||
};
|
||||
|
||||
Mockfb.markFbCleaningInProgress = function(value) {
|
||||
utils.cookie.update({
|
||||
fbCleaningInProgress: value
|
||||
});
|
||||
};
|
||||
|
||||
46
gaia/apps/communications/contacts/test/unit/mock_fb_data.js
Executable file
46
gaia/apps/communications/contacts/test/unit/mock_fb_data.js
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
'use strict';
|
||||
|
||||
var MockFbContactsWriterObj = function() {
|
||||
this.storedData = Object.create(null);
|
||||
this.savedError = [];
|
||||
};
|
||||
|
||||
|
||||
MockFbContactsWriterObj.prototype = {
|
||||
_getRequest: function() {
|
||||
return {
|
||||
result: {},
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_getErrorRequest: function(errorName) {
|
||||
return {
|
||||
error: {
|
||||
name: errorName
|
||||
},
|
||||
set onerror(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
save: function(obj) {
|
||||
if (this.storedData[obj.uid]) {
|
||||
return this._getErrorRequest('AlreadyExists');
|
||||
}
|
||||
|
||||
if (this.savedError.indexOf(obj.uid) !== -1) {
|
||||
return this._getErrorRequest('DB Error');
|
||||
}
|
||||
|
||||
this.storedData[obj.uid] = obj;
|
||||
return this._getRequest();
|
||||
},
|
||||
|
||||
getLength: function() {
|
||||
return Object.keys(this.storedData).length;
|
||||
}
|
||||
};
|
||||
11
gaia/apps/communications/contacts/test/unit/mock_fb_loader.js
Executable file
11
gaia/apps/communications/contacts/test/unit/mock_fb_loader.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
/* exported MockFbLoader */
|
||||
|
||||
var MockFbLoader = function() {
|
||||
return {
|
||||
loaded: true,
|
||||
load: function(callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
}();
|
||||
10
gaia/apps/communications/contacts/test/unit/mock_file_reader.js
Executable file
10
gaia/apps/communications/contacts/test/unit/mock_file_reader.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
function MockFileReader() {}
|
||||
|
||||
MockFileReader.prototype.readAsText = function readAsText(file) {
|
||||
if (this.onloadend) {
|
||||
this.result = file;
|
||||
this.onloadend();
|
||||
}
|
||||
};
|
||||
108
gaia/apps/communications/contacts/test/unit/mock_find_matcher.js
Executable file
108
gaia/apps/communications/contacts/test/unit/mock_find_matcher.js
Executable file
|
|
@ -0,0 +1,108 @@
|
|||
'use strict';
|
||||
/* global SimplePhoneMatcher */
|
||||
/* exported MockFindMatcher */
|
||||
|
||||
var MockFindMatcher = {
|
||||
find: function(options) {
|
||||
this.result = [];
|
||||
|
||||
if (!this.data && Array.isArray(this.foundData)) {
|
||||
return {
|
||||
result: this.foundData,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
if (options.filterBy.indexOf('tel') !== -1) {
|
||||
value = options.filterValue;
|
||||
|
||||
var variantsValue = SimplePhoneMatcher.generateVariants(value);
|
||||
var variantsContact1 = [];
|
||||
var variantsContact2 = [];
|
||||
var found = false;
|
||||
if (this.data.tel && this.data.tel[0] && this.data.tel[0].value) {
|
||||
var telValue = this.data.tel[0].value;
|
||||
found = variantsValue.indexOf(
|
||||
SimplePhoneMatcher.sanitizedNumber(telValue)) !== -1;
|
||||
if (!found) {
|
||||
variantsContact1 =
|
||||
SimplePhoneMatcher.generateVariants(telValue);
|
||||
found = variantsContact1.indexOf(
|
||||
SimplePhoneMatcher.sanitizedNumber(value)) !== -1;
|
||||
}
|
||||
}
|
||||
if (!found && this.data.tel && this.data.tel[1] &&
|
||||
this.data.tel[1].value) {
|
||||
var tel2Value = this.data.tel[1].value;
|
||||
found = variantsValue.indexOf(
|
||||
SimplePhoneMatcher.sanitizedNumber(tel2Value)) !== -1;
|
||||
if (!found) {
|
||||
variantsContact2 =
|
||||
SimplePhoneMatcher.generateVariants(tel2Value);
|
||||
found = variantsContact1.indexOf(
|
||||
SimplePhoneMatcher.sanitizedNumber(value)) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
this.result = [this.data];
|
||||
}
|
||||
} else if (options.filterBy.indexOf('email') !== -1) {
|
||||
value = options.filterValue;
|
||||
if (this.data.email && this.data.email[0].value === value ||
|
||||
this.data.email[1] && this.data.email[1].value === value) {
|
||||
this.result = [this.data];
|
||||
}
|
||||
} else if (options.filterBy.indexOf('familyName') !== -1) {
|
||||
value = options.filterValue;
|
||||
if (this.data.familyName && this.data.familyName[0] === value) {
|
||||
this.result = [this.data];
|
||||
}
|
||||
} else if (options.filterBy.indexOf('name') !== -1) {
|
||||
value = options.filterValue;
|
||||
if (this.data.name && this.data.name[0] === value) {
|
||||
this.result = [this.data];
|
||||
}
|
||||
}
|
||||
return {
|
||||
result: this.result,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
save: function() {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
},
|
||||
set onerror(cb) {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
},
|
||||
set onerror(cb) {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
setData: function(data) {
|
||||
this.data = data;
|
||||
},
|
||||
|
||||
setFoundData: function(data) {
|
||||
this.foundData = data;
|
||||
}
|
||||
};
|
||||
205
gaia/apps/communications/contacts/test/unit/mock_form_dom.js.html
Executable file
205
gaia/apps/communications/contacts/test/unit/mock_form_dom.js.html
Executable file
|
|
@ -0,0 +1,205 @@
|
|||
var MockFormDom = '<section id="view-contact-form" role="region" data-mirror="mirror-contact-form" class="view view-edit-contact">';
|
||||
MockFormDom += ' <gaia-header id="contact-form-header" action="edit">';
|
||||
MockFormDom += ' <h1 id="contact-form-title" data-l10n-id="addContact">Add contact</h1>';
|
||||
MockFormDom += ' <button id="save-button" data-l10n-id="done">Done</button>';
|
||||
MockFormDom += ' </gaia-header>';
|
||||
MockFormDom += ' <progress id="throbber" value="0" max="100" class="pack-activity hide"></progress>';
|
||||
|
||||
MockFormDom += '<div id="add-phone-#i#" role="listitem" data-template class="phone-template field-template" data-index="#i#">';
|
||||
MockFormDom += ' <fieldset class="fillflow-row">';
|
||||
MockFormDom += ' <div class="two_fields">';
|
||||
MockFormDom += ' <legend class="action" role="combobox" aria-haspopup="true" aria-labelledby="tel_type_#i#">';
|
||||
MockFormDom += ' <span aria-hidden="true" data-taglist="phone-type" name="tel" data-value="#type_value#"';
|
||||
MockFormDom += ' id="tel_type_#i#" data-field="type" data-l10n-id="#type_l10n_id#">';
|
||||
MockFormDom += ' #type#';
|
||||
MockFormDom += ' </span>';
|
||||
MockFormDom += ' </legend>';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <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#" dir="auto">';
|
||||
MockFormDom += ' <button type="reset">Clear</button>';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' <section>';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <input placeholder="Phone" data-field="value" data-l10n-id="tel" name="tel[#i#][value]" class="textfield" type="tel" value="#value#" id="number_#i#">';
|
||||
MockFormDom += ' <button type="reset">Clear</button>';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </section>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
MockFormDom += '</div>';
|
||||
|
||||
MockFormDom += ' <!-- EMAIL TEMPLATE -->';
|
||||
MockFormDom += ' <div id="add-email-#i#" data-template class="email-template" data-index="#i#">';
|
||||
MockFormDom += ' <dl class="setbox fillflow-row">';
|
||||
MockFormDom += ' <dt class="setbox-title">';
|
||||
MockFormDom += ' <a data-taglist="email-type" name="email" value="#type#" id="email_type_#i#" data-field="type">#type#</a>';
|
||||
MockFormDom += ' <span role="button" class="icon-arrow icon-arrow-bottom setbox-icon bb-button">Expand</span>';
|
||||
MockFormDom += ' </dt>';
|
||||
MockFormDom += ' <dd class="setbox-body">';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <label class="hide" for="email_#i#" data-l10n-id="labelEmail">e-mail:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Email" data-field="value" data-l10n-id="email" name="email" class="textfield" type="email" value="#value#" id="email_#i#">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </dd>';
|
||||
MockFormDom += ' </dl>';
|
||||
MockFormDom += ' </div>';
|
||||
|
||||
MockFormDom += ' <!-- ADDRESS TEMPLATE -->';
|
||||
MockFormDom += ' <div id="add-address-#i#" data-template class="address-template" data-index="#i#">';
|
||||
MockFormDom += ' <dl class="setbox fillflow-row">';
|
||||
MockFormDom += ' <dt class="setbox-title">';
|
||||
MockFormDom += ' <a data-taglist="address-type" name="address" value="#type#" id="address_type_#i#" data-field="type">#type#</a>';
|
||||
MockFormDom += ' <span role="button" class="icon-arrow icon-arrow-bottom setbox-icon bb-button">Expand</span>';
|
||||
MockFormDom += ' </dt>';
|
||||
MockFormDom += ' <dd class="setbox-body">';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <label class="hide" for="streetAddress_#i#" data-l10n-id="labelStreet">Street:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Street" data-field="streetAddress" data-l10n-id="streetAddress" name="address" class="textfield" type="text" value="#streetAddress#" id="streetAddress_#i#">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <label class="hide" for="postalCode_#i#" data-l10n-id="labelZip">Zip Code:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Zip Code" data-field="postalCode" data-l10n-id="postalCode" name="address" class="textfield" type="text" value="#postalCode#" id="postalCode_#i#">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <label class="hide" for="locality_#i#" data-l10n-id="labelCity">City:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="City" data-field="locality" data-l10n-id="locality" name="address" class="textfield" type="text" value="#locality#" id="locality_#i#">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <label class="hide" for="countryName_#i#" data-l10n-id="labelCountry">Country:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Country" data-field="countryName" data-l10n-id="countryName" name="address" class="textfield" type="text" value="#countryName#" id="countryName_#i#">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </dd>';
|
||||
MockFormDom += ' </dl>';
|
||||
MockFormDom += ' </div>';
|
||||
|
||||
MockFormDom += ' <!-- DATES TEMPLATE -->'
|
||||
MockFormDom += ' <div id="add-date-#i#" data-template class="date-template" data-exclusive="true" data-custom="false" data-index="#i#">'
|
||||
MockFormDom += ' <fieldset class="fillflow-row">'
|
||||
MockFormDom += ' <legend class="action">'
|
||||
MockFormDom += ' <span data-taglist="date-type" name="date[#i#][type]" data-value="#type_value#" id="date_type_#i#" data-field="type" data-l10n-id="#type_l10n_id#">#type#</span>'
|
||||
MockFormDom += ' </legend>'
|
||||
MockFormDom += ' <section>'
|
||||
MockFormDom += ' <p class="setbox-item">'
|
||||
MockFormDom += ' <span class="button icon icon-dialog">'
|
||||
MockFormDom += ' <span id="date-text_#i#" data-l10n-id="date.placeholder" class="datetime">'
|
||||
MockFormDom += ' Date'
|
||||
MockFormDom += ' </span>'
|
||||
MockFormDom += ' <input placeholder="date" data-field="#type#" data-l10n-id="date" name="date[#i#][value]" class="textfield hidden-input" type="date" id="date_#i#">'
|
||||
MockFormDom += ' </span>'
|
||||
MockFormDom += ' </p>'
|
||||
MockFormDom += ' </section>'
|
||||
MockFormDom += ' </fieldset>'
|
||||
MockFormDom += ' </div>'
|
||||
|
||||
MockFormDom += ' <!-- COMMENTS TEMPLATE -->';
|
||||
MockFormDom += ' <div id="add-note-#i#" role="listitem" data-template class="note-template field-template" data-index="#i#">';
|
||||
MockFormDom += ' <dl role="presentation" class="setbox fillflow-row">';
|
||||
MockFormDom += ' <dd class="setbox-body">';
|
||||
MockFormDom += ' <p class="setbox-item">';
|
||||
MockFormDom += ' <input placeholder="Comment" data-field="note" data-l10n-id="comment" name="comment[#i#]" class="textfield" type="text" x-inputmode="latin-prose" value="#note#" id="note_#i#" dir="auto">';
|
||||
MockFormDom += ' <button type="reset">Clear</button>';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </dd>';
|
||||
MockFormDom += ' </dl>';
|
||||
MockFormDom += ' </div>';
|
||||
|
||||
MockFormDom += ' <article class="view-body">';
|
||||
MockFormDom += ' <div class="view-body-inner">';
|
||||
MockFormDom += ' <form id="contact-form" action="#" class="fill-flow">';
|
||||
MockFormDom += ' <input name="id" id="contact-form-id" type="hidden" value="">';
|
||||
MockFormDom += ' <fieldset class="item first">';
|
||||
MockFormDom += ' <legend class="hide" data-l10n-id="legendTitleMain">Main information</legend>';
|
||||
MockFormDom += ' <div id="thumbnail-action" href="#" class="item-media fillflow-media">';
|
||||
MockFormDom += ' <div role="button" id="photo-button" class="bb-button">';
|
||||
MockFormDom += ' <p>';
|
||||
MockFormDom += ' <span role="button" class="icon-addimage bb-button"></span>';
|
||||
MockFormDom += ' <em data-l10n-id="addPhoto"> Add photo</em>';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' <img id="thumbnail-photo" alt="">';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' <div class="item-body-exp">';
|
||||
MockFormDom += ' <p class="fillflow-row">';
|
||||
MockFormDom += ' <label class="hide" for="givenName" data-l10n-id="labelName">Name:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Name" data-field="givenName" data-l10n-id="givenName" name="givenName" class="textfield" type="text" value="#givenName#" id="givenName">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' <p class="fillflow-row">';
|
||||
MockFormDom += ' <label class="hide" for="user_lastname" data-l10n-id="labelLastName">Last name:</label>';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Last name" data-field="familyName" data-l10n-id="familyName" name="familyName" class="textfield" type="text" value="#familyName#" id="familyName">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' <p class="fillflow-row">';
|
||||
MockFormDom += ' <input data-cancelable placeholder="Company Name" data-field="org" familyName data-l10n-id="org" name="org" class="textfield" type="text" value="" id="org">';
|
||||
MockFormDom += ' </p>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
|
||||
MockFormDom += ' <fieldset>';
|
||||
MockFormDom += ' <legend data-l10n-id="legendPhones">Phone numbers</legend>';
|
||||
MockFormDom += ' <div id="contacts-form-phones">';
|
||||
MockFormDom += ' <!-- Iterating over phone template here -->';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
|
||||
MockFormDom += ' <button id="add-new-phone" class="fillflow-row action action-add">';
|
||||
MockFormDom += ' <span role="button" class="icon-add bb-button"></span>';
|
||||
MockFormDom += ' <b data-l10n-id="addPhone">Add phone number</b>';
|
||||
MockFormDom += ' </button>';
|
||||
|
||||
MockFormDom += ' <fieldset>';
|
||||
MockFormDom += ' <legend data-l10n-id="legendEmail">E-mail address</legend>';
|
||||
MockFormDom += ' <div id="contacts-form-emails">';
|
||||
MockFormDom += ' <!-- Iterating over email template here -->';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
|
||||
MockFormDom += ' <button id="add-new-email" class="fillflow-row action action-add">';
|
||||
MockFormDom += ' <span role="button" class="icon-add bb-button"></span>';
|
||||
MockFormDom += ' <b data-l10n-id="addEmail">Add email address</b>';
|
||||
MockFormDom += ' </button>';
|
||||
|
||||
MockFormDom += ' <fieldset>';
|
||||
MockFormDom += ' <legend data-l10n-id="legendAddress">Address</legend>';
|
||||
MockFormDom += ' <div id="contacts-form-addresses">';
|
||||
MockFormDom += ' <!-- Iterating over address template here -->';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
|
||||
MockFormDom += ' <button id="add-new-address" class="fillflow-row action action-add">';
|
||||
MockFormDom += ' <span role="button" class="icon-add bb-button"></span>';
|
||||
MockFormDom += ' <b data-l10n-id="addAddress">Add new address</b>';
|
||||
MockFormDom += ' </button>';
|
||||
|
||||
MockFormDom += ' <li>'
|
||||
MockFormDom += ' <section>'
|
||||
MockFormDom += ' <div id="contacts-form-dates"></div>'
|
||||
MockFormDom += ' </section>'
|
||||
MockFormDom += ' <button data-field-type="date" id="add-new-date" data-l10n-id="addDate" class="fillflow-row action action-add icon icon-add">'
|
||||
MockFormDom += ' Add Date'
|
||||
MockFormDom += ' </button>'
|
||||
MockFormDom += ' </li>'
|
||||
|
||||
|
||||
MockFormDom += ' <fieldset>';
|
||||
MockFormDom += ' <legend data-l10n-id="comments">Comments</legend>';
|
||||
MockFormDom += ' <div id="contacts-form-notes">';
|
||||
MockFormDom += ' <!-- Iterating over comment template here -->';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </fieldset>';
|
||||
|
||||
MockFormDom += ' <button id="add-new-note" class="fillflow-row action action-add">';
|
||||
MockFormDom += ' <span role="button" class="icon-add bb-button"></span>';
|
||||
MockFormDom += ' <b data-l10n-id="addComment">Add comment</b>';
|
||||
MockFormDom += ' </button>';
|
||||
|
||||
MockFormDom += ' </form>';
|
||||
|
||||
MockFormDom += ' <footer class="tail-actions hide">'
|
||||
MockFormDom += ' <button id="delete-contact" class="hide fillflow-row action action-delete danger">';
|
||||
MockFormDom += ' <b data-l10n-id="deleteContact">Delete contact</b>';
|
||||
MockFormDom += ' </button>';
|
||||
MockFormDom += ' </footer>';
|
||||
MockFormDom += ' </div>';
|
||||
MockFormDom += ' </article>';
|
||||
MockFormDom += ' </section>';
|
||||
MockFormDom += ' <form is="confirmation-message" id="confirmation-message" class="hide" role="dialog" data-type="confirm">';
|
||||
MockFormDom += ' <section><h1>Confirmation title</h1><p>Confirmation message</p></section><menu><button>Action 1</button><button>Action 2</button></menu></form>';
|
||||
33
gaia/apps/communications/contacts/test/unit/mock_get_device_storage.js
Executable file
33
gaia/apps/communications/contacts/test/unit/mock_get_device_storage.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
'use strict';
|
||||
/* exported MockgetDeviceStorage */
|
||||
|
||||
var MockgetDeviceStorage = function() {
|
||||
return {
|
||||
'get': function(filepath) {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
},
|
||||
get result() {
|
||||
var file = {
|
||||
name: filepath,
|
||||
size: 1
|
||||
};
|
||||
return file;
|
||||
}
|
||||
};
|
||||
},
|
||||
'addNamed': function(contact, filename) {
|
||||
var response = {
|
||||
target: {
|
||||
result: filename
|
||||
}
|
||||
};
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb(response);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
34
gaia/apps/communications/contacts/test/unit/mock_header_ui.js
Executable file
34
gaia/apps/communications/contacts/test/unit/mock_header_ui.js
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
/* exported MockHeaderUI */
|
||||
|
||||
/* globals ActivityHandler, MainNavigation */
|
||||
|
||||
var MockHeaderUI = {
|
||||
_lastCustomHeaderCallback: null,
|
||||
|
||||
init: function() {},
|
||||
|
||||
setupActionableHeader: function() {},
|
||||
|
||||
setCancelableHeader: function(cb, titleId) {},
|
||||
|
||||
setNormalHeader: function() {},
|
||||
|
||||
setupCancelableHeader: function(alternativeTitle) {},
|
||||
|
||||
handleCancel: function() {
|
||||
//If in an activity, cancel it
|
||||
if (ActivityHandler.currentlyHandling) {
|
||||
ActivityHandler.postCancel();
|
||||
MainNavigation.home();
|
||||
} else {
|
||||
MainNavigation.back();
|
||||
}
|
||||
},
|
||||
|
||||
updateSelectCountTitle: function(count) {},
|
||||
|
||||
hideAddButton: function() {},
|
||||
|
||||
updateHeader: function() {}
|
||||
};
|
||||
14
gaia/apps/communications/contacts/test/unit/mock_icc_helper.js
Executable file
14
gaia/apps/communications/contacts/test/unit/mock_icc_helper.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
/* exported MockIccHelper */
|
||||
|
||||
var MockIccHelper = {
|
||||
mSetup: function icch_mSetup() {},
|
||||
|
||||
mTeardown: function icch_mTeardown() {},
|
||||
|
||||
addEventListener: function icch_addEventListener(event, handler) {},
|
||||
|
||||
get cardState() {
|
||||
return 'ready';
|
||||
}
|
||||
};
|
||||
26
gaia/apps/communications/contacts/test/unit/mock_ice_data.js
Executable file
26
gaia/apps/communications/contacts/test/unit/mock_ice_data.js
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockICEData */
|
||||
|
||||
var MockICEData = {
|
||||
_mChangeCallbacks: [],
|
||||
iceContacts: [],
|
||||
load: function() {},
|
||||
setICEContact: function(id, pos, active) {
|
||||
this.iceContacts[pos] = {
|
||||
id: id,
|
||||
active: active
|
||||
};
|
||||
},
|
||||
listenForChanges: function(cb) {
|
||||
this._mChangeCallbacks.push(cb);
|
||||
},
|
||||
stopListenForChanges: function() {
|
||||
this._mChangeCallbacks = [];
|
||||
},
|
||||
_mTriggerChange: function(data) {
|
||||
this._mChangeCallbacks.forEach(function(fn) {
|
||||
fn(MockICEData.iceContacts);
|
||||
});
|
||||
}
|
||||
};
|
||||
7
gaia/apps/communications/contacts/test/unit/mock_image_thumbnail.js
Executable file
7
gaia/apps/communications/contacts/test/unit/mock_image_thumbnail.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockThumbnailImage */
|
||||
|
||||
var MockThumbnailImage = function(blob, callback) {
|
||||
callback(blob);
|
||||
};
|
||||
26
gaia/apps/communications/contacts/test/unit/mock_import_status_data.js
Executable file
26
gaia/apps/communications/contacts/test/unit/mock_import_status_data.js
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
/* global Promise */
|
||||
/* exported MockImportStatusData */
|
||||
|
||||
var MockImportStatusData = {
|
||||
keys: Object.create(null),
|
||||
|
||||
get: function get(key) {
|
||||
return Promise.resolve(this.keys[key]);
|
||||
},
|
||||
|
||||
put: function put(key, obj) {
|
||||
this.keys[key] = obj;
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
remove: function remove(key) {
|
||||
delete this.keys[key];
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
clear: function clear() {
|
||||
this.keys = Object.create(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
18
gaia/apps/communications/contacts/test/unit/mock_import_utils.js
Executable file
18
gaia/apps/communications/contacts/test/unit/mock_import_utils.js
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
/* exported MockimportUtils */
|
||||
'use strict';
|
||||
|
||||
var MockimportUtils = {
|
||||
getPreferredPictureBox: function(){
|
||||
return 1;
|
||||
},
|
||||
getPreferredPictureDetail: function() {
|
||||
return 1;
|
||||
},
|
||||
setTimestamp: function(type, callback) {
|
||||
callback(Date.now());
|
||||
},
|
||||
getTimestamp: function(type, callback) {
|
||||
callback(Date.now());
|
||||
}
|
||||
};
|
||||
|
||||
61
gaia/apps/communications/contacts/test/unit/mock_l10n.js
Executable file
61
gaia/apps/communications/contacts/test/unit/mock_l10n.js
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockMozL10n */
|
||||
|
||||
window.realL10n = window.navigator.mozL10n;
|
||||
|
||||
var MockMozL10n = window.navigator.mozL10n = {
|
||||
realL10nCB: null,
|
||||
language: {
|
||||
code: 'en',
|
||||
direction: 'ltr'
|
||||
},
|
||||
get: function get(key, params) {
|
||||
var out = key;
|
||||
|
||||
if (params) {
|
||||
if (key == 'itemWithLabel') {
|
||||
out = params.label + ', ' + params.item;
|
||||
} else {
|
||||
Object.keys(params).forEach(function(id) {
|
||||
out += params[id];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
},
|
||||
translate: function() {},
|
||||
once: function(cb) {
|
||||
this.realL10nCB = cb;
|
||||
this.onceCb = cb;
|
||||
cb();
|
||||
},
|
||||
ready: function(cb) {
|
||||
this.readyCb = cb;
|
||||
},
|
||||
fireReady: function() {
|
||||
if (!this.readyCb) {
|
||||
return;
|
||||
}
|
||||
this.readyCb();
|
||||
},
|
||||
fireOnce: function() {
|
||||
if (!this.onceCb) {
|
||||
return;
|
||||
}
|
||||
this.onceCb();
|
||||
},
|
||||
setAttributes: function(element, id, args) {
|
||||
element.setAttribute('data-l10n-id', id);
|
||||
if (args) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(args));
|
||||
}
|
||||
},
|
||||
getAttributes: function(element) {
|
||||
return {
|
||||
id: element.getAttribute('data-l10n-id'),
|
||||
args: JSON.parse(element.getAttribute('data-l10n-args'))
|
||||
};
|
||||
},
|
||||
};
|
||||
39
gaia/apps/communications/contacts/test/unit/mock_link.html
Executable file
39
gaia/apps/communications/contacts/test/unit/mock_link.html
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
<section role="region" id="content" class="link">
|
||||
|
||||
<gaia-header id="link-header" action="close">
|
||||
<h1 data-l10n-id="fbFriends">Facebook Friends</h1>
|
||||
</gaia-header>
|
||||
|
||||
<section id="main">
|
||||
<!-- Contacts List Section -->
|
||||
<section id="mainContent" data-state="selection" data-type="list">
|
||||
<ol id="friends-list">
|
||||
<li data-template data-uuid="#uid#">
|
||||
<a href="#">
|
||||
<aside class="pack-end">
|
||||
<span data-type="img" data-src="https://graph.facebook.com/#uid#/picture?width=#picwidth#&height=#picheight#"></span>
|
||||
</aside>
|
||||
<p>#name#</p>
|
||||
<p>#email#</p>
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</section> <!-- mainContent -->
|
||||
|
||||
<form role="dialog" data-type="confirm" class="no-overlay">
|
||||
<menu>
|
||||
<button id="view-all" data-l10n-id="viewAll" class="full">
|
||||
View all Facebook Friends
|
||||
</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</section> <!-- main -->
|
||||
|
||||
</section> <!-- role="region" -->
|
||||
|
||||
<section id="statusMsg" role="status">
|
||||
<p></p>
|
||||
</section>
|
||||
|
||||
10
gaia/apps/communications/contacts/test/unit/mock_link.html.js
Executable file
10
gaia/apps/communications/contacts/test/unit/mock_link.html.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
/* exported MockLinkHtml */
|
||||
|
||||
var MockLinkHtml = (function MockLinkHtml() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', '/contacts/test/unit/mock_link.html', false);
|
||||
req.send(null);
|
||||
|
||||
return req.responseText;
|
||||
})();
|
||||
70
gaia/apps/communications/contacts/test/unit/mock_linked_contacts.js
Executable file
70
gaia/apps/communications/contacts/test/unit/mock_linked_contacts.js
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
'use strict';
|
||||
/* exported MockAllFacebookContacts */
|
||||
/* exported MockLinkedContacts */
|
||||
|
||||
var MockLinkedContacts = {
|
||||
data: [{
|
||||
fql_result_set: [
|
||||
{
|
||||
'uid': '1xz',
|
||||
'email': 'test@test.com',
|
||||
'name': 'Pepito Grillo'
|
||||
},
|
||||
{
|
||||
'uid': '2abc',
|
||||
'email': 'test2@test2.com',
|
||||
'name': 'Alfonso Gonzo'
|
||||
}]},
|
||||
{
|
||||
fql_result_set: [{
|
||||
'uid': '5678x'
|
||||
},
|
||||
{
|
||||
'uid': '56zwt'
|
||||
},
|
||||
{
|
||||
'uid': 'kjh2389'
|
||||
},
|
||||
{
|
||||
'uid': 'aa45bb'
|
||||
}]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var MockAllFacebookContacts = {
|
||||
data: [
|
||||
{
|
||||
'uid': '5678x',
|
||||
'email': 'beppe@grillo.it',
|
||||
'name': 'Beppe Grillo',
|
||||
'last_name': 'Grillo',
|
||||
'first_name': 'Beppe',
|
||||
'middle_name': null
|
||||
},
|
||||
{
|
||||
'uid': '56zwt',
|
||||
'email': 'test2@test2.com',
|
||||
'name': 'Herman Gonzo',
|
||||
'last_name': 'Gonzo',
|
||||
'first_name': 'Herman',
|
||||
'middle_name': null
|
||||
},
|
||||
{
|
||||
'uid': 'kjh2389',
|
||||
'email': 'angela.cuts@german.de',
|
||||
'name': 'Ángela Cuts',
|
||||
'last_name': 'Cuts',
|
||||
'first_name': 'Ángela',
|
||||
'middle_name': null
|
||||
},
|
||||
{
|
||||
'uid': 'aa45bb',
|
||||
'email': 'rudygonzalez@example.org',
|
||||
'name': 'Rudy González',
|
||||
'last_name': 'González',
|
||||
'first_name': 'Rudy',
|
||||
'middle_name': null
|
||||
}
|
||||
]
|
||||
};
|
||||
12
gaia/apps/communications/contacts/test/unit/mock_loader.js
Executable file
12
gaia/apps/communications/contacts/test/unit/mock_loader.js
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
/* exported MockLoader */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockLoader = {
|
||||
utility: function(view, callback, type) {
|
||||
callback();
|
||||
},
|
||||
view: function(view, callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
5
gaia/apps/communications/contacts/test/unit/mock_main_navigation.js
Executable file
5
gaia/apps/communications/contacts/test/unit/mock_main_navigation.js
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
'use strict';
|
||||
/* global MockNavigationStack */
|
||||
/* exported MockMainNavigation */
|
||||
|
||||
var MockMainNavigation = new MockNavigationStack();
|
||||
37
gaia/apps/communications/contacts/test/unit/mock_matching_contacts.html
Executable file
37
gaia/apps/communications/contacts/test/unit/mock_matching_contacts.html
Executable file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue