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,19 @@
{
"extends": "../../../../.jshintrc",
"predef": [
"assert",
"suite",
"test",
"setup",
"teardown",
"suiteSetup",
"suiteTeardown",
"suiteTemplate",
"require",
"requireApp",
"requireElements",
"sinon",
"mocha",
"loadBodyHTML"
]
}

View file

@ -0,0 +1,54 @@
'use strict';
/* global loadBodyHTML, MockNavigatormozApps, appManager, MockL10n */
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
require('/shared/test/unit/mocks/mock_l10n.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/js/component_utils.js');
require('/shared/elements/gaia_confirm/script.js');
require('/shared/js/homescreens/confirm_dialog_helper.js');
suite('app_manager.js > ', function() {
var realMozApps = null,
realL10n = null,
app = {};
suiteSetup(function(done) {
loadBodyHTML('/index.html');
realMozApps = navigator.mozApps;
navigator.mozApps = MockNavigatormozApps;
realL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
require('/js/app_manager.js', done);
});
suiteTeardown(function() {
navigator.mozApps = realMozApps;
MockNavigatormozApps.mTeardown();
navigator.mozL10n = realL10n;
realL10n = realMozApps = null;
});
test('The library was initialized properly', function() {
MockNavigatormozApps.mTriggerLastRequestSuccess(app);
assert.equal(appManager.self, app);
});
test('Can\'t show delete dialog more than once', function() {
var showDialogSpy = sinon.spy();
sinon.stub(window, 'ConfirmDialogHelper').returns({ show: showDialogSpy });
var removeItemEvent = new CustomEvent('removeitem',
{ detail:
{ detail: { type: null } }
});
appManager.handleEvent(removeItemEvent);
assert(appManager.dialogVisible);
appManager.handleEvent(removeItemEvent);
assert(showDialogSpy.calledOnce);
});
});

View file

@ -0,0 +1,122 @@
'use strict';
/* global app */
/* global MocksHelper, loadBodyHTML */
require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/mocks/mock_settings_listener.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
require('/shared/elements/gaia_grid/js/grid_layout.js');
require('/shared/elements/gaia_grid/js/grid_view.js');
require('/shared/elements/gaia_grid/script.js');
require('/shared/elements/gaia_grid/js/items/grid_item.js');
require('/shared/elements/gaia_grid/js/items/divider.js');
require('/shared/elements/gaia_grid/js/items/placeholder.js');
require('/test/unit/mock_item_store.js');
var mocksHelperForApp = new MocksHelper([
'LazyLoader',
'ItemStore',
'SettingsListener'
]).init();
suite('app.js > ', function() {
mocksHelperForApp.attachTestHelpers();
var raf, scrollStub;
var documentHiddenValue = false;
suiteSetup(function() {
Object.defineProperty(document, 'hidden', {
configurable: true,
get: function() {
return documentHiddenValue;
}
});
});
setup(function(done) {
raf = sinon.stub(window, 'requestAnimationFrame',
function(callback) { callback(); });
scrollStub = sinon.stub(window, 'scrollTo');
loadBodyHTML('/index.html');
var grid = document.querySelector('gaia-grid')._grid;
// Some features are loaded after rendering like dragdrop
grid.render();
require('/js/app.js', done);
this.sinon.useFakeTimers();
});
teardown(function() {
raf.restore();
scrollStub.restore();
documentHiddenValue = false;
});
test('Scrolls on hashchange', function() {
window.scrollY = 100000;
window.dispatchEvent(new CustomEvent('hashchange'));
assert.ok(scrollStub.called);
});
test('Scrolls on gaiagrid-attention', function() {
window.scrollY = 100000;
app.grid.dispatchEvent(
new CustomEvent('gaiagrid-attention', {detail: {y: 0, height: 0}}));
assert.ok(scrollStub.called);
});
test('No scrolling while context menu is displayed', function() {
window.dispatchEvent(new CustomEvent('context-menu-open'));
window.dispatchEvent(new CustomEvent('hashchange'));
assert.isFalse(raf.called);
window.dispatchEvent(new CustomEvent('context-menu-close'));
});
test('Transition property in edit-mode', function() {
app.grid.dispatchEvent(new CustomEvent('editmode-start'));
assert.equal(app.grid.style.transition, app.EDIT_MODE_TRANSITION_STYLE);
app.grid.dispatchEvent(new CustomEvent('editmode-end'));
assert.equal(app.grid.style.transition, '');
});
test('Hashchange event without dragdrop', function() {
var oldDragdrop = app.grid._grid.dragdrop;
app.grid._grid.dragdrop = undefined;
app.handleEvent({type: 'hashchange'});
app.grid._grid.dragdrop = oldDragdrop;
// This test was added for bug 1051061. If the test passes it means that
// the test did not throw an error and that bug is not a problem.
// No assertion is needed.
});
suite('When the homescreen is hidden', function() {
setup(function() {
documentHiddenValue = true;
document.dispatchEvent(new CustomEvent('visibilitychange'));
});
test('should hide the overflow to prevent displayport rendering',
function() {
assert.equal(document.body.style.overflow, 'hidden');
});
suite('then displayed again',function() {
setup(function() {
documentHiddenValue = false;
document.dispatchEvent(new CustomEvent('visibilitychange'));
});
test('should let the homescreen scroll after a tick', function() {
assert.equal(document.body.style.overflow, 'hidden');
this.sinon.clock.tick();
assert.equal(document.body.style.overflow, '');
});
});
});
});

