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:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View 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;
}
});
});
});
});