VulpesOS/gaia/apps/system/test/unit/base_module_test.js
OverSu b38dea0597 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.
2026-09-30 23:13:03 +02:00

747 lines
26 KiB
JavaScript
Executable file

/* global BaseModule, MocksHelper, MockService, MockLazyLoader, MockPromise,
Deferred */
'use strict';
require('/shared/test/unit/mocks/mock_service.js');
require('/shared/test/unit/mocks/mock_promise.js');
require('/shared/test/unit/mocks/mock_lazy_loader.js');
requireApp('system/test/unit/deferred.js');
var mocksForBaseModule = new MocksHelper([
'LazyLoader', 'Service'
]).init();
suite('system/BaseModule', function() {
mocksForBaseModule.attachTestHelpers();
setup(function(done) {
requireApp('system/js/base_module.js', done);
});
test('lowercase capital', function() {
assert.equal('appWindowManager',
BaseModule.lowerCapital('AppWindowManager'));
});
test('parse module path', function() {
var module = BaseModule.parsePath('path/to/ModuleName');
assert.equal(module.path, 'path/to/');
assert.equal(module.name, 'ModuleName');
});
test('object name to file name', function() {
assert.deepEqual('/js/app_window_manager.js',
BaseModule.object2fileName('AppWindowManager'));
assert.deepEqual('/js/path/to/module_name.js',
BaseModule.object2fileName('path/to/ModuleName'));
});
test('lazy load from an array of submodule strings', function(done) {
var stubLoad = this.sinon.stub(MockLazyLoader, 'load');
BaseModule.lazyLoad(['AppWindowManager']).then(function() {
done();
});
assert.isTrue(stubLoad.calledWith(['/js/app_window_manager.js']));
stubLoad.yield();
});
suite('Launching promise', function() {
test('start should resolve right away', function(done) {
var LaunchingPromiseTester = function() {};
BaseModule.create(LaunchingPromiseTester, {
name: 'LaunchingPromiseTester'
});
var lpt = BaseModule.instantiate('LaunchingPromiseTester');
lpt.start().catch((e) => {throw e || 'Should not throw'; })
.then(done, done);
});
test('custom start', function(done) {
var LaunchingPromiseTester = function() {};
BaseModule.create(LaunchingPromiseTester, {
name: 'LaunchingPromiseTester',
_start: function() {
return new Promise(function(resolve) {
resolve();
});
}
});
var lpt = BaseModule.instantiate('LaunchingPromiseTester');
lpt.start().catch((e) => {throw e || 'Should not throw'; })
.then(done, done);
});
});
suite('BaseModule.instantiate', function() {
test('Get a new instance if the module is available', function() {
var InstantiationTester = function() {};
BaseModule.create(InstantiationTester, {
name: 'InstantiationTester'
});
assert.isDefined(BaseModule.instantiate('InstantiationTester'));
assert.equal(BaseModule.instantiate('InstantiationTester').name,
'InstantiationTester');
});
test('Get undefined if the module is unavailable', function() {
assert.isUndefined(BaseModule.instantiate('NoSuchModule'));
});
});
suite('Centralized settins observer', function() {
var fakeAppWindowManager, settings;
setup(function() {
var FakeAppWindowManager = function() {};
FakeAppWindowManager.SETTINGS = ['app-suspending.enabled'];
BaseModule.create(FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
settings = {
'app-suspending.enabled': true
};
fakeAppWindowManager = new FakeAppWindowManager();
});
teardown(function() {
fakeAppWindowManager.stop();
});
test('addObserver will be called if SETTINGS is specified', function(done) {
var spy = this.sinon.stub(fakeAppWindowManager, 'observe');
this.sinon.stub(MockService, 'request',
function(service, name, consumer) {
if (service === 'SettingsCore:addObserver') {
assert.equal(name, 'app-suspending.enabled');
assert.deepEqual(consumer, fakeAppWindowManager);
consumer.observe(name, settings[name]);
assert.isTrue(spy.calledWith('app-suspending.enabled', true));
done();
}
});
fakeAppWindowManager.start();
});
test('get settings', function(done) {
this.sinon.stub(MockService, 'request').returns(
new Promise(function(resolve) {
resolve(new Promise(function(iresolve) {
iresolve(true);
}));
}));
fakeAppWindowManager.readSetting('app-suspending.enabled')
.then(function(value) {
assert.equal(value, true);
done();
});
});
test('set settings', function(done) {
this.sinon.stub(MockService, 'request',
function(service, object) {
for (var key in object) {
settings[key] = object[key];
}
assert.equal(settings['app-suspending.enabled'], false);
done();
});
fakeAppWindowManager.writeSetting({'app-suspending.enabled': false});
});
test('settings relation function will not be injected if not specified',
function() {
var fakeAppWindowManager2;
var FakeAppWindowManager2 = function() {};
BaseModule.create(FakeAppWindowManager2, {
name: 'FakeAppWindowManager2'
});
fakeAppWindowManager2 = new FakeAppWindowManager2();
assert.isUndefined(fakeAppWindowManager2.observe);
assert.isUndefined(fakeAppWindowManager2._observeSettings);
assert.isUndefined(fakeAppWindowManager2._unobserveSettings);
});
});
suite('Centralized event handler', function() {
var fakeAppWindowManager;
setup(function() {
var FakeAppWindowManager = function() {};
FakeAppWindowManager.EVENTS = ['ftuskip'];
BaseModule.create(FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
fakeAppWindowManager = new FakeAppWindowManager();
});
teardown(function() {
fakeAppWindowManager.stop();
});
test('handleEvent should be called when registering events', function() {
var stubHandleEvent =
this.sinon.stub(fakeAppWindowManager, 'handleEvent');
window.dispatchEvent(new CustomEvent('ftuskip'));
assert.isFalse(stubHandleEvent.called);
fakeAppWindowManager.start();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isTrue(stubHandleEvent.calledWith(ftuskipEvent));
});
test('specific handler should be called if it exists', function() {
var stubHandleFtuskip =
fakeAppWindowManager._handle_ftuskip = this.sinon.spy();
window.dispatchEvent(new CustomEvent('ftuskip'));
assert.isFalse(stubHandleFtuskip.called);
fakeAppWindowManager.start();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isTrue(stubHandleFtuskip.calledWith(ftuskipEvent));
});
test('pre handler should be called if it exists', function() {
var spy = fakeAppWindowManager._handle_ftuskip = this.sinon.spy();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isFalse(spy.called);
fakeAppWindowManager.start();
window.dispatchEvent(ftuskipEvent);
assert.isTrue(spy.calledWith(ftuskipEvent));
});
test('pre handler should be called if it exists', function() {
var spy = fakeAppWindowManager._pre_handleEvent = this.sinon.spy();
var spyFtuskip = fakeAppWindowManager._handle_ftuskip = this.sinon.spy();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isFalse(spy.called);
assert.isFalse(spyFtuskip.called);
fakeAppWindowManager.start();
window.dispatchEvent(ftuskipEvent);
assert.isTrue(spy.calledWith(ftuskipEvent));
assert.isTrue(spyFtuskip.calledWith(ftuskipEvent));
});
test('specific event handler should be not called ' +
'if pre handler returns false', function() {
fakeAppWindowManager._pre_handleEvent = function() {};
var spy = this.sinon.stub(fakeAppWindowManager,
'_pre_handleEvent').returns(false);
var spyFtuskip = fakeAppWindowManager._handle_ftuskip = this.sinon.spy();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isFalse(spy.called);
assert.isFalse(spyFtuskip.called);
fakeAppWindowManager.start();
window.dispatchEvent(ftuskipEvent);
assert.isTrue(spy.calledWith(ftuskipEvent));
assert.isFalse(spyFtuskip.calledWith(ftuskipEvent));
});
test('post handler should be called if it exists', function() {
var spy = fakeAppWindowManager._post_handleEvent = this.sinon.spy();
var ftuskipEvent = new CustomEvent('ftuskip');
window.dispatchEvent(ftuskipEvent);
assert.isFalse(spy.called);
fakeAppWindowManager.start();
window.dispatchEvent(ftuskipEvent);
assert.isTrue(spy.calledWith(ftuskipEvent));
});
test('event relation function will not be injected if not specified',
function() {
var FakeAppWindowManager2 = function() {};
BaseModule.create(FakeAppWindowManager2, {
name: 'FakeAppWindowManager2'
});
var fakeAppWindowManager2 = new FakeAppWindowManager2();
assert.isUndefined(fakeAppWindowManager2.handleEvent);
assert.isUndefined(fakeAppWindowManager2._pre_handleEvent);
assert.isUndefined(fakeAppWindowManager2._post_handleEvent);
assert.isUndefined(fakeAppWindowManager2._subscribeEvents);
assert.isUndefined(fakeAppWindowManager2._unsubscribeEvents);
});
});
suite('Submodule management', function() {
var fakeAppWindowManager, fakePromise;
setup(function() {
BaseModule.__clearDefined();
});
suite('Already defined submodules with array SUB_MODULES', function() {
setup(function() {
fakePromise = new MockPromise();
this.sinon.stub(BaseModule, 'lazyLoad', function() {
return fakePromise;
});
window.FakeAppWindowManager = function() {};
window.FakeAppWindowManager.SUB_MODULES = ['FakeTaskManager'];
BaseModule.create(window.FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
fakeAppWindowManager = new window.FakeAppWindowManager();
fakeAppWindowManager.start();
});
test('submodule should be not loaded', function() {
fakeAppWindowManager._fakeTaskManager_loaded = this.sinon.spy();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isFalse(fakeAppWindowManager._fakeTaskManager_loaded.called);
});
});
suite('Already defined submodules with object SUB_MODULES', function() {
setup(function() {
fakePromise = new MockPromise();
this.sinon.stub(BaseModule, 'lazyLoad', function() {
return fakePromise;
});
window.FakeAppWindowManager = function() {};
window.FakeAppWindowManager.SUB_MODULES = {
default: ['FakeTaskManager']
};
BaseModule.create(window.FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
fakeAppWindowManager = new window.FakeAppWindowManager();
fakeAppWindowManager.start();
});
test('submodule should be not loaded', function() {
fakeAppWindowManager._fakeTaskManager_loaded = this.sinon.spy();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isFalse(fakeAppWindowManager._fakeTaskManager_loaded.called);
});
});
suite('Not defined submodules with array SUB_MODULES', function() {
setup(function() {
fakePromise = new MockPromise();
this.sinon.stub(BaseModule, 'lazyLoad', function() {
return fakePromise;
});
window.FakeAppWindowManager = function() {};
window.FakeAppWindowManager.SUB_MODULES = [
'FakeTaskManager',
'path/to/FakeSubModuleInDir'
];
BaseModule.create(window.FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
window.FakeTaskManager = null;
window.FakeSubModuleInDir = null;
fakeAppWindowManager = new window.FakeAppWindowManager();
fakeAppWindowManager.start();
});
teardown(function() {
fakeAppWindowManager.stop();
window.FakeTaskManager = null;
window.FakeAppWindowManager = null;
window.FakeSubModuleInDir = null;
});
test('submodule should be loaded', function() {
var spy = fakeAppWindowManager._fakeTaskManager_loaded =
this.sinon.spy();
var spy2 = fakeAppWindowManager._fakeSubModuleInDir_loaded =
this.sinon.spy();
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
window.FakeSubModuleInDir = function() {};
BaseModule.create(window.FakeSubModuleInDir, {
name: 'FakeSubModuleInDir'
});
fakePromise.mFulfillToValue();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isTrue(spy.called);
assert.isDefined(fakeAppWindowManager.fakeSubModuleInDir);
assert.isTrue(spy2.called);
});
test('submodule loaded handler should be called if it exists',
function() {
var spy = fakeAppWindowManager._fakeTaskManager_loaded =
this.sinon.spy();
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
fakePromise.mFulfillToValue();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isTrue(spy.called);
});
test('submodule should be started once parent is started', function() {
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
var spyStart = this.sinon.stub(window.FakeTaskManager.prototype,
'start');
fakePromise.mFulfillToValue();
assert.isTrue(spyStart.called);
});
test('submodule should be stopped once parent is stopped', function() {
window.FakeTaskManager = function() {};
window.FakeSubModuleInDir = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
BaseModule.create(window.FakeSubModuleInDir, {
name: 'FakeSubModuleInDir'
});
fakePromise.mFulfillToValue();
var spyStop =
this.sinon.stub(fakeAppWindowManager.fakeTaskManager, 'stop');
var spyStop2 =
this.sinon.stub(fakeAppWindowManager.fakeSubModuleInDir, 'stop');
fakeAppWindowManager.stop();
assert.isTrue(spyStop.called);
assert.isTrue(spyStop2.called);
});
test('submodule should not be started if the parent is already stopped',
function() {
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
var spyStart =
this.sinon.stub(window.FakeTaskManager.prototype, 'start');
fakeAppWindowManager.stop();
fakePromise.mFulfillToValue();
assert.isFalse(spyStart.called);
});
});
suite('Not defined submodules with object SUB_MODULES', function() {
setup(function() {
fakePromise = new MockPromise();
this.sinon.stub(BaseModule, 'lazyLoad', function() {
return fakePromise;
});
window.FakeAppWindowManager = function() {};
window.FakeAppWindowManager.SUB_MODULES = {
default: ['FakeTaskManager'],
_GAIA_DEVICE_TYPE_: ['path/to/FakeSubModuleInDir']
};
BaseModule.create(window.FakeAppWindowManager, {
name: 'FakeAppWindowManager'
});
window.FakeTaskManager = null;
window.FakeSubModuleInDir = null;
fakeAppWindowManager = new window.FakeAppWindowManager();
fakeAppWindowManager.start();
});
teardown(function() {
fakeAppWindowManager.stop();
window.FakeTaskManager = null;
window.FakeAppWindowManager = null;
window.FakeSubModuleInDir = null;
});
test('submodule should be loaded', function() {
var spy = fakeAppWindowManager._fakeTaskManager_loaded =
this.sinon.spy();
var spy2 = fakeAppWindowManager._fakeSubModuleInDir_loaded =
this.sinon.spy();
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
window.FakeSubModuleInDir = function() {};
BaseModule.create(window.FakeSubModuleInDir, {
name: 'FakeSubModuleInDir'
});
fakePromise.mFulfillToValue();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isTrue(spy.called);
assert.isDefined(fakeAppWindowManager.fakeSubModuleInDir);
assert.isTrue(spy2.called);
});
test('submodule loaded handler should be called if it exists',
function() {
var spy = fakeAppWindowManager._fakeTaskManager_loaded =
this.sinon.spy();
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
fakePromise.mFulfillToValue();
assert.isDefined(fakeAppWindowManager.fakeTaskManager);
assert.isTrue(spy.called);
});
test('submodule should be started once parent is started', function() {
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
var spyStart = this.sinon.stub(window.FakeTaskManager.prototype,
'start');
fakePromise.mFulfillToValue();
assert.isTrue(spyStart.called);
});
test('submodule should be stopped once parent is stopped', function() {
window.FakeTaskManager = function() {};
window.FakeSubModuleInDir = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
BaseModule.create(window.FakeSubModuleInDir, {
name: 'FakeSubModuleInDir'
});
fakePromise.mFulfillToValue();
var spyStop =
this.sinon.stub(fakeAppWindowManager.fakeTaskManager, 'stop');
var spyStop2 =
this.sinon.stub(fakeAppWindowManager.fakeSubModuleInDir, 'stop');
fakeAppWindowManager.stop();
assert.isTrue(spyStop.called);
assert.isTrue(spyStop2.called);
});
test('submodule should not be started if the parent is already stopped',
function() {
window.FakeTaskManager = function() {};
BaseModule.create(window.FakeTaskManager, {
name: 'FakeTaskManager'
});
var spyStart =
this.sinon.stub(window.FakeTaskManager.prototype, 'start');
fakeAppWindowManager.stop();
fakePromise.mFulfillToValue();
assert.isFalse(spyStart.called);
});
});
});
suite('Service registration', function() {
var fakeAppWindowManager;
setup(function() {
var FakeAppWindowManager = function() {};
FakeAppWindowManager.SERVICES = ['isBusyLoading'];
BaseModule.create(FakeAppWindowManager, {
name: 'FakeAppWindowManager',
isBusyLoading: function() {}
});
fakeAppWindowManager = new FakeAppWindowManager();
fakeAppWindowManager.start();
});
teardown(function() {
fakeAppWindowManager.stop();
});
test('register/unregister functions should be injected', function() {
assert.isDefined(fakeAppWindowManager._registerServices);
assert.isDefined(fakeAppWindowManager._unregisterServices);
});
test('Should register service to System when starting', function() {
fakeAppWindowManager.stop();
var stubRegister = this.sinon.stub(MockService, 'register');
fakeAppWindowManager.start();
assert.isTrue(stubRegister.calledWith('isBusyLoading',
fakeAppWindowManager));
});
test('Should unregister service to System when stopping', function() {
var stubRegister = this.sinon.stub(MockService, 'unregister');
fakeAppWindowManager.stop();
assert.isTrue(stubRegister.calledWith('isBusyLoading',
fakeAppWindowManager));
});
test('Should not inject service registration functions', function() {
var FakeAppWindowManager2 = function() {};
BaseModule.create(FakeAppWindowManager2, {
name: 'FakeAppWindowManager2',
isBusyLoading: function() {}
});
var fakeAppWindowManager2 = new FakeAppWindowManager2();
assert.isUndefined(fakeAppWindowManager2._registerServices);
assert.isUndefined(fakeAppWindowManager2._unregisterServices);
});
});
suite('State registration', function() {
var fakeFtuLauncher;
setup(function() {
var FakeFtuLauncher = function() {};
FakeFtuLauncher.STATES = ['isUpgrading'];
BaseModule.create(FakeFtuLauncher, {
_upgrading: false,
name: 'FakeFtuLauncher',
isUpgrading: function() {
return this._upgrading;
}
});
fakeFtuLauncher = new FakeFtuLauncher();
fakeFtuLauncher.start();
});
teardown(function() {
fakeFtuLauncher.stop();
});
test('Should register service to System when starting', function() {
fakeFtuLauncher.stop();
var stubRegister = this.sinon.stub(MockService, 'registerState');
fakeFtuLauncher.start();
assert.isTrue(stubRegister.calledWith('isUpgrading',
fakeFtuLauncher));
});
test('Should unregister service to System when stopping', function() {
var stubRegister = this.sinon.stub(MockService, 'unregisterState');
fakeFtuLauncher.stop();
assert.isTrue(stubRegister.calledWith('isUpgrading',
fakeFtuLauncher));
});
test('Should not inject service registration functions', function() {
var FakeFtuLauncher2 = function() {};
BaseModule.create(FakeFtuLauncher2, {
name: 'FakeFtuLauncher2',
isUpgrading: function() {}
});
var fakeFtuLauncher2 = new FakeFtuLauncher2();
this.sinon.stub(MockService, 'registerState');
this.sinon.stub(MockService, 'unregisterState');
fakeFtuLauncher2.start();
assert.isFalse(MockService.registerState.called);
fakeFtuLauncher2.stop();
assert.isFalse(MockService.unregisterState.called);
});
});
suite('Start chain', function() {
var chainTester;
var chainTester_startDeferred, cModule_startDeferred;
setup(function() {
chainTester_startDeferred = new Deferred();
cModule_startDeferred = new Deferred();
var ChainTester = function() {};
var CModule = function() {};
BaseModule.create(CModule, {
name: 'CModule',
DEBUG: true,
_start: sinon.spy(function() {
return cModule_startDeferred.promise;
})
});
ChainTester.SUB_MODULES = ['CModule'];
BaseModule.create(ChainTester, {
name: 'ChainTester',
DEBUG: true,
_start: sinon.spy(function() {
return chainTester_startDeferred.promise;
})
});
chainTester = new ChainTester();
});
test('Should wait until child start', function(done) {
var p = chainTester.start();
assert.isTrue(chainTester._start.calledOnce);
assert.isTrue(chainTester.cModule._start.calledOnce);
p.then(done, done);
chainTester_startDeferred.resolve();
cModule_startDeferred.resolve();
});
});
suite('Import', function() {
var importTester;
setup(function() {
var ImportTester = function() {};
ImportTester.IMPORTS = ['BModule', 'CModule'];
BaseModule.create(ImportTester, {
name: 'ImportTester',
_start: function() {}
});
importTester = new ImportTester();
});
teardown(function() {
importTester.stop();
});
test('Module start will be executed until import loaded', function() {
var p = new MockPromise();
this.sinon.stub(MockLazyLoader, 'load', function() {
return p;
});
var stubCustomStart = this.sinon.stub(importTester, '_start');
importTester.start();
assert.isFalse(stubCustomStart.called);
p.mFulfillToValue();
assert.isTrue(stubCustomStart.called);
});
});
suite('Module life cycle control', function() {
var lifeCycleTester;
setup(function() {
var LifeCycleTester = function() {};
BaseModule.create(LifeCycleTester, {
name: 'LifeCycleTester',
_start: function() {},
_stop: function() {}
});
lifeCycleTester = new LifeCycleTester();
});
teardown(function() {
lifeCycleTester.stop();
});
test('custom start should be triggered', function() {
var spy = this.sinon.stub(lifeCycleTester, '_start');
lifeCycleTester.start();
assert.isTrue(spy.calledOnce);
});
test('custom start will not execute if already started', function() {
lifeCycleTester.start();
var spy = this.sinon.stub(lifeCycleTester, '_start');
lifeCycleTester.start();
assert.isFalse(spy.called);
});
test('custom stop should be triggered', function() {
var spy = this.sinon.stub(lifeCycleTester, '_stop');
lifeCycleTester.start();
lifeCycleTester.stop();
assert.isTrue(spy.calledOnce);
});
test('custom stop will not execute if already stopped', function() {
lifeCycleTester.start();
lifeCycleTester.stop();
var spy = this.sinon.stub(lifeCycleTester, '_stop');
lifeCycleTester.stop();
assert.isFalse(spy.called);
});
});
});