View file

@ -0,0 +1,370 @@
'use strict';
/* global Configurator, MockNavigatorSettings, IccHelper,
MocksHelper, MockVersionHelper, verticalPreferences,
MockNavigatorGetFeature, LazyLoader */
require('/shared/js/homescreens/vertical_preferences.js');
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
require('/shared/test/unit/mocks/mock_navigator_get_feature.js');
require('/shared/test/unit/mocks/mock_icc_helper.js');
require('/test/unit/mock_version_helper.js');
require('/shared/js/lazy_loader.js');
var mocksHelperForConfigurator = new MocksHelper([
'VersionHelper',
'IccHelper'
]).init();
suite('configurator.js >', function() {
mocksHelperForConfigurator.attachTestHelpers();
var realGetFeature;
var realMozSettings;
var requests = [];
var configurator;
var confGridOK = {
'preferences': {},
'prediction': {
'enabled': true,
'lookahead': 16
},
'grid': [
[
{
'entry_point': 'dialer',
'name': 'Phone',
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
'icon':
'app://communications.gaiamobile.org/dialer/style/icons/Dialer_60.png'
}
]
]};
var confSV = {
'214-007': [
{
'location': 14,
'manifestURL':
'https://marketplace.firefox.com/app/' +
'9f96ce77-5b2d-42ca-a0d9-10a933dd84c4/manifest.webapp'
},{
'location': 1000,
'manifestURL': 'https://mobile.twitter.com/cache/twitter.webapp'
},{
'location': 6,
'manifestURL':
'https://bits.wikimedia.org/WikipediaMobileFirefoxOS/manifest.webapp'
},{
'manifestURL':
'https://owdstore.hi.inet/operRes/latam/operatorResourcesLatam.webapp'
}
]};
suiteSetup(function() {
mocksHelperForConfigurator.suiteSetup();
realMozSettings = navigator.mozSettings;
realGetFeature = navigator.getFeature;
navigator.getFeature = MockNavigatorGetFeature;
navigator.mozSettings = MockNavigatorSettings;
MockNavigatorSettings.mSyncRepliesOnly = true;
});
suiteTeardown(function() {
mocksHelperForConfigurator.suiteTeardown();
navigator.getFeature = realGetFeature;
navigator.mozSettings = realMozSettings;
MockNavigatorSettings.mSyncRepliesOnly = false;
});
setup(function(done) {
mocksHelperForConfigurator.setup();
requireApp('verticalhome/js/configurator.js', function() {
configurator = new Configurator();
requests = [];
done();
});
});
teardown(function() {
mocksHelperForConfigurator.teardown();
navigator.mozSettings.mTeardown();
});
test('Sections >', function(done) {
this.sinon.stub(LazyLoader, 'getJSON')
.returns(Promise.resolve(confGridOK));
configurator.load();
window.addEventListener('configuration-ready', function ready() {
window.removeEventListener('configuration-ready', ready);
var grid = configurator.getGrid();
assert.equal(grid[0][0].entry_point, confGridOK.grid[0][0].entry_point);
assert.equal(grid[0][0].name, confGridOK.grid[0][0].name);
assert.equal(grid[0][0].manifestURL, confGridOK.grid[0][0].manifestURL);
assert.equal(grid[0][0].icon, confGridOK.grid[0][0].icon);
var prediction = configurator.getSection('prediction');
assert.equal(prediction.enabled, confGridOK.prediction.enabled);
assert.equal(prediction.lookahead, confGridOK.prediction.lookahead);
// This section should be undefined
assert.isUndefined(configurator.getSection('noExiste'));
// For configurator remove the listener
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
IccHelper.mTriggerEventListeners('iccinfochange', {});
done();
});
});
function assertLoadFile(okLoad, done) {
window.addEventListener('configuration-ready', function ready() {
window.removeEventListener('configuration-ready', ready);
var grid = configurator.getGrid();
if (okLoad) {
assert.notEqual(grid, undefined);
} else {
assert.equal(grid, undefined);
}
// For remove listener
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
IccHelper.mTriggerEventListeners('iccinfochange', {});
done();
});
configurator.load();
}
test('Correct load conf file >', function(done) {
this.sinon.stub(LazyLoader, 'getJSON')
.returns(Promise.resolve(confGridOK));
assertLoadFile(true, done);
});
test('Wrong load conf file >', function(done) {
this.sinon.stub(LazyLoader, 'getJSON')
.returns(Promise.reject({'type': 'expected error'}));
assertLoadFile(false, done);
});
function assertSV(xhrOk, done) {
sinon.useFakeTimers();
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
IccHelper.mTriggerEventListeners('iccinfochange', {});
window.addEventListener('singlevariant-ready', function svReady() {
window.removeEventListener('singlevariant-ready', svReady);
var svApp;
if (xhrOk) {
svApp =
configurator.getSingleVariantApp(confSV['214-007'][0].manifestURL);
assert.equal(svApp.manifestURL, confSV['214-007'][0].manifestURL);
assert.equal(svApp.location, confSV['214-007'][0].location);
svApp =
configurator.getSingleVariantApp('nonexistent_manifest');
assert.isUndefined(svApp);
} else {
svApp =
configurator.getSingleVariantApp(confSV['214-007'][0].manifestURL);
assert.isUndefined(svApp);
}
done();
});
configurator.load();
}
/*
* It tests the public method 'getSingleVariantApps' getting properties/values
*/
test('getSingleVariantApps - Correct conf file >', function(done) {
this.sinon.stub(LazyLoader, 'getJSON')
.returns(Promise.resolve(confSV));
assertSV(true, done);
});
test('getSingleVariantApps - Wrong conf file >', function(done) {
this.sinon.stub(LazyLoader, 'getJSON')
.returns(Promise.reject({'type': 'expected error'}));
assertSV(false, done);
});
const KEY_SIM_ON_1ST_RUN = 'ftu.simPresentOnFirstBoot';
/*
* Checks isSimPresentOnFirstBoot function
*/
var testCases = [
{
'preValSet': undefined,
'currentMccMnc': '214-007',
'expecValSet': true,
'title': KEY_SIM_ON_1ST_RUN +
'setting value is undefined - isSimPresentOnFirstBoot is true'
}, {
'preValSet': '000-000',
'currentMccMnc': '214-007',
'expecValSet': false,
'title': KEY_SIM_ON_1ST_RUN +
'setting value different to the current mcc-mnc - ' +
'isSimPresentOnFirstBoot is false'
}, {
'preValSet': '214-007',
'currentMccMnc': '214-007',
'expecValSet': true,
'title': KEY_SIM_ON_1ST_RUN +
'setting value the same as current mcc-mnc - ' +
'isSimPresentOnFirstBoot is true'
}
];
testCases.forEach(function(testCase) {
test(testCase.title, function() {
this.sinon.useFakeTimers();
MockNavigatorSettings.mSettings[KEY_SIM_ON_1ST_RUN] = testCase.preValSet;
configurator.loadSettingSIMPresent(testCase.currentMccMnc);
this.sinon.clock.tick();
assert.equal(configurator.isSimPresentOnFirstBoot,
testCase.expecValSet);
});
});
suite('migration> ', function() {
var updateHandler = null;
var vpGetStub = null;
var vpEvtUpdateStub = null;
var mGrid_layout = {
'grid': [
[
{
'name': 'Phone',
'manifestURL': 'app://communications/manifest.webapp',
'icon': 'app://communications/icons/Dialer_60.png',
'entry_point': 'dialer'
},
{
'name': 'Messages',
'manifestURL': 'app://sms/manifest.webapp',
'icon': 'app://sms/icons/Sms_60.png'
}
],
[
{ 'id': 289, 'role': 'collection' },
{ 'id': 207, 'role': 'collection' }
],
[
{
'name': 'Contacts',
'manifestURL': 'app://communications/manifest.webapp',
'icon': 'app://communications/icons/Contacts_60.png',
'entry_point': 'contacts'
},
{
'name': 'Settings',
'manifestURL': 'app://settings/manifest.webapp',
'icon': 'app://settings/icons/Settings_60.png'
}
]
]
};
var mGrid_layout2 = {
'grid': [
[
{
'name': 'Messages2',
'manifestURL': 'app://sms/manifest.webapp',
'icon': 'app://sms/icons/Sms_60.png'
}
],
[
{ 'id': 200, 'role': 'collection' },
{ 'id': 100, 'role': 'collection' }
],
[
{
'name': 'Contacts2',
'manifestURL': 'app://communications/manifest.webapp',
'icon': 'app://communications/icons/Contacts_60.png',
'entry_point': 'contacts'
}
]
]
};
function dispatchUpdatedEvent(grid) {
updateHandler({
type: 'updated',
target: {
name: 'grid.layout',
value: grid
}
});
}
setup(function() {
vpGetStub = sinon.stub(verticalPreferences, 'get', function(field) {
return {
then: function(cb) {
cb(mGrid_layout);
}
};
});
vpEvtUpdateStub = sinon.stub(verticalPreferences, 'addEventListener',
function(type, handler) {
updateHandler = handler;
}
);
MockVersionHelper.mIsUpgrade = true;
});
teardown(function() {
vpGetStub.restore();
vpEvtUpdateStub.restore();
});
function assertGridOk(gridTest, gridOk) {
assert.notEqual(gridTest, undefined);
assert.equal(gridTest.length, gridOk.length);
for (var i = 0, iLen = gridOk.length; i < iLen; i++) {
assert.equal(gridTest[i].length, gridOk[i].length);
for (var j = 0, jLen = gridOk[i].length; j < jLen; j++) {
assert.equal(gridTest[i].length, gridOk[i].length);
assert.equal(gridTest[i][j].name, gridOk[i][j].name);
}
}
}
test('Upgrade from old homescreen - grid.layout ready >', function(done) {
window.addEventListener('configuration-ready', function ready() {
window.removeEventListener('configuration-ready', ready);
var grid = configurator.getGrid();
assertGridOk(grid, mGrid_layout.grid);
done();
});
configurator.load();
sinon.assert.callCount(vpEvtUpdateStub, 0);
});
test('Upgrade from old homescreen - grid.layout not ready >', function() {
var gridTest = mGrid_layout;
mGrid_layout = undefined;
configurator.load();
sinon.assert.calledOnce(vpEvtUpdateStub);
var grid = configurator.getGrid();
assert.equal(grid, undefined);
dispatchUpdatedEvent(mGrid_layout2);
grid = configurator.getGrid();
assertGridOk(grid, mGrid_layout2.grid);
mGrid_layout = gridTest;
});
});
});

View file

@ -0,0 +1,74 @@
'use strict';
/* global MocksHelper, MockL10n, contextMenuUI, loadBodyHTML,
contextMenuHandler, App */
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/mocks/mock_l10n.js');
require('/test/unit/mock_app.js');
require('/js/contextmenu_ui.js');
var mocksHelperForContextMenuHandler = new MocksHelper([
'App',
'LazyLoader'
]).init();
suite('contextmenu_handler.js >', function() {
var realL10n = null;
var clock = null;
mocksHelperForContextMenuHandler.attachTestHelpers();
suiteSetup(function(done) {
realL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
clock = sinon.useFakeTimers();
loadBodyHTML('/index.html');
require('/js/contextmenu_handler.js', done);
});
suiteTeardown(function() {
navigator.mozL10n = realL10n;
realL10n = null;
});
function dispatchContextMenu() {
contextMenuHandler.container.dispatchEvent(new CustomEvent('contextmenu'));
clock.tick();
}
test(' Handling contextmenu event', function() {
window.app = new App();
var stub = sinon.stub(contextMenuUI, 'show');
dispatchContextMenu();
sinon.assert.called(stub);
stub.restore();
delete window.app;
});
test(' Handling contextmenu event in edit mode', function() {
window.app = new App();
window.app.grid._grid.dragdrop.inEditMode = true;
var stub = sinon.stub(contextMenuUI, 'show');
dispatchContextMenu();
sinon.assert.notCalled(stub);
stub.restore();
delete window.app;
});
test(' Handling hashchange event', function() {
var stub = sinon.stub(contextMenuUI, 'hide');
window.dispatchEvent(new CustomEvent('hashchange'));
sinon.assert.called(stub);
stub.restore();
});
});

View file

@ -0,0 +1,96 @@
'use strict';
/* global app, contextMenuUI, wallpaper, MocksHelper */
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
require('/shared/elements/gaia_grid/js/grid_layout.js');
require('/shared/elements/gaia_grid/js/grid_view.js');
require('/shared/elements/gaia_grid/js/grid_zoom.js');
require('/shared/elements/gaia_grid/js/items/grid_item.js');
require('/shared/elements/gaia_grid/js/items/placeholder.js');
require('/shared/elements/gaia_grid/script.js');
require('/test/unit/mock_item_store.js');
require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/js/wallpaper.js');
requireElements('verticalhome/elements/contextmenu.html');
var mocksHelperForContextMenuUI = new MocksHelper([
'LazyLoader',
'ItemStore'
]).init();
suite('contextmenu_ui.js >', function() {
mocksHelperForContextMenuUI.attachTestHelpers();
var fakeEvt = {};
suiteSetup(function(done) {
loadBodyHTML('/index.html');
require('/js/app.js', done);
});
setup(function(done) {
app.init();
this.sinon.stub(app.grid._grid, 'getNearestItemIndex').returns(0);
require('/js/contextmenu_ui.js', done);
});
suiteTeardown(function() {
document.body.innerHTML = '';
});
function assertDisplayed() {
assert.isTrue(!contextMenuUI.dialog.hasAttribute('hidden'));
}
function assertHidden() {
assert.isTrue(contextMenuUI.dialog.hasAttribute('hidden'));
}
test(' Show and hide context menu', function() {
var clock = sinon.useFakeTimers();
contextMenuUI.show(fakeEvt);
clock.tick(50);
assertDisplayed();
contextMenuUI.hide();
assertHidden();
});
test(' Change wallpaper action', function(done) {
var stub = sinon.stub(wallpaper, 'change', function() {
stub.restore;
done();
});
contextMenuUI.show(fakeEvt);
contextMenuUI.dialog.querySelector('#change-wallpaper-action').click();
assertHidden();
});
test(' Cancel action', function() {
contextMenuUI.show(fakeEvt);
contextMenuUI.dialog.dispatchEvent(new CustomEvent('gaiamenu-cancel'));
assertHidden();
});
test(' Hide the context menu when the document is hidden', function() {
Object.defineProperty(document, 'hidden', {
configurable: true,
get: function() {
return true;
}
});
contextMenuUI.show(fakeEvt);
contextMenuUI.handleEvent({
'type': 'visibilitychange'
});
delete document.hidden;
assertHidden();
});
});

View file

@ -0,0 +1,60 @@
'use strict';
function MockApp() {
MockApp.initialized = false;
MockApp.mIcons = {};
MockApp.mItems = [];
}
MockApp.prototype = {
HIDDEN_ROLES: [
'system', 'keyboard', 'homescreen', 'search', 'addon', 'langpack'
],
init: function() {
MockApp.initialized = true;
},
mGetInitialized: function () {
return MockApp.initialized;
},
itemStore: {
save: function() {},
deferredSave: function() {}
},
grid: {
add: function(detail) {
if (detail) {
MockApp.mItems.push(detail);
}
},
appendItemToExpandedGroup: function(detail) {
if (detail) {
MockApp.mItems.push(detail);
}
},
removeIconByIdentifier: function(identifier) {
delete MockApp.mIcons[identifier];
},
removeItemByIndex: function(idx) {
MockApp.mItems.splice(idx, 1);
},
getIcons: function() {
return MockApp.mIcons;
},
getItems: function() {
return MockApp.mItems;
},
render: function() {},
_grid: {
dragdrop: {
inEditMode: false
}
}
}
};
MockApp.mTeardown = function mp_mTeardown() {
delete MockApp.initialized;
MockApp.mIcons = {};
MockApp.mItems = [];
};

View file

@ -0,0 +1,50 @@
/* global GaiaGrid */
'use strict';
var apps = [
{
'manifestURL': 'app://gallery.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://clock.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://keyboard.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://camera.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp'
},{
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp'
},{
'entryPoint': 'contacts',
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp'
},{
'entryPoint': 'dialer',
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp'
}
];
function MockApplicationSource() {
this.entries = [];
var mozApp;
for (var i = 0, iLen = apps.length; i < iLen; i++){
if (apps[i].entryPoint) {
mozApp = new GaiaGrid.Mozapp(apps[i], apps[i].entryPoint);
} else {
mozApp = new GaiaGrid.Mozapp(apps[i]);
}
mozApp.detail.index = i;
this.entries.push(mozApp);
}
}
MockApplicationSource.prototype = {
addPreviouslyInstalledSvApp: function(manifestURL) {
},
mapToApp: function (item) {
},
populate: function (next){
next(this.entries);
}
};

View file

@ -0,0 +1,11 @@
'use strict';
function MockBookmarkSource() {
this.entries = [];
}
MockBookmarkSource.prototype = {
populate: function(next) {
next(this.entries);
}
};

View file

@ -0,0 +1,56 @@
'use strict';
var confSV = {
'https://owdstore.hi.inet/operRes/spainResources.webapp':
{
'manifestURL': 'https://owdstore.hi.inet/operRes/spainResources.webapp'
},
'https://url/path/appSV.webapp':
{
'manifestURL': 'https://url/path/appSV.webapp',
'location': 1
}
};
var mcGrid = [
[
{
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
'name': 'Phone',
'entry_point': 'dialer',
'icon': 'app://communications.gaiamobile.org/dialer/icons/Dialer_120.png'
},{
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp',
'name': 'email',
'icon': 'app://email.gaiamobile.org/style/icons/Email_120.png'
}
],[
{
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
'entry_point': 'contacts',
'name': 'contacts',
'icon': 'app://communications.gaiamobile.org/contacts/style/icons/Cont'
}
],[
{
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp',
'name': 'browser',
'icon': 'app://browser.gaiamobile.esources/branding/Browser_120.png'
},{
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp',
'icon': 'app://music.gaiamobile.org/style/icons/Music_120.png'
}
]
];
var configurator = {
getGrid: function() {
return mcGrid;
},
isSingleVariantReady: true,
getSingleVariantApp: function(manifestURL) {
return confSV[manifestURL];
}
};
window.configurator = configurator;

View file

@ -0,0 +1,14 @@
'use strict';
function MockItemStore() {}
MockItemStore.prototype = {
mNextPosition: 0,
all: function() {},
deferredSave: function() {},
getNextPosition: function() {
var nextPosition = this.mNextPosition;
this.mNextPosition++;
return nextPosition;
}
};

View file

@ -0,0 +1,19 @@
'use strict';
var MockVersionHelper = {
mIsUpgrade: false,
mVersionInfo: {
isUpgrade: function() {
return MockVersionHelper.mIsUpgrade;
}
},
getVersionInfo: function() {
return {
then: function(cb) {
cb(MockVersionHelper.mVersionInfo);
}
};
}
};

View file

@ -0,0 +1,5 @@
'use strict';
/* global require */
require('/shared/test/unit/mocks/mocks_helper.js');

View file

@ -0,0 +1,67 @@
'use strict';
/* global App, ApplicationSource, GaiaGrid, ItemStore */
/* global MocksHelper, MockNavigatormozApps, loadBodyHTML */
require('/shared/js/l10n.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
require('/shared/elements/gaia_grid/js/grid_layout.js');
require('/shared/elements/gaia_grid/js/grid_view.js');
require('/shared/elements/gaia_grid/js/grid_zoom.js');
require('/shared/elements/gaia_grid/script.js');
require('/shared/elements/gaia_grid/js/items/grid_item.js');
require('/shared/elements/gaia_grid/js/items/placeholder.js');
require('/shared/elements/gaia_grid/js/items/mozapp.js');
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
require('/test/unit/mock_app.js');
require('/test/unit/mock_item_store.js');
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
var mocksHelperForApp = new MocksHelper([
'App',
'ItemStore'
]).init();
suite('app.js > ', function() {
mocksHelperForApp.attachTestHelpers();
var subject;
var realMozApps;
suiteSetup(function(done) {
window.app = new App();
realMozApps = navigator.mozApps;
navigator.mozApps = MockNavigatormozApps;
require('/js/sources/application.js', done);
});
suiteTeardown(function() {
navigator.mozApps = realMozApps;
MockNavigatormozApps.mTeardown();
});
setup(function() {
loadBodyHTML('/index.html');
subject = new ApplicationSource(new ItemStore());
});
test('synchronize removes app', function() {
var removeStub = this.sinon.stub(subject, 'removeIconFromGrid');
subject.store._allItems = [
new GaiaGrid.Mozapp({
manifestURL: 'mozilla'
}),
new GaiaGrid.Mozapp({
manifestURL: 'removeme'
})
];
subject.synchronize();
assert.ok(removeStub.calledTwice);
});
});

View file

@ -0,0 +1,138 @@
'use strict';
/* global MocksHelper, MockIndexedDB, ItemStore, configurator */
require('/shared/js/l10n.js');
require('/shared/test/unit/mocks/mock_indexedDB.js');
require('/test/unit/mock_application_source.js');
require('/test/unit/mock_bookmark_source.js');
require('/test/unit/mock_configurator.js');
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
require('/shared/elements/gaia_grid/script.js');
require('/shared/elements/gaia_grid/js/items/grid_item.js');
require('/shared/elements/gaia_grid/js/items/divider.js');
require('/shared/elements/gaia_grid/js/items/mozapp.js');
// Unit tests for item library
requireApp('verticalhome/js/stores/item.js');
var mocksHelperForItemStore = new MocksHelper([
'ApplicationSource',
'BookmarkSource'
]).init();
suite('item.js >', function() {
var mockIndexedDB;
var realSetMessageHandler;
var dataStoreItems = {
'0': {
'type': 'app',
'manifestURL': 'app://gallery.gaiamobile.org/manifest.webapp',
'index': 0
},
'1': {
'type': 'app',
'manifestURL': 'app://clock.gaiamobile.org/manifest.webapp',
'index': 1
},
'2': {
'type': 'app',
'manifestURL': 'app://keyboard.gaiamobile.org/manifest.webapp',
'index': 2
},
'3': {
'type': 'app',
'manifestURL': 'app://camera.gaiamobile.org/manifest.webapp',
'index': 3
},
'4': {
'type': 'app',
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp',
'index': 4
},
'5': {
'type': 'app',
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp',
'index': 5
},
'6': {
'type': 'app',
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp',
'index': 6
},
'7': {
'type': 'app',
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
'entryPoint': 'contacts',
'index': 7
},
'8': {
'type': 'app',
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
'entryPoint': 'dialer',
'index': 8
}
};
mocksHelperForItemStore.attachTestHelpers();
suiteSetup(function() {
mockIndexedDB = new MockIndexedDB();
mocksHelperForItemStore.suiteSetup();
});
suiteTeardown(function() {
mocksHelperForItemStore.suiteTeardown();
});
setup(function() {
mocksHelperForItemStore.setup();
realSetMessageHandler = navigator.mozSetMessageHandler;
navigator.mozSetMessageHandler = () => {};
});
teardown(function() {
mocksHelperForItemStore.teardown();
navigator.mozSetMessageHandler = realSetMessageHandler;
});
test('ItemStore new >', function() {
mockIndexedDB.options.upgradeNeededDbs = ['verticalhome'];
mockIndexedDB.storedDataDbs = {
'verticalhome': dataStoreItems
};
/*jshint unused:false*/
var itemStore = new ItemStore();
window.dispatchEvent(new CustomEvent('configuration-ready'));
window.dispatchEvent(new CustomEvent('gaiagrid-cached-icons-rendered'));
var savedElem = mockIndexedDB.dbs[0].receivedData;
var grid = configurator.getGrid();
var gridInd = 0;
var keys = Object.keys(savedElem);
for (var i = 0, iLen = savedElem.length, gLen = grid.length;
i < iLen && gridInd < gLen; i++) {
if (savedElem[i].type === 'app') {
assert.equal(savedElem[i].manifestURL, grid[gridInd][0].manifestURL);
if (savedElem[i].entryPoint) {
assert.equal(savedElem[i].entryPoint, grid[gridInd][0].entry_point);
}
grid[gridInd].shift();
} else if (savedElem[i].type === 'divider') {
gridInd += 1;
}
}
var moreDivider = false;
for (;i < iLen && !moreDivider; i++) {
moreDivider = savedElem[keys[i]].type === 'divider';
}
assert.isFalse(moreDivider);
for (i = 0, iLen = grid.length; i < iLen; i++) {
assert.equal(grid[i].length, 0);
}
});
});

View file

@ -0,0 +1,130 @@
'use strict';
/* global verticalPreferences, MockDatastore, MockNavigatorDatastore */
require('/shared/test/unit/mocks/mock_navigator_datastore.js');
require('/shared/js/homescreens/vertical_preferences.js');
suite('vertical_preferences.js >', function() {
var realDatastore = null,
gridCols = 'grid.cols',
cols = 3;
suiteSetup(function() {
realDatastore = navigator.getDataStores;
});
suiteTeardown(function() {
navigator.getDataStores = realDatastore;
});
setup(function() {
navigator.getDataStores = MockNavigatorDatastore.getDataStores;
});
teardown(function() {
MockDatastore._inError = false;
MockDatastore._records = Object.create(null);
});
test('testing not getDataStores defined >', function(done) {
navigator.getDataStores = undefined;
verticalPreferences.get(gridCols).then(function(value) {
// Do noting
}, function(e) {
assert.equal(e.name, 'NO_DATASTORE');
done();
});
});
test('testing no access to datastore >', function(done) {
navigator.getDataStores = function() {
return {
then: function(resolve, reject) {
resolve({
length: 0
});
}
};
};
verticalPreferences.get(gridCols).then(function(value) {
// Do noting
}, function(e) {
assert.equal(e.name, 'NO_ACCESS_TO_DATASTORE');
done();
});
});
test('calling to put method - added >', function(done) {
verticalPreferences.put(gridCols, cols).then(done);
});
test('calling to put method - failed >', function(done) {
MockDatastore._inError = true;
verticalPreferences.put(gridCols, cols).then(function() {
// Do nothing here
}, function() {
done();
});
});
test('calling to get method - OK >', function(done) {
verticalPreferences.put(gridCols, cols).then(function() {
verticalPreferences.get(gridCols).then(function(value) {
assert.equal(value, cols);
done();
});
});
});
test('calling to get method - failed >', function(done) {
MockDatastore._inError = true;
verticalPreferences.get(gridCols).then(function() {
// Do nothing here
}, function() {
done();
});
});
test('testing addEventListener for "updated" event >', function(done) {
verticalPreferences.addEventListener('updated', function onUpdated(event) {
verticalPreferences.removeEventListener('updated', onUpdated);
assert.equal(event.type, 'updated');
assert.equal(event.target.name, gridCols);
assert.equal(event.target.value, cols);
done();
});
verticalPreferences.put(gridCols, cols);
});
test('testing removeEventListener >', function(done) {
var onUpdated = function() {
done(new Error('The "updated" listener should NOT be called!!!'));
};
verticalPreferences.addEventListener('updated', onUpdated);
var ret = verticalPreferences.removeEventListener('updated', onUpdated);
assert.isTrue(ret);
verticalPreferences.put(gridCols, cols).then(function() {
done();
});
});
test('testing removeEventListener unknown type >', function() {
assert.isFalse(verticalPreferences.removeEventListener('dog', function() {
// Do nothing...
}));
});
test('testing removeEventListener unknown callback >', function() {
assert.isFalse(verticalPreferences.removeEventListener('updated',
function() {
// Do nothing...
}
));
});
});

View file

@ -0,0 +1,110 @@
'use strict';
/* global MocksHelper, MockMozActivity, MockNavigatorSettings, wallpaper */
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
require('/shared/test/unit/mocks/mock_moz_activity.js');
require('/js/wallpaper.js');
var mocksHelperForWallpaper = new MocksHelper([
'MozActivity'
]).init();
// A simple mock for shared/js/omadrm/fl.js so we don't have to
// create a more complicated settings mock than what we already have here.
// If I put this in suiteSetup, I get a test error for a leaking global.
window.ForwardLock = { getKey: function(f) { f(null); } };
mocksHelperForWallpaper.attachTestHelpers();
suite('wallpaper.js >', function() {
var realMozSettings, activitySub;
suiteSetup(function() {
activitySub = sinon.stub(window, 'MozActivity', function(info) {
MockMozActivity.calls.push(info);
MockMozActivity.instances.push(this);
});
realMozSettings = navigator.mozSettings;
navigator.mozSettings = MockNavigatorSettings;
});
suiteTeardown(function() {
activitySub.restore();
navigator.mozSettings = realMozSettings;
delete window.ForwardLock;
});
setup(function() {
wallpaper.change();
});
teardown(function() {
window.MockNavigatorSettings.mSettings['wallpaper.image'] = null;
});
function FakeBlob(data) {
return {
type: 'image/png',
data: data
};
}
function startMozActivity(methodName, blob) {
var instance = MockMozActivity.instances[0];
instance.result = {
blob: blob
};
instance[methodName]();
}
test('The MozActivity was initialized correctly ', function() {
// There is only one activity running
var activities = MockMozActivity.calls;
assert.equal(activities.length, 1);
var instances = MockMozActivity.instances;
assert.equal(instances.length, 1);
// Activity data
var activity = activities[0];
assert.equal(activity.name, 'pick');
assert.ok(activity.data.type === 'wallpaper' ||
(Array.isArray(activity.data.type) &&
activity.data.type.indexOf('wallpaper') >= 0),
'activity type is or includes "wallpaper"');
// Activity callbacks
assert.isFunction(instances[0].onsuccess);
});
test('Pick activity returns a blob ', function() {
var fakeblob = FakeBlob('banana');
// This is the blob returned by the activity
startMozActivity('onsuccess', fakeblob);
// We set the wallpaper.image property to "banana"
assert.deepEqual(window.MockNavigatorSettings.mSettings['wallpaper.image'],
fakeblob);
});
test('Pick activity returns nothing (no blob) ', function() {
// MozActivity doesn't return a blob
startMozActivity('onsuccess');
// No blob then wallpaper.image property is not defined
assert.isNull(window.MockNavigatorSettings.mSettings['wallpaper.image']);
});
test('Pick activity has been cancelled ', function() {
// User cancels
startMozActivity('onerror');
// Then wallpaper.image property is not defined
assert.isNull(window.MockNavigatorSettings.mSettings['wallpaper.image']);
});
});