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/system/test/unit/.jshintrc
Executable file
17
gaia/apps/system/test/unit/.jshintrc
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"require",
|
||||
"requireApp",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
95
gaia/apps/system/test/unit/about_service_workers_proxy_test.js
Executable file
95
gaia/apps/system/test/unit/about_service_workers_proxy_test.js
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* global AboutServiceWorkersProxy */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/about_service_workers_proxy.js');
|
||||
requireApp('system/test/unit/mock_iac_handler.js');
|
||||
|
||||
var MockEventListener = {};
|
||||
function MockAddEventListener(event, listener) {
|
||||
MockEventListener[event] = listener;
|
||||
}
|
||||
|
||||
suite('system/AboutServiceWorkersProxy >', function() {
|
||||
var stubAddEventListener;
|
||||
|
||||
setup(function() {
|
||||
stubAddEventListener = this.sinon.stub(window, 'addEventListener',
|
||||
MockAddEventListener);
|
||||
AboutServiceWorkersProxy.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubAddEventListener.restore();
|
||||
});
|
||||
|
||||
suite('Initial state', function() {
|
||||
test('Integrity', function() {
|
||||
assert.isNotNull(AboutServiceWorkersProxy);
|
||||
});
|
||||
|
||||
test('Test event listeners', function() {
|
||||
// We should be listening for IAC messages
|
||||
assert.ok(MockEventListener['iac-about-service-workers']);
|
||||
assert.ok(
|
||||
MockEventListener['iac-about-service-workers'] instanceof Function);
|
||||
// But not for chrome events yet.
|
||||
assert.isUndefined(MockEventListener.mozAboutServiceWorkersChromeEvent);
|
||||
});
|
||||
});
|
||||
|
||||
suite('On known IAC message', function() {
|
||||
var dispatchEventStub;
|
||||
|
||||
setup(function() {
|
||||
dispatchEventStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
|
||||
AboutServiceWorkersProxy.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'init'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
dispatchEventStub.restore();
|
||||
});
|
||||
|
||||
test('We should send a content request', function() {
|
||||
sinon.assert.calledOnce(dispatchEventStub);
|
||||
});
|
||||
|
||||
test('We should be listening for chrome events', function() {
|
||||
assert.ok(MockEventListener.mozAboutServiceWorkersChromeEvent);
|
||||
});
|
||||
});
|
||||
|
||||
suite('On unknown IAC message', function() {
|
||||
var dispatchEventStub;
|
||||
|
||||
setup(function() {
|
||||
dispatchEventStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
|
||||
AboutServiceWorkersProxy.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'whatever'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
dispatchEventStub.restore();
|
||||
});
|
||||
|
||||
test('We should send a content request', function() {
|
||||
sinon.assert.notCalled(dispatchEventStub);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
74
gaia/apps/system/test/unit/accessibility_quicknav_menu_test.js
Executable file
74
gaia/apps/system/test/unit/accessibility_quicknav_menu_test.js
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockLock, MockSettingsListener,
|
||||
AccessibilityQuicknavMenu */
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/js/accessibility_quicknav_menu.js');
|
||||
|
||||
var mocksForA11yQuicknavMenu = new MocksHelper([
|
||||
'SettingsListener'
|
||||
]).init();
|
||||
|
||||
suite('system/AccessibilityQuicknavMenu', function() {
|
||||
var screenNode;
|
||||
var quicknavMenu;
|
||||
mocksForA11yQuicknavMenu.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
screenNode = document.createElement('div');
|
||||
screenNode.id = 'screen';
|
||||
document.body.appendChild(screenNode);
|
||||
quicknavMenu = new AccessibilityQuicknavMenu();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
screenNode.parentNode.removeChild(screenNode);
|
||||
});
|
||||
|
||||
test('correct modes are available', function() {
|
||||
var modes = ['Link', 'Button', 'Landmark', 'FormControl'];
|
||||
MockSettingsListener.mCallbacks[
|
||||
'accessibility.screenreader_quicknav_modes'](modes.join(','));
|
||||
var items = quicknavMenu.element.querySelectorAll('li');
|
||||
assert.equal(items.length, 4);
|
||||
for (var i=0; i < items.length; i++) {
|
||||
var span = items[i].querySelector('span');
|
||||
assert.equal(span.dataset.l10nId, 'accessibility-quicknav_' + modes[i]);
|
||||
}
|
||||
});
|
||||
|
||||
test('correct mode is selected', function() {
|
||||
quicknavMenu.updateModes(['Link', 'Button', 'Landmark']);
|
||||
MockSettingsListener.mCallbacks[
|
||||
'accessibility.screenreader_quicknav_index'](1);
|
||||
var selected = quicknavMenu.element.querySelectorAll(
|
||||
'li[aria-selected=true]');
|
||||
assert.equal(selected.length, 1);
|
||||
assert.equal(selected[0].dataset.quicknavIndex, '1');
|
||||
});
|
||||
|
||||
test('select quicknavMenu mode', function() {
|
||||
quicknavMenu.updateModes(['Link', 'Button', 'Landmark']);
|
||||
quicknavMenu.show();
|
||||
|
||||
// Check that menu actually shows up.
|
||||
assert.isTrue(quicknavMenu.element.classList.contains('visible'));
|
||||
MockLock.clear();
|
||||
|
||||
// Click on the item with quicknavMenu index 2.
|
||||
var event = new MouseEvent('click', {
|
||||
'view': window,
|
||||
'bubbles': true,
|
||||
'cancelable': true
|
||||
});
|
||||
quicknavMenu.element.querySelector(
|
||||
'li[data-quicknav-index="2"]').dispatchEvent(event);
|
||||
|
||||
// Check that correct setting is set after click.
|
||||
assert.equal(
|
||||
MockLock.locks.shift()['accessibility.screenreader_quicknav_index'], 2);
|
||||
|
||||
// Check that menu goes away.
|
||||
assert.isFalse(quicknavMenu.element.classList.contains('visible'));
|
||||
});
|
||||
});
|
||||
599
gaia/apps/system/test/unit/accessibility_test.js
Executable file
599
gaia/apps/system/test/unit/accessibility_test.js
Executable file
|
|
@ -0,0 +1,599 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockSpeechSynthesis, MockSpeechSynthesisUtterance,
|
||||
Accessibility, SettingsListener, MockL10n, Service,
|
||||
MockSettingsHelper */
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_helper.js');
|
||||
requireApp('system/test/unit/mock_speech_synthesis.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/js/accessibility.js');
|
||||
requireApp('system/js/accessibility_quicknav_menu.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForA11y = new MocksHelper([
|
||||
'SettingsListener',
|
||||
'SettingsHelper',
|
||||
'LazyLoader',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/Accessibility', function() {
|
||||
|
||||
var accessibility, speechSynthesizer, screenNode;
|
||||
|
||||
var vcChangeKeyDetails = {
|
||||
eventType: 'vc-change',
|
||||
options: { pattern: [40], isKey: true }
|
||||
};
|
||||
|
||||
var vcChangeNotKeyDetails = {
|
||||
eventType: 'vc-change',
|
||||
options: { pattern: [40], isKey: false }
|
||||
};
|
||||
|
||||
var vcChangeHintsEnabledDetails = {
|
||||
eventType: 'vc-change',
|
||||
data: [{string: 'link'}],
|
||||
options: {
|
||||
hints: [{string: 'link-hint'}]
|
||||
}
|
||||
};
|
||||
|
||||
var screenChangeScreenDisabledEvent = {
|
||||
type: 'screenchange',
|
||||
detail: {
|
||||
screenEnabled: false
|
||||
}
|
||||
};
|
||||
|
||||
var clickActionDetails = {
|
||||
eventType: 'action',
|
||||
data: [{ string: 'clickAction' }]
|
||||
};
|
||||
|
||||
var liveRegionDetails = {
|
||||
eventType: 'liveregion-change',
|
||||
data: [{'string': 'hidden'}, 'Hiding live region'],
|
||||
options: { enqueue: true }
|
||||
};
|
||||
|
||||
var quicknavShowDetails = {
|
||||
eventType: 'quicknav-menu'
|
||||
};
|
||||
|
||||
var fakeLogoHidden = {
|
||||
type: 'logohidden'
|
||||
};
|
||||
|
||||
var fakeFTUCommsStarted = {
|
||||
type: 'iac-ftucomms',
|
||||
detail: 'started',
|
||||
timeStamp: Date.now()
|
||||
};
|
||||
|
||||
var fakeFTUCommsStep = {
|
||||
type: 'iac-ftucomms',
|
||||
detail: { type: 'step', hash: '#foo' },
|
||||
timeStamp: Date.now()
|
||||
};
|
||||
|
||||
var fakeAppwillopen = {
|
||||
type: 'appwillopen'
|
||||
};
|
||||
|
||||
var fakeHomescreenopening = {
|
||||
type: 'homescreenopening'
|
||||
};
|
||||
|
||||
var fakeAppopened = {
|
||||
type: 'appopened',
|
||||
detail: { name: 'test-app' }
|
||||
};
|
||||
|
||||
var fakeHomescreenopened = {
|
||||
type: 'homescreenopened',
|
||||
detail: { name: 'homescreen-app' }
|
||||
};
|
||||
|
||||
function getAccessFuOutput(aDetails) {
|
||||
return {
|
||||
type: 'mozChromeEvent',
|
||||
detail: {
|
||||
type: 'accessibility-output',
|
||||
details: JSON.stringify(aDetails)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getAccessFuControl(aDetails) {
|
||||
return {
|
||||
type: 'mozChromeEvent',
|
||||
detail: {
|
||||
type: 'accessibility-control',
|
||||
details: JSON.stringify(aDetails)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getVolumeUp() {
|
||||
return {
|
||||
type: 'volumeup',
|
||||
timeStamp: Date.now() * 1000
|
||||
};
|
||||
}
|
||||
|
||||
function getVolumeDown() {
|
||||
return {
|
||||
type: 'volumedown',
|
||||
timeStamp: Date.now() * 1000
|
||||
};
|
||||
}
|
||||
|
||||
var fakeSentence = 'This is captions text';
|
||||
|
||||
var realL10n = navigator.mozL10n;
|
||||
|
||||
mocksForA11y.attachTestHelpers();
|
||||
setup(function() {
|
||||
screenNode = document.createElement('div');
|
||||
screenNode.id = 'screen';
|
||||
document.body.appendChild(screenNode);
|
||||
accessibility = new Accessibility();
|
||||
accessibility.start();
|
||||
speechSynthesizer = accessibility.speechSynthesizer;
|
||||
this.sinon.stub(speechSynthesizer, 'speech', MockSpeechSynthesis);
|
||||
this.sinon.stub(speechSynthesizer, 'utterance',
|
||||
MockSpeechSynthesisUtterance);
|
||||
MockSettingsHelper.instances['language.current'] = { value: 'en-US' };
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
screenNode.parentNode.removeChild(screenNode);
|
||||
});
|
||||
|
||||
test('logohidden handler', function() {
|
||||
var stubActivateScreen = this.sinon.stub(accessibility,
|
||||
'activateScreen');
|
||||
accessibility.handleEvent(fakeLogoHidden);
|
||||
assert.isTrue(stubActivateScreen.called);
|
||||
});
|
||||
|
||||
suite('ftu events', function() {
|
||||
test('ftucomms started handler', function() {
|
||||
var stubHandleFTUStarted = this.sinon.stub(accessibility,
|
||||
'handleFTUStarted');
|
||||
accessibility.handleEvent(fakeFTUCommsStarted);
|
||||
assert.isTrue(stubHandleFTUStarted.calledWith(fakeFTUCommsStarted));
|
||||
});
|
||||
|
||||
test('ftustep handler', function() {
|
||||
var stubHandleFTUStep = this.sinon.stub(accessibility, 'handleFTUStep');
|
||||
accessibility.handleEvent(fakeFTUCommsStep);
|
||||
assert.isTrue(stubHandleFTUStep.called);
|
||||
});
|
||||
|
||||
test('handleFTUStep', function() {
|
||||
var stubReset = this.sinon.stub(accessibility, 'reset');
|
||||
var stubCancelSpeech = this.sinon.stub(accessibility, 'cancelSpeech');
|
||||
var spyDisableFTUStartedTimeout = this.sinon.spy(accessibility,
|
||||
'disableFTUStartedTimeout');
|
||||
var stubRemoveEventListener = this.sinon.stub(window,
|
||||
'removeEventListener');
|
||||
accessibility.FTUStartedTimeout = {};
|
||||
|
||||
accessibility.handleFTUStep();
|
||||
|
||||
assert.ok(!accessibility.FTUStartedTimeout);
|
||||
assert.isTrue(stubReset.called);
|
||||
assert.isTrue(stubCancelSpeech.called);
|
||||
assert.isTrue(spyDisableFTUStartedTimeout.called);
|
||||
assert.isTrue(stubRemoveEventListener.calledWith('iac-ftucomms',
|
||||
accessibility));
|
||||
});
|
||||
|
||||
test('handleFTUStarted screen reader turned off', function(done) {
|
||||
var stubReset = this.sinon.stub(accessibility, 'reset');
|
||||
var stubCancelSpeech = this.sinon.stub(accessibility, 'cancelSpeech');
|
||||
var stubAnnounceScreenReader = this.sinon.stub(accessibility,
|
||||
'announceScreenReader').returns(Promise.resolve());
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', false);
|
||||
accessibility.FTU_STARTED_TIMEOUT = 0;
|
||||
|
||||
accessibility.handleFTUStarted();
|
||||
// Wait until the FTU_STARTED_TIMEOUT expires.
|
||||
setTimeout(() => {
|
||||
assert.isTrue(stubReset.called);
|
||||
assert.isTrue(stubCancelSpeech.called);
|
||||
assert.isTrue(stubAnnounceScreenReader.called);
|
||||
done();
|
||||
}, 10);
|
||||
});
|
||||
|
||||
test('handleFTUStarted screen reader turned on', function() {
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', true);
|
||||
// make sure the timeout starts false and stays false
|
||||
assert.ok(!this.FTUStartedTimeout);
|
||||
|
||||
accessibility.handleFTUStarted();
|
||||
assert.ok(!this.FTUStartedTimeout);
|
||||
// Turn the screen reader back off.
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', false);
|
||||
});
|
||||
});
|
||||
|
||||
suite('handle volume button events', function() {
|
||||
test('volume up handler', function() {
|
||||
var stubHandleVolumeButtonPress = this.sinon.stub(accessibility,
|
||||
'handleVolumeButtonPress');
|
||||
var volumeUp = getVolumeUp();
|
||||
accessibility.handleEvent(volumeUp);
|
||||
assert.isTrue(stubHandleVolumeButtonPress.called);
|
||||
assert.isTrue(stubHandleVolumeButtonPress.calledWith(volumeUp));
|
||||
});
|
||||
|
||||
test('volume down handler', function() {
|
||||
var stubHandleVolumeButtonPress = this.sinon.stub(accessibility,
|
||||
'handleVolumeButtonPress');
|
||||
var volumeDown = getVolumeDown();
|
||||
accessibility.handleEvent(volumeDown);
|
||||
assert.isTrue(stubHandleVolumeButtonPress.called);
|
||||
assert.isTrue(stubHandleVolumeButtonPress.calledWith(volumeDown));
|
||||
});
|
||||
|
||||
test('reset', function() {
|
||||
var stubReset = this.sinon.stub(accessibility, 'reset');
|
||||
accessibility.handleEvent(getVolumeDown());
|
||||
assert.isTrue(stubReset.called);
|
||||
});
|
||||
|
||||
test('announce screen reader', function() {
|
||||
var stubAnnounceScreenReader = this.sinon.stub(accessibility,
|
||||
'announceScreenReader').returns(Promise.resolve());
|
||||
var stubDisableFTUStartedTimeout = this.sinon.stub(accessibility,
|
||||
'disableFTUStartedTimeout');
|
||||
// Toggle volume up + volume down sequence three times.
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
accessibility.handleEvent(getVolumeUp());
|
||||
accessibility.handleEvent(getVolumeDown());
|
||||
}
|
||||
assert.isTrue(stubAnnounceScreenReader.called);
|
||||
assert.isTrue(stubDisableFTUStartedTimeout.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('speech captions', function() {
|
||||
test('no captions by default', function() {
|
||||
var stubShowSpeech = this.sinon.stub(speechSynthesizer,
|
||||
'showSpeech');
|
||||
var stubHideSpeech = this.sinon.stub(speechSynthesizer,
|
||||
'hideSpeech');
|
||||
speechSynthesizer.speak(fakeSentence, {});
|
||||
assert.isTrue(stubShowSpeech.notCalled);
|
||||
assert.isTrue(stubHideSpeech.notCalled);
|
||||
});
|
||||
|
||||
test('captions when accessibility.screenreader-captions is set',
|
||||
function() {
|
||||
var stubShowSpeech = this.sinon.stub(speechSynthesizer,
|
||||
'showSpeech');
|
||||
var stubHideSpeech = this.sinon.stub(speechSynthesizer,
|
||||
'hideSpeech');
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-captions', true);
|
||||
speechSynthesizer.speak(fakeSentence, {});
|
||||
assert.isTrue(stubShowSpeech.called);
|
||||
assert.isTrue(stubHideSpeech.called);
|
||||
});
|
||||
|
||||
test('showSpeech', function() {
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
assert.isUndefined(speechSynthesizer.captionsBox);
|
||||
speechSynthesizer.showSpeech(fakeSentence);
|
||||
assert.notEqual(speechSynthesizer.captionsBox, undefined);
|
||||
assert.equal(speechSynthesizer.captionsBox.id,
|
||||
'accessibility-captions-box');
|
||||
assert.equal(speechSynthesizer.captionsBox.getAttribute('aria-hidden'),
|
||||
'true');
|
||||
assert.equal(speechSynthesizer.captionsBox.getAttribute(
|
||||
'data-z-index-level'), 'accessibility-captions');
|
||||
assert.equal(speechSynthesizer.captionsBox.innerHTML, fakeSentence);
|
||||
assert.isTrue(speechSynthesizer.captionsBox.classList.contains(
|
||||
'visible'));
|
||||
});
|
||||
|
||||
test('hideSpeech', function() {
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
this.sinon.stub(window, 'setTimeout', function(callback) {
|
||||
callback();
|
||||
});
|
||||
speechSynthesizer.showSpeech(fakeSentence);
|
||||
assert.isTrue(speechSynthesizer.captionsBox.classList.contains(
|
||||
'visible'));
|
||||
speechSynthesizer.hideSpeech();
|
||||
assert.isFalse(speechSynthesizer.captionsBox.classList.contains(
|
||||
'visible'));
|
||||
});
|
||||
|
||||
test('hideSpeech immediately', function() {
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
speechSynthesizer.showSpeech(fakeSentence);
|
||||
assert.isTrue(speechSynthesizer.captionsBox.classList.contains(
|
||||
'visible'));
|
||||
speechSynthesizer.hideSpeech(true);
|
||||
assert.isFalse(speechSynthesizer.captionsBox.classList.contains(
|
||||
'visible'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('handle accessibility-output events', function() {
|
||||
var stubSpeak;
|
||||
setup(function() {
|
||||
stubSpeak = this.sinon.stub(accessibility, 'speak').returns(
|
||||
Promise.resolve());
|
||||
});
|
||||
test('handleAccessFuOutput', function() {
|
||||
var stubHandleAccessFuOutput = this.sinon.stub(accessibility,
|
||||
'handleAccessFuOutput');
|
||||
accessibility.handleEvent(getAccessFuOutput(vcChangeKeyDetails));
|
||||
assert.isTrue(stubHandleAccessFuOutput.called);
|
||||
assert.isTrue(stubHandleAccessFuOutput.calledWith(vcChangeKeyDetails));
|
||||
});
|
||||
|
||||
test('vc-change key event', function() {
|
||||
var stub_playSound = this.sinon.stub(accessibility,
|
||||
'_playSound');
|
||||
accessibility.handleEvent(getAccessFuOutput(vcChangeKeyDetails));
|
||||
assert.isTrue(stub_playSound.called);
|
||||
assert.isTrue(stub_playSound.calledWith('vcKeyAudio'));
|
||||
assert.isTrue(stubSpeak.called);
|
||||
});
|
||||
|
||||
test('vc-change not key event', function() {
|
||||
var stub_playSound = this.sinon.stub(accessibility,
|
||||
'_playSound');
|
||||
accessibility.handleEvent(getAccessFuOutput(vcChangeNotKeyDetails));
|
||||
assert.isTrue(stub_playSound.called);
|
||||
assert.isTrue(stub_playSound.calledWith('vcMoveAudio'));
|
||||
assert.isTrue(stubSpeak.called);
|
||||
});
|
||||
|
||||
test('action click event', function() {
|
||||
var stub_playSound = this.sinon.stub(accessibility,
|
||||
'_playSound');
|
||||
accessibility.handleEvent(getAccessFuOutput(clickActionDetails));
|
||||
assert.isTrue(stub_playSound.called);
|
||||
assert.isTrue(stub_playSound.calledWith('clickedAudio'));
|
||||
assert.isFalse(stubSpeak.called);
|
||||
});
|
||||
|
||||
test('liveregion change event', function() {
|
||||
var stub_playSound = this.sinon.stub(accessibility,
|
||||
'_playSound');
|
||||
accessibility.handleEvent(getAccessFuOutput(liveRegionDetails));
|
||||
assert.isFalse(stub_playSound.called);
|
||||
assert.isTrue(stubSpeak.called);
|
||||
assert.deepEqual(liveRegionDetails.data, stubSpeak.args[0][0]);
|
||||
assert.deepEqual(liveRegionDetails.options, stubSpeak.args[0][1]);
|
||||
});
|
||||
|
||||
test('no-move event', function() {
|
||||
var stub_playSound = this.sinon.stub(accessibility,
|
||||
'_playSound');
|
||||
accessibility.handleEvent(getAccessFuOutput({ eventType: 'no-move' }));
|
||||
assert.isTrue(stub_playSound.called);
|
||||
assert.isTrue(stub_playSound.calledWith('noMoveAudio'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('quicknav menu', function() {
|
||||
var screenNode;
|
||||
setup(function() {
|
||||
screenNode = document.createElement('div');
|
||||
screenNode.id = 'screen';
|
||||
document.body.appendChild(screenNode);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
screenNode.parentNode.removeChild(screenNode);
|
||||
});
|
||||
|
||||
test('handle show quicknav menu event', function() {
|
||||
var stubHandleAccessFuControl = this.sinon.stub(accessibility,
|
||||
'handleAccessFuControl');
|
||||
accessibility.handleEvent(getAccessFuControl(quicknavShowDetails));
|
||||
assert.isTrue(stubHandleAccessFuControl.called);
|
||||
assert.isTrue(stubHandleAccessFuControl.calledWith(quicknavShowDetails));
|
||||
});
|
||||
|
||||
test('show quicknav menu', function() {
|
||||
assert.isFalse(!!accessibility.quicknav);
|
||||
accessibility.handleAccessFuControl(quicknavShowDetails);
|
||||
assert.isTrue(!!accessibility.quicknav);
|
||||
assert.isTrue(
|
||||
accessibility.quicknav.element.classList.contains('visible'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('interaction hints', function() {
|
||||
test('handle vc change event with hints enabled', function(done) {
|
||||
var stubSetHintsTimeout = this.sinon.stub(accessibility,
|
||||
'setHintsTimeout');
|
||||
this.sinon.stub(accessibility, 'speak').returns(
|
||||
Promise.resolve());
|
||||
accessibility.handleAccessFuOutput(vcChangeHintsEnabledDetails);
|
||||
setTimeout(() => {
|
||||
assert.isTrue(stubSetHintsTimeout.called);
|
||||
assert.isTrue(stubSetHintsTimeout.calledWith(
|
||||
vcChangeHintsEnabledDetails.options.hints));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('make sure hints are canceled on screen off', function() {
|
||||
var stubCancelHints = this.sinon.stub(accessibility, 'cancelHints');
|
||||
accessibility.handleEvent(screenChangeScreenDisabledEvent);
|
||||
assert.isTrue(stubCancelHints.called);
|
||||
});
|
||||
|
||||
test('make sure hints are canceled with output/control event', function(){
|
||||
// Output event
|
||||
accessibility.isSpeakingHints = true;
|
||||
accessibility.handleAccessFuOutput(vcChangeHintsEnabledDetails);
|
||||
assert.isFalse(accessibility.isSpeakingHints);
|
||||
|
||||
// Control event
|
||||
accessibility.isSpeakingHints = true;
|
||||
accessibility.handleAccessFuControl({});
|
||||
assert.isFalse(accessibility.isSpeakingHints);
|
||||
});
|
||||
|
||||
suite('timeout based hint tests', function(){
|
||||
var clock;
|
||||
|
||||
setup(function() {
|
||||
clock = this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('make sure hints are spoken', function() {
|
||||
var stubSpeak = this.sinon.stub(accessibility, 'speak').returns(
|
||||
Promise.resolve());
|
||||
accessibility.setHintsTimeout(
|
||||
vcChangeHintsEnabledDetails.options.hints);
|
||||
clock.tick(accessibility.HINTS_TIMEOUT + 50);
|
||||
assert.isTrue(stubSpeak.called);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('screenreader shade', function() {
|
||||
test('turn shade on when screenreader is off', function() {
|
||||
var stubRequest = this.sinon.stub(Service, 'request');
|
||||
var stubSpeak = this.sinon.stub(accessibility, 'speak');
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', true);
|
||||
assert.isFalse(stubRequest.calledWith('turnShadeOn'));
|
||||
assert.isFalse(stubSpeak.called);
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', false);
|
||||
assert.isFalse(stubSpeak.called);
|
||||
});
|
||||
|
||||
test('turn shade on when screenreader is on', function() {
|
||||
var stubRequest = this.sinon.stub(Service, 'request');
|
||||
var stubSpeak = this.sinon.stub(accessibility, 'speak');
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader', true);
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', true);
|
||||
assert.isTrue(stubRequest.calledWith('turnShadeOn'));
|
||||
assert.isTrue(stubSpeak.called);
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', false);
|
||||
assert.isTrue(stubRequest.calledWith('turnShadeOff'));
|
||||
assert.isTrue(stubSpeak.calledTwice);
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader', false);
|
||||
});
|
||||
|
||||
test('turn screenreader on and off when shade is on', function() {
|
||||
var stubRequest = this.sinon.stub(Service, 'request');
|
||||
var stubSpeak = this.sinon.stub(accessibility, 'speak');
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', true);
|
||||
assert.isFalse(stubRequest.calledWith('turnShadeOn'));
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader', true);
|
||||
// If shade is on, it is announced after the screen reader turns on
|
||||
assert.isTrue(stubSpeak.calledOnce);
|
||||
assert.isTrue(stubRequest.calledWith('turnShadeOn'));
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader', false);
|
||||
assert.isTrue(stubRequest.calledWith('turnShadeOff'));
|
||||
SettingsListener.mTriggerCallback(
|
||||
'accessibility.screenreader-shade', false);
|
||||
// We should not get a speak if the screen reader is toggled off before
|
||||
// the shade
|
||||
assert.isTrue(stubSpeak.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('screenreader language support', function() {
|
||||
test('with unsupported language', function() {
|
||||
MockSettingsHelper.instances['language.current'] = { value: 'he-IL' };
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', true);
|
||||
assert.equal(MockSettingsHelper.instances['language.current'].value,
|
||||
'en-US');
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', false);
|
||||
});
|
||||
|
||||
test('with supported language in different locale', function() {
|
||||
MockSettingsHelper.instances['language.current'] = { value: 'en-GB' };
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', true);
|
||||
assert.equal(MockSettingsHelper.instances['language.current'].value,
|
||||
'en-GB');
|
||||
SettingsListener.mTriggerCallback('accessibility.screenreader', false);
|
||||
});
|
||||
});
|
||||
|
||||
suite('app related events', function() {
|
||||
test('appwillopen/homescreenopening', function() {
|
||||
var stubPrepareForApp = this.sinon.stub(accessibility, 'prepareForApp');
|
||||
accessibility.handleEvent(fakeAppwillopen);
|
||||
assert.isTrue(stubPrepareForApp.called);
|
||||
|
||||
stubPrepareForApp.reset();
|
||||
accessibility.handleEvent(fakeHomescreenopening);
|
||||
assert.isTrue(stubPrepareForApp.called);
|
||||
});
|
||||
|
||||
test('prepareForApp', function() {
|
||||
accessibility.appOpening = false;
|
||||
accessibility.prepareForApp();
|
||||
assert.isTrue(accessibility.appOpening);
|
||||
});
|
||||
|
||||
test('appopened/homescreenopened', function() {
|
||||
var stubAnnounceApp = this.sinon.stub(accessibility, 'announceApp');
|
||||
accessibility.handleEvent(fakeAppopened);
|
||||
assert.isTrue(stubAnnounceApp.called);
|
||||
assert.isTrue(stubAnnounceApp.calledWith(fakeAppopened.detail));
|
||||
|
||||
stubAnnounceApp.reset();
|
||||
accessibility.handleEvent(fakeHomescreenopened);
|
||||
assert.isTrue(stubAnnounceApp.called);
|
||||
assert.isTrue(stubAnnounceApp.calledWith(fakeHomescreenopened.detail));
|
||||
});
|
||||
|
||||
test('announceApp', function(done) {
|
||||
accessibility.appOpening = true;
|
||||
var stubSpeak = this.sinon.stub(accessibility, 'speak').returns(
|
||||
Promise.resolve());
|
||||
var stubHandleAccessFuOutput = this.sinon.stub(accessibility,
|
||||
'handleAccessFuOutput');
|
||||
var fakeLastVCChangeDetails = {test: 'test'};
|
||||
accessibility.lastVCChangeDetails = fakeLastVCChangeDetails;
|
||||
|
||||
accessibility.announceApp(fakeAppopened.detail);
|
||||
assert.isTrue(stubSpeak.calledWith(fakeAppopened.detail.name));
|
||||
setTimeout(() => {
|
||||
assert.isFalse(accessibility.appOpening);
|
||||
assert.isTrue(stubHandleAccessFuOutput.calledWith(
|
||||
fakeLastVCChangeDetails));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
160
gaia/apps/system/test/unit/action_menu_test.js
Executable file
160
gaia/apps/system/test/unit/action_menu_test.js
Executable file
|
|
@ -0,0 +1,160 @@
|
|||
'use strict';
|
||||
/* global ActionMenu, SystemDialog, MockL10n */
|
||||
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/system_dialog.js');
|
||||
requireApp('system/js/action_menu.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/js/event_safety.js');
|
||||
require('/shared/js/component_utils.js');
|
||||
require('/shared/elements/gaia_checkbox/script.js');
|
||||
|
||||
suite('ActionMenu', function() {
|
||||
var rafStub, realL10n, stubById, actionMenu, systemHideStub,
|
||||
controller, renderStub, publishStub, systemShowStub;
|
||||
|
||||
function getListItems(number) {
|
||||
var items = [];
|
||||
for (var i = 0; i < number; i++) {
|
||||
items.push({
|
||||
label: 'label' + i,
|
||||
icon: null,
|
||||
manifest: null,
|
||||
value: i
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
rafStub = this.sinon.stub(window, 'requestAnimationFrame',
|
||||
function(callback) { callback(); });
|
||||
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
ActionMenu.prototype.containerElement =
|
||||
document.createElement('div');
|
||||
|
||||
renderStub = this.sinon.stub(ActionMenu.prototype, 'render');
|
||||
publishStub = this.sinon.stub(ActionMenu.prototype, 'publish');
|
||||
systemShowStub = this.sinon.stub(SystemDialog.prototype, 'show');
|
||||
systemHideStub = this.sinon.stub(SystemDialog.prototype, 'hide');
|
||||
controller = {
|
||||
successCb: this.sinon.stub(),
|
||||
cancelCb: this.sinon.stub()
|
||||
};
|
||||
actionMenu = new ActionMenu(controller);
|
||||
actionMenu.element = document.createElement('div');
|
||||
actionMenu._fetchElements();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
suite('Instantation > ', function() {
|
||||
test('renders the view and publish created', function() {
|
||||
assert.isTrue(renderStub.called);
|
||||
assert.isTrue(publishStub.calledWith('created'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Show > ', function() {
|
||||
setup(function() {
|
||||
actionMenu.element = document.createElement('div');
|
||||
actionMenu._fetchElements();
|
||||
});
|
||||
|
||||
test('Calls to parent .show method', function() {
|
||||
actionMenu.show([]);
|
||||
assert.isTrue(systemShowStub.called);
|
||||
assert.isTrue(actionMenu.form.classList.contains('visible'));
|
||||
});
|
||||
|
||||
test('Renders the list of items and the cancel button', function() {
|
||||
var numberActions = 2;
|
||||
actionMenu.show(getListItems(numberActions));
|
||||
var menu = actionMenu.menu;
|
||||
var buttons = menu.getElementsByTagName('button');
|
||||
assert.isTrue(buttons.length === (numberActions + 1));
|
||||
assert.ok(buttons[numberActions].dataset.action === 'cancel');
|
||||
});
|
||||
|
||||
test('Renders the default option', function() {
|
||||
actionMenu.show(getListItems(1), 'title', true);
|
||||
|
||||
var input = actionMenu.menu.getElementsByTagName('input');
|
||||
assert.ok(input);
|
||||
});
|
||||
|
||||
test('Sets the title', function() {
|
||||
var title = 'title';
|
||||
actionMenu.show(getListItems(1), title);
|
||||
assert.isTrue(actionMenu.header.dataset.l10nId === title);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Hide > ', function() {
|
||||
|
||||
setup(function() {
|
||||
actionMenu.active = true;
|
||||
});
|
||||
|
||||
test('Should force position:fixed during the transition', function() {
|
||||
actionMenu.hide();
|
||||
assert.equal(actionMenu.form.style.position, 'fixed');
|
||||
var evt = new CustomEvent('transitionend');
|
||||
actionMenu.form.dispatchEvent(evt);
|
||||
assert.equal(actionMenu.form.style.position, '');
|
||||
});
|
||||
|
||||
test('Calls to parent .hide method after transition', function() {
|
||||
actionMenu.hide();
|
||||
var evt = new CustomEvent('transitionend');
|
||||
actionMenu.form.dispatchEvent(evt);
|
||||
assert.isTrue(systemHideStub.called);
|
||||
assert.isFalse(actionMenu.form.classList.contains('visible'));
|
||||
});
|
||||
|
||||
test('Does nothing if not active', function() {
|
||||
actionMenu.active = false;
|
||||
actionMenu.hide();
|
||||
var evt = new CustomEvent('transitionend');
|
||||
actionMenu.form.dispatchEvent(evt);
|
||||
assert.isFalse(systemHideStub.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Events > ', function() {
|
||||
test('calls to successCb on item click', function() {
|
||||
actionMenu.show(getListItems(2));
|
||||
var selected = 1;
|
||||
var items = actionMenu.menu.getElementsByTagName('button');
|
||||
items[selected].click();
|
||||
assert.isTrue(controller.successCb.calledWith(selected, false));
|
||||
});
|
||||
|
||||
test('calls to cancelCb on cancel click', function() {
|
||||
actionMenu.show(getListItems(2));
|
||||
var selected = 2;
|
||||
var items = actionMenu.menu.getElementsByTagName('button');
|
||||
items[selected].click();
|
||||
assert.isTrue(controller.cancelCb.called);
|
||||
});
|
||||
|
||||
test('sends the default checkbox value', function() {
|
||||
actionMenu.show(getListItems(2), '', true);
|
||||
var selected = 1;
|
||||
var items = actionMenu.menu.getElementsByTagName('button');
|
||||
var selector = '[data-action="set-default-action"]';
|
||||
var defaultInput = actionMenu.menu.querySelector(selector);
|
||||
defaultInput.checked = true;
|
||||
items[selected].click();
|
||||
assert.isTrue(controller.successCb.calledWith(selected, true));
|
||||
});
|
||||
});
|
||||
});
|
||||
530
gaia/apps/system/test/unit/activities_test.js
Executable file
530
gaia/apps/system/test/unit/activities_test.js
Executable file
|
|
@ -0,0 +1,530 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockApplications, MockL10n, MockDefaultActivityHelper,
|
||||
ActionMenu, BaseModule, DefaultActivityHelper, MockService
|
||||
*/
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_default_activity_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_action_menu.js');
|
||||
requireApp('system/shared/js/manifest_helper.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
|
||||
var mocksForActivities = new MocksHelper([
|
||||
'Applications',
|
||||
'LazyLoader',
|
||||
'ActionMenu'
|
||||
]).init();
|
||||
|
||||
suite('system/Activities', function() {
|
||||
var realL10n;
|
||||
var realDefaultActivityHelper;
|
||||
var subject;
|
||||
var realApplications;
|
||||
var realService;
|
||||
|
||||
var fakeLaunchConfig1 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://fakeapp1.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 1',
|
||||
'manifestURL': 'app://fakeapp1.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp1.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 1'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
mocksForActivities.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
realApplications = window.applications;
|
||||
realDefaultActivityHelper = window.DefaultActivityHelper;
|
||||
realService = window.Service;
|
||||
window.Service = MockService;
|
||||
window.applications = MockApplications;
|
||||
window.DefaultActivityHelper = MockDefaultActivityHelper;
|
||||
requireApp('system/js/activities.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
window.applications = realApplications;
|
||||
window.Service = realService;
|
||||
window.DefaultActivityHelper = realDefaultActivityHelper;
|
||||
realApplications = null;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
suite('constructor', function() {
|
||||
test('adds event listeners', function() {
|
||||
var expected = [];
|
||||
subject = BaseModule.instantiate('Activities');
|
||||
this.sinon.stub(subject, 'handleEvent', function(evt) {
|
||||
expected.push(evt.type);
|
||||
});
|
||||
subject.start();
|
||||
var events = {};
|
||||
var eventsToListen = [
|
||||
'mozChromeEvent',
|
||||
'appopened',
|
||||
'lockscreen-appopened',
|
||||
'applicationinstall'
|
||||
];
|
||||
|
||||
eventsToListen.forEach(function(name) {
|
||||
events[name] = new CustomEvent(name);
|
||||
window.dispatchEvent(events[name]);
|
||||
assert.isTrue(expected[expected.length - 1] === name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('handleEvent', function() {
|
||||
test('calls chooseActivity', function() {
|
||||
var stub = this.sinon.stub(subject, 'chooseActivity');
|
||||
var detail = {
|
||||
type: 'activity-choice'
|
||||
};
|
||||
subject.handleEvent({
|
||||
type: 'mozChromeEvent',
|
||||
detail: detail
|
||||
});
|
||||
assert.ok(stub.calledWith(detail));
|
||||
});
|
||||
|
||||
test('hides actionMenu on appopended if it exists', function() {
|
||||
this.sinon.stub(ActionMenu.prototype, 'hide');
|
||||
subject.actionMenu = new ActionMenu();
|
||||
subject.handleEvent({type: 'appopened'});
|
||||
assert.ok(ActionMenu.prototype.hide.calledOnce);
|
||||
});
|
||||
|
||||
test('cancel choice when locked', function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
this.sinon.stub(subject, 'cancel');
|
||||
subject.handleEvent({type: 'lockscreen-appopened'});
|
||||
assert.ok(subject.cancel.calledOnce);
|
||||
});
|
||||
|
||||
test('cancel choice when pressing home button', function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
this.sinon.stub(subject, 'cancel');
|
||||
subject.handleEvent({type: 'home'});
|
||||
assert.ok(subject.cancel.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('activity (multi)selection', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(DefaultActivityHelper, 'getDefaultAction')
|
||||
.returns({ // instead of Promise.resolve() to return in same cycle
|
||||
then: function(cb) { cb(null); }
|
||||
});
|
||||
});
|
||||
|
||||
test('choice when only one item', function() {
|
||||
var stub = this.sinon.stub(subject, 'choose', function(obj) {
|
||||
console.log('called with ' + obj);
|
||||
});
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
choices: ['first']
|
||||
});
|
||||
assert.ok(stub.calledWith('0'));
|
||||
});
|
||||
|
||||
test('opens action menu with multiple choice', function() {
|
||||
this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
choices: ['first', 'second']
|
||||
});
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(window.dispatchEvent.getCall(0).args[0].type,
|
||||
'activityrequesting');
|
||||
assert.equal(window.dispatchEvent.getCall(1).args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('only opens once if we get two activity-choice events', function() {
|
||||
subject.actionMenu = null;
|
||||
this.sinon.stub(ActionMenu.prototype, 'show', function() {
|
||||
subject.actionMenu.active = true;
|
||||
});
|
||||
var evt = {
|
||||
type: 'mozChromeEvent',
|
||||
detail: {
|
||||
type: 'activity-choice',
|
||||
choices: ['first', 'second']
|
||||
}
|
||||
};
|
||||
subject.handleEvent(evt);
|
||||
this.sinon.clock.tick();
|
||||
subject.handleEvent(evt);
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(ActionMenu.prototype.show.calledOnce);
|
||||
});
|
||||
|
||||
test('does not allow a choice that would subvert forward lock', function() {
|
||||
var stub = this.sinon.stub(subject, 'choose');
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://fl.example.com/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If it is a view activity and one of the choices is the FL app, we
|
||||
// must always choose the FL app.
|
||||
assert.ok(stub.calledWith('1'));
|
||||
// Ensure that we're not dispatching an activitymenuwillopen event
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(dispatchStub.calledOnce);
|
||||
assert.notEqual(dispatchStub.firstCall.args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('does not allow another choice that would subvert forward lock',
|
||||
function() {
|
||||
var stub = this.sinon.stub(subject, 'choose');
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://fl.example.com/e//fl.gaiamobile.org/' +
|
||||
'manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If it is a view activity and one of the choices is the FL app, we
|
||||
// must always choose the FL app.
|
||||
assert.ok(stub.calledWith('1'));
|
||||
// Ensure that we're not dispatching an activitymenuwillopen event
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(dispatchStub.calledOnce);
|
||||
assert.notEqual(dispatchStub.firstCall.args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('allows choice for non-forward lock view activities', function() {
|
||||
var stub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://video.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If this is a view activity without the FL app as one of the choices
|
||||
// we must allow the user to make a choice.
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(stub.firstCall.args[0].type, 'activityrequesting');
|
||||
assert.equal(stub.secondCall.args[0].type, 'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('allows choice for non-view activities that include FL', function() {
|
||||
var stub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If this is a not a view activity then we must allow the user to make
|
||||
// a choice even if the FL app is one of the choices.
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(stub.firstCall.args[0].type, 'activityrequesting');
|
||||
assert.equal(stub.secondCall.args[0].type, 'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('checks for default app on the list', function() {
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
});
|
||||
|
||||
test('if not on the list, ignore', function() {
|
||||
this.sinon.spy(subject, '_gotDefaultAction');
|
||||
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
assert.ok(subject._gotDefaultAction.calledWith(null));
|
||||
});
|
||||
|
||||
test('if on the list, check for default launch associated', function() {
|
||||
DefaultActivityHelper.getDefaultAction
|
||||
.returns({
|
||||
then: function(cb) { cb('fakeManifest'); }
|
||||
});
|
||||
this.sinon.spy(subject, '_gotDefaultAction');
|
||||
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
assert.ok(subject._gotDefaultAction.calledWith('fakeManifest'));
|
||||
});
|
||||
|
||||
suite('choosing an activity ', function() {
|
||||
var sendEvent,
|
||||
defaultAct,
|
||||
formatted;
|
||||
|
||||
setup(function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
|
||||
formatted = {
|
||||
id: 'foo',
|
||||
type: 'activity-choice',
|
||||
value: 0,
|
||||
setAsDefault: false
|
||||
};
|
||||
|
||||
sendEvent = this.sinon.stub(subject, '_sendEvent');
|
||||
defaultAct = this.sinon.stub(DefaultActivityHelper, 'setDefaultAction');
|
||||
});
|
||||
|
||||
test('without default activity set >', function() {
|
||||
var set_default = false;
|
||||
formatted.setAsDefault = set_default;
|
||||
subject.choose(0, set_default);
|
||||
|
||||
assert.ok(sendEvent.calledWith(formatted),
|
||||
'calls _sendEvent WITHOUT default activity set');
|
||||
assert.isFalse(defaultAct.called, 'should not call the helper');
|
||||
});
|
||||
|
||||
test('with a default activity set >', function() {
|
||||
var set_default = true;
|
||||
formatted.setAsDefault = set_default;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.choose(0, set_default);
|
||||
|
||||
assert.ok(sendEvent.calledWith(formatted),
|
||||
'calls _sendEvent WITH default activity set');
|
||||
assert.ok(defaultAct.calledWith('testactivity', 'testtype', 'manifest'),
|
||||
'should call the helper with the proper values');
|
||||
assert.ok(subject.publish.calledWith('activitychoosen'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('cancel selection', function() {
|
||||
test('calls _sendEvent', function() {
|
||||
subject._detail = {
|
||||
id: 'foo'
|
||||
};
|
||||
this.sinon.stub(subject, 'publish');
|
||||
var stub = this.sinon.stub(subject, '_sendEvent');
|
||||
var formatted = {
|
||||
id: 'foo',
|
||||
type: 'activity-choice',
|
||||
value: -1
|
||||
};
|
||||
subject.cancel();
|
||||
assert.ok(stub.calledWith(formatted));
|
||||
assert.ok(subject.publish.calledWith('activitycanceled'));
|
||||
});
|
||||
|
||||
test('does not destroy the action menu', function() {
|
||||
subject._detail = {
|
||||
id: 'foo'
|
||||
};
|
||||
var stub = this.sinon.stub(subject.actionMenu, 'hide');
|
||||
subject.cancel();
|
||||
assert.ok(stub.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('when a new app is installed', function() {
|
||||
var app,
|
||||
listedName,
|
||||
listedType;
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(DefaultActivityHelper, 'getDefaultAction');
|
||||
this.sinon.stub(DefaultActivityHelper, 'setDefaultAction');
|
||||
|
||||
app = {
|
||||
'manifest': {
|
||||
'activities': {
|
||||
'browse': {
|
||||
'filters': {
|
||||
'type': 'photos'
|
||||
}
|
||||
},
|
||||
'pick': {
|
||||
'filters': {
|
||||
'type': ['image/*']
|
||||
}
|
||||
},
|
||||
'open': {
|
||||
'filters': {
|
||||
'type': ['video/*']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
listedName = 'pick';
|
||||
listedType = 'image/*';
|
||||
|
||||
subject = BaseModule.instantiate('Activities');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.destroy();
|
||||
});
|
||||
|
||||
test('correctly handles apps without activities', function() {
|
||||
var appWithoutActivities = {
|
||||
'manifest': {}
|
||||
};
|
||||
|
||||
assert.doesNotThrow(
|
||||
() => subject._onNewAppInstalled(appWithoutActivities)
|
||||
);
|
||||
});
|
||||
|
||||
test('manages the default launch for the app\'s activities', function() {
|
||||
DefaultActivityHelper.getDefaultAction
|
||||
.returns({ // instead of Promise.resolve() to return in same cycle
|
||||
then: function(cb) {
|
||||
cb(null);
|
||||
}
|
||||
})
|
||||
.withArgs(listedName, listedType).returns({
|
||||
then: function(cb) {
|
||||
cb('app://fakeapp1.gaiamobile.org/manifest.webapp');
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent(new CustomEvent('applicationinstall',{
|
||||
detail: {
|
||||
application: app
|
||||
}
|
||||
}));
|
||||
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('browse', 'photos'),
|
||||
'check the list for the first activity');
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('pick', 'image/*'),
|
||||
'check the list for the second activity');
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('open', 'video/*'),
|
||||
'check the list for the third activity');
|
||||
|
||||
assert.ok(DefaultActivityHelper.setDefaultAction
|
||||
.calledWith(listedName, listedType, null),
|
||||
'removes the default app when the activity has it associated');
|
||||
|
||||
assert.ok(DefaultActivityHelper.setDefaultAction.calledOnce,
|
||||
'not called for any other activity');
|
||||
});
|
||||
});
|
||||
|
||||
suite('_sendEvent', function() {
|
||||
test('dispatches a mozContentEvent', function() {
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject._sendEvent();
|
||||
assert.equal(dispatchStub.getCall(0).args[0].type, 'mozContentEvent');
|
||||
});
|
||||
});
|
||||
|
||||
suite('_listItems', function() {
|
||||
test('called with empty array', function() {
|
||||
var result = subject._listItems([]);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
test('returns formatted result', function() {
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig1);
|
||||
|
||||
var result = subject._listItems([
|
||||
{
|
||||
manifest: fakeLaunchConfig1.manifestURL,
|
||||
icon: 'http://mozilla'
|
||||
}
|
||||
]);
|
||||
assert.equal(result.length, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
254
gaia/apps/system/test/unit/activity_window_manager_test.js
Executable file
254
gaia/apps/system/test/unit/activity_window_manager_test.js
Executable file
|
|
@ -0,0 +1,254 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, ActivityWindowManager, ActivityWindow,
|
||||
AppWindow, MockService */
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_activity_window.js');
|
||||
requireApp('system/test/unit/mock_popup_window.js');
|
||||
|
||||
var mocksForActivityWindowManager = new MocksHelper([
|
||||
'AppWindow', 'ActivityWindow', 'PopupWindow', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/ActivityWindowManager', function() {
|
||||
mocksForActivityWindowManager.attachTestHelpers();
|
||||
var subject;
|
||||
var fakeActivityConfig1 = {
|
||||
'url': 'app://fakeact1.gaiamobile.org/pick.html',
|
||||
'oop': true,
|
||||
'name': 'Fake Activity 1',
|
||||
'manifestURL': 'app://fakeact1.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeact.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake Activity 1'
|
||||
}
|
||||
};
|
||||
|
||||
var fakeActivityConfig2 = {
|
||||
'url': 'app://fakeact2.gaiamobile.org/pick.html',
|
||||
'oop': true,
|
||||
'name': 'Fake Activity 2',
|
||||
'manifestURL': 'app://fakeact2.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeact2.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake Activity 2'
|
||||
}
|
||||
};
|
||||
|
||||
var fakeActivityConfig3 = {
|
||||
'url': 'app://fakeact3.gaiamobile.org/pick.html',
|
||||
'oop': true,
|
||||
'name': 'Fake Activity 3',
|
||||
'manifestURL': 'app://fakeact3.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeact3.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake Activity 3'
|
||||
}
|
||||
};
|
||||
|
||||
var activity1, activity2, activity3;
|
||||
var popup1, popup2;
|
||||
var app1, app2;
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
var fakeAppConfig2 = {
|
||||
url: 'app://www.fake2/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake2/ManifestURL',
|
||||
origin: 'app://www.fake2'
|
||||
};
|
||||
|
||||
var fakePopupConfig1 = {
|
||||
url: 'app://www.fake/popup.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
var fakePopupConfig2 = {
|
||||
url: 'app://www.fake2/popup.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake2/ManifestURL',
|
||||
origin: 'app://www.fake2'
|
||||
};
|
||||
|
||||
setup(function(done) {
|
||||
requireApp('system/js/activity_window_manager.js', done);
|
||||
});
|
||||
|
||||
suite('handle events', function() {
|
||||
setup(function() {
|
||||
subject = new ActivityWindowManager();
|
||||
subject.start();
|
||||
|
||||
activity1 = new ActivityWindow(fakeActivityConfig1);
|
||||
activity2 = new ActivityWindow(fakeActivityConfig2);
|
||||
activity3 = new ActivityWindow(fakeActivityConfig3);
|
||||
app1 = new AppWindow(fakeAppConfig1);
|
||||
app2 = new AppWindow(fakeAppConfig2);
|
||||
popup1 = new ActivityWindow(fakePopupConfig1);
|
||||
popup2 = new ActivityWindow(fakePopupConfig2);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
subject = null;
|
||||
MockService.mockQueryWith('getTopMostWindow', null);
|
||||
});
|
||||
|
||||
test('maintain activity: created', function() {
|
||||
subject._activities = [activity1, activity2, activity3];
|
||||
var current = subject._activities.length;
|
||||
subject.handleEvent({
|
||||
type: 'activitycreated',
|
||||
detail: {
|
||||
instanceID: 99999
|
||||
}
|
||||
});
|
||||
|
||||
assert.isTrue(subject._activities.length === current + 1);
|
||||
});
|
||||
|
||||
test('maintain activity: terminated', function() {
|
||||
subject._activities = [activity1, activity2, activity3];
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'activityterminated',
|
||||
detail: activity1
|
||||
});
|
||||
|
||||
assert.isTrue(subject._activities.length == 2);
|
||||
});
|
||||
|
||||
test('maintain activity pool: push inline activity into chaining',
|
||||
function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
activity3.bottomWindow = activity2;
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'activityopened',
|
||||
detail: activity3
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.has(activity3.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: push inner sheet into chaining', function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
app2.previousWindow = app1;
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'appopened',
|
||||
detail: app2
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.has(app2.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: push popup into chaining', function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
popup1.bottomWindow = app1;
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'popupopened',
|
||||
detail: popup1
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.has(popup1.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: push window activity into chaining',
|
||||
function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
app2.callerWindow = app1;
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'appopened',
|
||||
detail: app2
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.has(app2.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: requesting out of chaining', function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
MockService.mockQueryWith('getTopMostWindow', app2);
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'activityrequesting'
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.size == 1);
|
||||
assert.isTrue(subject.activityPool.has(app2.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: requesting in chaining', function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[app2.instanceID, true],
|
||||
[app1.instanceID, true]
|
||||
]);
|
||||
|
||||
MockService.mockQueryWith('getTopMostWindow', app2);
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'activityrequesting'
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.size == 4);
|
||||
assert.isTrue(subject.activityPool.has(app1.instanceID));
|
||||
assert.isTrue(subject.activityPool.has(app2.instanceID));
|
||||
assert.isTrue(subject.activityPool.has(activity1.instanceID));
|
||||
assert.isTrue(subject.activityPool.has(activity2.instanceID));
|
||||
});
|
||||
|
||||
test('maintain activity pool: terminated', function() {
|
||||
subject.activityPool = new Map([
|
||||
[activity1.instanceID, true],
|
||||
[activity2.instanceID, true],
|
||||
[activity3.instanceID, true]
|
||||
]);
|
||||
|
||||
subject.handleEvent({
|
||||
type: 'activityterminated',
|
||||
detail: activity1
|
||||
});
|
||||
|
||||
assert.isTrue(subject.activityPool.size == 2);
|
||||
assert.isFalse(subject.activityPool.has(activity1.instanceID));
|
||||
});
|
||||
});
|
||||
});
|
||||
161
gaia/apps/system/test/unit/activity_window_test.js
Executable file
161
gaia/apps/system/test/unit/activity_window_test.js
Executable file
|
|
@ -0,0 +1,161 @@
|
|||
/* global AppWindow, ActivityWindow, MocksHelper, BaseModule, MockContextMenu */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_manifest_helper.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_context_menu.js');
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_screen_layout.js');
|
||||
|
||||
var mocksForActivityWindow = new MocksHelper([
|
||||
'Applications', 'SettingsListener',
|
||||
'ManifestHelper', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/ActivityWindow', function() {
|
||||
mocksForActivityWindow.attachTestHelpers();
|
||||
var activityWindow;
|
||||
var stubById;
|
||||
var fakeConfig = {
|
||||
'url': 'app://fakeact.gaiamobile.org/pick.html',
|
||||
'oop': true,
|
||||
'name': 'Fake Activity',
|
||||
'manifestURL': 'app://fakeact.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeact.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake Activity'
|
||||
}
|
||||
};
|
||||
var fakeConfigFullScreen = {
|
||||
'url': 'app://fakeact.gaiamobile.org/pick.html',
|
||||
'oop': true,
|
||||
'name': 'Fake Activity',
|
||||
'manifestURL': 'app://fakeact.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeact.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake Activity',
|
||||
'fullscreen': true
|
||||
}
|
||||
};
|
||||
|
||||
setup(function(done) {
|
||||
stubById = this.sinon.stub(document, 'getElementById', function(id) {
|
||||
var element = document.createElement('div');
|
||||
if (id.indexOf('AppWindow') >= 0 || id.indexOf('ActivityWindow') >= 0) {
|
||||
var container = document.createElement('div');
|
||||
container.className = 'browser-container';
|
||||
element.appendChild(container);
|
||||
}
|
||||
|
||||
return element;
|
||||
});
|
||||
requireApp('system/js/browser_config_helper.js');
|
||||
requireApp('system/js/browser_frame.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/app_window.js');
|
||||
requireApp('system/js/browser_mixin.js');
|
||||
requireApp('system/js/activity_window.js', function() {
|
||||
this.sinon.stub(BaseModule, 'instantiate', function(name) {
|
||||
if (name === 'BrowserContextMenu') {
|
||||
return MockContextMenu;
|
||||
}
|
||||
});
|
||||
done();
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
suite('activity window instance.', function() {
|
||||
var app, appF, appOrientationUndefined;
|
||||
setup(function() {
|
||||
app = new AppWindow({
|
||||
iframe: document.createElement('iframe'),
|
||||
frame: document.createElement('div'),
|
||||
origin: 'http://fake',
|
||||
url: 'http://fakeurl/index.html',
|
||||
manifestURL: 'http://fakemanifesturl',
|
||||
name: 'fake',
|
||||
manifest: {
|
||||
orientation: 'default'
|
||||
}
|
||||
});
|
||||
appF = new AppWindow({
|
||||
iframe: document.createElement('iframe'),
|
||||
frame: document.createElement('div'),
|
||||
origin: 'http://fake',
|
||||
url: 'http://fakeurl/index.html',
|
||||
manifestURL: 'http://fakemanifesturl',
|
||||
name: 'fake',
|
||||
manifest: {
|
||||
orientation: 'default',
|
||||
fullscreen: true
|
||||
}
|
||||
});
|
||||
appOrientationUndefined = new AppWindow({
|
||||
iframe: document.createElement('iframe'),
|
||||
frame: document.createElement('div'),
|
||||
origin: 'http://fake',
|
||||
url: 'http://fakeurl/index.html',
|
||||
manifestURL: 'http://fakemanifesturl',
|
||||
name: 'fake',
|
||||
manifest: {
|
||||
}
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
});
|
||||
|
||||
test('Render activity inside its caller', function() {
|
||||
var activity = new ActivityWindow(fakeConfig, app);
|
||||
assert.deepEqual(activity.containerElement, app.element);
|
||||
});
|
||||
|
||||
test('requestOpen', function() {
|
||||
var activity = new ActivityWindow(fakeConfig, app);
|
||||
var stubRequestOpen = this.sinon.stub(app, 'requestOpen');
|
||||
|
||||
activity.requestOpen();
|
||||
|
||||
assert.isTrue(stubRequestOpen.calledOnce);
|
||||
});
|
||||
|
||||
test('copy fullscreen from caller', function() {
|
||||
var activity = new ActivityWindow(fakeConfig, appF);
|
||||
assert.isTrue(activity.element.classList.contains('fullscreen-app'));
|
||||
});
|
||||
|
||||
test('prioritize fullscreen mode of the activity', function() {
|
||||
var activity = new ActivityWindow(fakeConfigFullScreen, app);
|
||||
assert.isTrue(activity.element.classList.contains('fullscreen-app'));
|
||||
});
|
||||
|
||||
test('Activity created', function() {
|
||||
var created = false;
|
||||
window.addEventListener('activitycreated', function oncreated() {
|
||||
window.removeEventListener('activitycreated', oncreated);
|
||||
created = true;
|
||||
});
|
||||
activityWindow = new ActivityWindow(fakeConfig);
|
||||
assert.equal(
|
||||
activityWindow.browser.element.getAttribute('mozbrowser'),
|
||||
'true');
|
||||
assert.isTrue(created);
|
||||
});
|
||||
|
||||
test('Activity should stop event propagation', function() {
|
||||
var activity = new ActivityWindow(fakeConfig, appOrientationUndefined);
|
||||
var spy = this.sinon.spy();
|
||||
activity.handleEvent({
|
||||
type: 'mozbrowserloadend',
|
||||
stopPropagation: spy,
|
||||
detail: {}
|
||||
});
|
||||
assert.isTrue(spy.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
882
gaia/apps/system/test/unit/advanced_telemetry_test.js
Executable file
882
gaia/apps/system/test/unit/advanced_telemetry_test.js
Executable file
|
|
@ -0,0 +1,882 @@
|
|||
'use strict';
|
||||
|
||||
/* global AdvancedTelemetry, MockasyncStorage, MockNavigatorSettings, Gzip,
|
||||
AdvancedTelemetryPing, MockLazyLoader */
|
||||
|
||||
require('/shared/js/settings_listener.js');
|
||||
require('/shared/js/uuid.js');
|
||||
require('/shared/js/telemetry.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/js/gzip/gzip.js');
|
||||
requireApp('system/test/unit/mock_asyncStorage.js');
|
||||
requireApp('system/js/advanced_telemetry.js');
|
||||
requireApp('system/js/app_usage_metrics.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
|
||||
suite('AdvancedTelemetry:', function() {
|
||||
var realMozSettings, realOnLine, realPerformanceNow;
|
||||
var isOnLine = true;
|
||||
var payloadOld = {
|
||||
keyedHistograms: {
|
||||
DEV_TOOLS_MEMORY: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
settings: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
}
|
||||
},
|
||||
DEV_TOOLS_STARTUP: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
settings: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
}
|
||||
}
|
||||
},
|
||||
addonHistograms: {
|
||||
addon1: {
|
||||
COMM_SMS: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var payloadNew = {
|
||||
keyedHistograms: {
|
||||
DEV_TOOLS_MEMORY: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
settings: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
calendar: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
}
|
||||
},
|
||||
DEV_TOOLS_STARTUP: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
settings: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
}
|
||||
},
|
||||
DEV_TOOLS_JANK: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
},
|
||||
settings: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type:0,
|
||||
sum:58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]
|
||||
}
|
||||
}
|
||||
},
|
||||
addonHistograms: {
|
||||
addon1: {
|
||||
COMM_SMS: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
||||
}
|
||||
},
|
||||
addon2: {
|
||||
COMM_DIALER: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mergedPayload = {
|
||||
keyedHistograms:{
|
||||
DEV_TOOLS_MEMORY:{
|
||||
verticalhome:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:116,
|
||||
log_sum:21.871920108795166,
|
||||
log_sum_squares:59.90799617767334,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,8,0,0,0,0,0]},
|
||||
settings:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:116,
|
||||
log_sum:21.871920108795166,
|
||||
log_sum_squares:59.90799617767334,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,8,0,0,0,0,0]},
|
||||
calendar:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:58,
|
||||
log_sum:10.935960054397583,
|
||||
log_sum_squares:29.95399808883667,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]}
|
||||
},
|
||||
DEV_TOOLS_STARTUP:{
|
||||
verticalhome:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:116,
|
||||
log_sum:21.871920108795166,
|
||||
log_sum_squares:59.90799617767334,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,8,0,0,0,0,0]},
|
||||
settings:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:116,
|
||||
log_sum:21.871920108795166,
|
||||
log_sum_squares:59.90799617767334,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,8,0,0,0,0,0]}
|
||||
},
|
||||
DEV_TOOLS_JANK:{
|
||||
verticalhome:{
|
||||
min:1,
|
||||
max:1000,histogram_type:0,
|
||||
sum:58,
|
||||
log_sum:10.935960054397583,
|
||||
log_sum_squares:29.95399808883667,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]},
|
||||
settings:{
|
||||
min:1,max:1000,histogram_type:0,
|
||||
sum:58,
|
||||
log_sum:10.935960054397583,
|
||||
log_sum_squares:29.95399808883667,
|
||||
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
||||
counts:[0,0,0,0,4,0,0,0,0,0]}
|
||||
}
|
||||
},
|
||||
addonHistograms:{
|
||||
addon1: {
|
||||
COMM_SMS: {
|
||||
min: 1, max: 1000, histogram_type: 0,
|
||||
sum: 116,
|
||||
log_sum: 21.871920108795166,
|
||||
log_sum_squares: 59.90799617767334,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 8, 0, 0, 0, 0, 0]}
|
||||
},
|
||||
addon2: {
|
||||
COMM_DIALER: {
|
||||
min: 1, max: 1000, histogram_type: 0,
|
||||
sum: 58,
|
||||
log_sum: 10.935960054397583,
|
||||
log_sum_squares: 29.95399808883667,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function navigatorOnLine() {
|
||||
return isOnLine;
|
||||
}
|
||||
|
||||
function setNavigatorOnLine(value) {
|
||||
isOnLine = value;
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
realOnLine = Object.getOwnPropertyDescriptor(navigator, 'onLine');
|
||||
Object.defineProperty(navigator, 'onLine', {
|
||||
configurable: true,
|
||||
get: navigatorOnLine,
|
||||
set: setNavigatorOnLine
|
||||
});
|
||||
navigator.addIdleObserver = function(o) {
|
||||
setTimeout(function() {
|
||||
o.onidle();
|
||||
}, o.time * 1000);
|
||||
};
|
||||
navigator.removeIdleObserver = function() {};
|
||||
|
||||
realPerformanceNow = window.performance.now;
|
||||
window.performance.now = function() { return Date.now(); };
|
||||
AdvancedTelemetry.DEBUG = false;
|
||||
AdvancedTelemetry.LOGINFO = false;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
delete window.asyncStorage;
|
||||
|
||||
if (realOnLine) {
|
||||
Object.defineProperty(navigator, 'onLine', realOnLine);
|
||||
} else {
|
||||
delete navigator.onLine;
|
||||
}
|
||||
window.performance.now = realPerformanceNow;
|
||||
});
|
||||
|
||||
suite('Sending the Metrics:', function() {
|
||||
var at, clock, XHR, xhr, mockSettings;
|
||||
var transmitSpy;
|
||||
var wrapper, packedWrapper;
|
||||
var gzipCompressedData = new Uint8Array([1,2,3,4,5]);
|
||||
|
||||
setup(function(done) {
|
||||
wrapper = {
|
||||
type: AdvancedTelemetry.REASON,
|
||||
id: 'uuid',
|
||||
creationDate: 'testDate',
|
||||
version: AdvancedTelemetry.TELEMETRY_VERSION,
|
||||
application: {
|
||||
architecture: 'arm',
|
||||
buildId: 'build',
|
||||
name: AdvancedTelemetry.TELEMETRY_APP_NAME,
|
||||
version: '43',
|
||||
vendor: 'Mozilla',
|
||||
platformVersion: '43',
|
||||
xpcomAbi: 'arm-gcc3',
|
||||
channel: 'default'
|
||||
},
|
||||
clientId: 'uuid',
|
||||
payload: {
|
||||
keyedHistograms: {
|
||||
DEVTOOLS_HUD_REFLOW_DURATION: {
|
||||
verticalhome: {
|
||||
min: 1,
|
||||
max: 1000,
|
||||
histogram_type: 0,
|
||||
sum: 189,
|
||||
log_sum: 14.329224586486816,
|
||||
log_sum_squares: 53.6346640586853,
|
||||
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
||||
counts: [0, 0, 0, 0, 2, 1, 1, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
addonHistograms: {
|
||||
addon3: {
|
||||
rn_metric: {
|
||||
min: 1,
|
||||
max: 10000,
|
||||
histogram_type: 1,
|
||||
sum: 99,
|
||||
sum_squares_lo: 9801,
|
||||
sum_squares_hi: 0,
|
||||
ranges: [0, 1, 1251, 2501, 3751, 5001, 6250, 7500, 8750, 10000],
|
||||
counts: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
packedWrapper = {
|
||||
type: AdvancedTelemetry.REASON,
|
||||
id: 'uuid',
|
||||
creationDate: 'testDate',
|
||||
version: AdvancedTelemetry.TELEMETRY_VERSION,
|
||||
application: {
|
||||
architecture: 'arm',
|
||||
buildId: 'build',
|
||||
name: AdvancedTelemetry.TELEMETRY_APP_NAME,
|
||||
version: '43',
|
||||
vendor: 'Mozilla',
|
||||
platformVersion: '43',
|
||||
xpcomAbi: 'arm-gcc3',
|
||||
channel: 'default'
|
||||
},
|
||||
clientId: 'uuid',
|
||||
payload: {
|
||||
keyedHistograms: {
|
||||
DEVTOOLS_HUD_REFLOW_DURATION: {
|
||||
verticalhome: {
|
||||
range: [1, 1000],
|
||||
bucket_count:10,
|
||||
histogram_type: 0,
|
||||
values: {'5':0, '12':2, '29':1, '70':1, '170':0},
|
||||
sum: 189,
|
||||
log_sum:14.329224586486816,
|
||||
log_sum_squares: 53.6346640586853
|
||||
}
|
||||
}
|
||||
},
|
||||
addonHistograms: {
|
||||
addon3: {
|
||||
rn_metric: {
|
||||
range: [1, 10000],
|
||||
bucket_count: 10,
|
||||
histogram_type: 1,
|
||||
values: {'0': 0, '1': 1, '1251': 0},
|
||||
sum: 99,
|
||||
sum_squares_lo: 9801,
|
||||
sum_squares_hi: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
transmitSpy = this.sinon.spy(AdvancedTelemetry.prototype, 'transmit');
|
||||
clock = this.sinon.useFakeTimers();
|
||||
XHR = sinon.useFakeXMLHttpRequest();
|
||||
XHR.onCreate = function(instance) { xhr = instance; };
|
||||
MockNavigatorSettings.mSetup();
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
mockSettings = MockNavigatorSettings.mSettings;
|
||||
this.sinon.stub(window, 'uuid', function() {
|
||||
return 'uuid';
|
||||
});
|
||||
|
||||
this.sinon.stub(Date.prototype, 'toISOString').returns('testDate');
|
||||
mockSettings['deviceinfo.platform_build_id'] = 'build';
|
||||
mockSettings['deviceinfo.platform_version'] = '43';
|
||||
mockSettings['app.update.channel'] = 'default';
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
||||
at = new AdvancedTelemetry();
|
||||
at.start();
|
||||
at.startCollecting();
|
||||
done();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
transmitSpy.restore();
|
||||
clock.restore();
|
||||
window.uuid.restore();
|
||||
at.stop();
|
||||
XHR.restore();
|
||||
MockasyncStorage.mTeardown();
|
||||
MockNavigatorSettings.mTeardown();
|
||||
});
|
||||
|
||||
function dispatch(detail) {
|
||||
window.dispatchEvent(new CustomEvent('advanced-telemetry-update',
|
||||
{detail: detail}));
|
||||
clock.tick();
|
||||
}
|
||||
|
||||
test('advanced telemetry update should call transmit', function() {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
at.handleGeckoMessage(payloadNew.payload, function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.equal(transmitSpy.callCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('should retry if not online', function(done) {
|
||||
isOnLine = false;
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'startRetryBatch');
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
||||
at.handleGeckoMessage(payloadNew.payload, function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startRetryBatch);
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should create the XHR properly', function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
|
||||
isOnLine = true;
|
||||
AdvancedTelemetryPing.prototype.send().then(function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.ok(xhr);
|
||||
assert.equal(xhr.method, 'POST');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should format the URL properly', function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
var deviceQuery = {
|
||||
'deviceinfo.platform_version': '43',
|
||||
'app.update.channel': 'default',
|
||||
'deviceinfo.platform_build_id': '34'
|
||||
};
|
||||
|
||||
var atp = new AdvancedTelemetryPing({id: '1234'}, deviceQuery);
|
||||
atp.send().then(function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
// Check that the URL is properly formatted.
|
||||
// URLformat:/id/reason/appName/appVersion/appUpdateChannel/appBuildID?v=4
|
||||
var baseURL = AdvancedTelemetry.REPORT_URL;
|
||||
assert.ok(xhr.url.indexOf(baseURL) === 0);
|
||||
var path = xhr.url.substring(baseURL.length + 1).split('/');
|
||||
assert.equal(path[0], '1234');
|
||||
assert.equal(path[1], AdvancedTelemetry.REASON);
|
||||
assert.equal(path[2], AdvancedTelemetry.TELEMETRY_APP_NAME);
|
||||
assert.equal(path[3], '43');
|
||||
assert.equal(path[4], 'default');
|
||||
let version = path[5].split('?');
|
||||
assert.equal(version[0], '34');
|
||||
assert.equal(version[1], 'v=4');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should format the body properly', function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
at.handleGeckoMessage(wrapper.payload, function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
var req = JSON.parse(at.request.data);
|
||||
assert.ok(req);
|
||||
|
||||
assert.equal(req.type, wrapper.type);
|
||||
assert.equal(req.id, wrapper.id);
|
||||
assert.equal(req.creationDate, wrapper.creationDate);
|
||||
assert.equal(req.version, wrapper.version);
|
||||
assert.equal(req.clientId, wrapper.clientId);
|
||||
|
||||
// Verify the application object picked up the settings correctly.
|
||||
assert.deepEqual(req.application, packedWrapper.application);
|
||||
// Verify that the Histograms are intact and are properly packed.
|
||||
assert.deepEqual(req.payload, packedWrapper.payload);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('advanced telemetry should gzip compression payload', function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
|
||||
this.sinon.stub(AdvancedTelemetryPing.prototype, 'post', function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
// Even though `getData` is being stubbed, since `gzip.compress` is
|
||||
// stubbed to resolve compressed data, `post` should be called with
|
||||
// the compressed data.
|
||||
this.sinon.stub(AdvancedTelemetryPing.prototype, 'getData', function() {
|
||||
return JSON.parse(JSON.stringify(wrapper.payload));
|
||||
});
|
||||
|
||||
AdvancedTelemetryPing.prototype.send().then(function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
// `post` should be called with the compressed data
|
||||
sinon.assert.calledOnce(AdvancedTelemetryPing.prototype.post);
|
||||
sinon.deepEqual(
|
||||
AdvancedTelemetryPing.prototype.post.getCall(0).args[1],
|
||||
gzipCompressedData);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('advanced telemetry should handle gzip compression failure',
|
||||
function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.reject('compress error');
|
||||
});
|
||||
|
||||
this.sinon.stub(AdvancedTelemetryPing.prototype, 'post', function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
// `gzip.compress` is stubbed to "reject" therefore `post` should be
|
||||
// called with the original, uncompressed payload.
|
||||
this.sinon.stub(AdvancedTelemetryPing.prototype, 'getData', function() {
|
||||
return JSON.parse(JSON.stringify(wrapper.payload));
|
||||
});
|
||||
|
||||
AdvancedTelemetryPing.prototype.send().then(function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
// `post` should be called with the uncompressed payload
|
||||
sinon.assert.calledOnce(AdvancedTelemetryPing.prototype.post);
|
||||
sinon.deepEqual(
|
||||
AdvancedTelemetryPing.prototype.post.getCall(0).args[1],
|
||||
wrapper.payload);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should retry on a timeout error', function(done) {
|
||||
var retryspy = this.sinon.spy(window, 'setTimeout');
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
dispatch({payload: wrapper.payload});
|
||||
|
||||
// Simulate a timeout
|
||||
xhr.ontimeout(new CustomEvent('timeout'));
|
||||
assert.equal(retryspy.getCall(0).args[1],
|
||||
AdvancedTelemetry.RETRY_INTERVAL);
|
||||
done();
|
||||
});
|
||||
|
||||
test('should retry interval after failed transmit', function(done) {
|
||||
var retryspy = this.sinon.spy(window, 'setTimeout');
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
dispatch({payload: wrapper.payload});
|
||||
|
||||
// Simulate a timeout
|
||||
xhr.ontimeout(new CustomEvent('error'));
|
||||
assert.equal(retryspy.getCall(0).args[1],
|
||||
AdvancedTelemetry.RETRY_INTERVAL);
|
||||
done();
|
||||
});
|
||||
|
||||
test('should clear out the payload after a successful transmit',
|
||||
function(done) {
|
||||
this.sinon.stub(Gzip, 'compress', function() {
|
||||
return Promise.resolve(gzipCompressedData);
|
||||
});
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
at.handleGeckoMessage(wrapper.payload, function() {
|
||||
// Simulate a successful send
|
||||
xhr.onload(new CustomEvent('load'));
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.clearPayload);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should clear out the payload after a successful merge',
|
||||
function(done) {
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
at.merge = true;
|
||||
at.handleGeckoMessage(wrapper.payload, function() {
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.clearPayload);
|
||||
sinon.assert.calledWith(AdvancedTelemetry.prototype.clearPayload,
|
||||
false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should NOT clear out the payload after a failed transmit',
|
||||
function(done) {
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
at.handleGeckoMessage(wrapper.payload, function() {
|
||||
// Simulate an error
|
||||
xhr.ontimeout(new CustomEvent('error'));
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should NOT clear out the payload after a transmit timeout',
|
||||
function(done) {
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
||||
this.sinon.stub(console, 'info').returns(0);
|
||||
at.handleGeckoMessage(wrapper.payload, function() {
|
||||
// Simulate a timeout
|
||||
xhr.ontimeout(new CustomEvent('timeout'));
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Enable/disable:', function() {
|
||||
var mockSettings, at, clock;
|
||||
|
||||
setup(function() {
|
||||
MockNavigatorSettings.mSetup();
|
||||
mockSettings = MockNavigatorSettings.mSettings;
|
||||
clock = this.sinon.useFakeTimers();
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'startCollecting');
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'stopCollecting');
|
||||
at = new AdvancedTelemetry();
|
||||
clock.tick();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
at.stop();
|
||||
clock.tick();
|
||||
MockNavigatorSettings.mTeardown();
|
||||
});
|
||||
|
||||
test('starts immediately if enabled', function(done) {
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
||||
at.start();
|
||||
clock.tick();
|
||||
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.stopCollecting);
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
||||
done();
|
||||
});
|
||||
|
||||
test('does not start if not enabled', function(done) {
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
||||
at.start();
|
||||
clock.tick();
|
||||
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.startCollecting);
|
||||
done();
|
||||
});
|
||||
|
||||
test('starts when enabled', function(done) {
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
||||
|
||||
at.start();
|
||||
clock.tick();
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.startCollecting);
|
||||
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
||||
MockNavigatorSettings.mTriggerObservers(
|
||||
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'Enhanced' });
|
||||
clock.tick();
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
||||
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
||||
MockNavigatorSettings.mTriggerObservers(
|
||||
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'None' });
|
||||
clock.tick();
|
||||
|
||||
done(sinon.assert.calledTwice(
|
||||
AdvancedTelemetry.prototype.stopCollecting));
|
||||
});
|
||||
|
||||
test('stops when disabled and starts again', function(done) {
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
||||
at.start();
|
||||
clock.tick();
|
||||
sinon.assert.notCalled(AdvancedTelemetry.prototype.stopCollecting);
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
||||
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
||||
MockNavigatorSettings.mTriggerObservers(
|
||||
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'None' });
|
||||
clock.tick();
|
||||
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
||||
|
||||
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
||||
MockNavigatorSettings.mTriggerObservers(
|
||||
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'Enhanced' });
|
||||
clock.tick();
|
||||
sinon.assert.calledTwice(AdvancedTelemetry.prototype.startCollecting);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Batch Timings:', function() {
|
||||
var BatchTiming, clock;
|
||||
suiteSetup(function() {
|
||||
BatchTiming = AdvancedTelemetry.BatchTiming;
|
||||
});
|
||||
|
||||
setup(function () {
|
||||
clock = this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
test('should set full interval the first time', function (done) {
|
||||
this.sinon.stub(Date, 'now').returns(2);
|
||||
var bt = new BatchTiming(true);
|
||||
bt.getInterval();
|
||||
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY, function(value) {
|
||||
assert.equal(value, '2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should set full interval after a batch send', function (done) {
|
||||
this.sinon.stub(Date, 'now').returns(2);
|
||||
var bt = new BatchTiming();
|
||||
bt.getInterval();
|
||||
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
||||
function (value) {
|
||||
assert.equal(value, '2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should not modify the start time if existing time', function (done) {
|
||||
MockasyncStorage[AdvancedTelemetry.BATCH_KEY] = '2';
|
||||
var bt = new BatchTiming(true);
|
||||
bt.getInterval();
|
||||
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
||||
function (value) {
|
||||
assert.equal(value, '2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should recalculate the interval correctly if existing time set',
|
||||
function (done) {
|
||||
MockasyncStorage.setItem(AdvancedTelemetry.BATCH_KEY, 1437671946520);
|
||||
clock.tick();
|
||||
this.sinon.stub(Date, 'now').returns(1437671946521);
|
||||
|
||||
var bt = new BatchTiming(true);
|
||||
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
||||
function (value) {
|
||||
assert.equal(value, 1437671946520);
|
||||
assert.equal(bt.getInterval(), 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should safeguard an interval being set for too long',
|
||||
function (done) {
|
||||
MockasyncStorage.setItem(AdvancedTelemetry.BATCH_KEY, 1437681946521);
|
||||
clock.tick();
|
||||
this.sinon.stub(Date, 'now').returns(1487681946521);
|
||||
|
||||
var bt = new BatchTiming(true);
|
||||
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
||||
function (value) {
|
||||
assert.equal(value, 1487681946521);
|
||||
assert.equal(bt.getInterval(), AdvancedTelemetry.REPORT_INTERVAL);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Merging Metrics:', function() {
|
||||
var mockSettings, at, clock;
|
||||
// The old, and new payloads are setup to make sure that the merged
|
||||
// payload properly reflects: 1) An item in the old that is not in the new,
|
||||
// 2) An item in the new that is not in the old, and 3) the addition of the
|
||||
// histogram elements is done correctly for sum, log_sum, and
|
||||
// log_sum_squares.
|
||||
|
||||
setup(function() {
|
||||
mockSettings = MockNavigatorSettings.mSettings;
|
||||
clock = this.sinon.useFakeTimers();
|
||||
this.sinon.spy(MockasyncStorage, 'setItem');
|
||||
this.sinon.spy(AdvancedTelemetry.prototype, 'transmit');
|
||||
at = new AdvancedTelemetry();
|
||||
clock.tick();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
at.stop();
|
||||
clock.tick();
|
||||
MockasyncStorage.mTeardown();
|
||||
done();
|
||||
});
|
||||
|
||||
test('should merge correctly with no previous metrics', function() {
|
||||
at.mergeMetrics(payloadNew);
|
||||
sinon.assert.calledOnce(MockasyncStorage.setItem);
|
||||
// The calledWith does a deepEqual check on all the JSON elements.
|
||||
sinon.assert.calledWith(MockasyncStorage.setItem,
|
||||
AdvancedTelemetry.METRICS_KEY, payloadNew);
|
||||
});
|
||||
|
||||
test('should merge correct with metrics with existing metrics', function() {
|
||||
// Make a clone so we don't modify it for subsequent tests.
|
||||
var cloneOldPayload = JSON.parse(JSON.stringify(payloadOld));
|
||||
|
||||
MockasyncStorage.setItem(AdvancedTelemetry.METRICS_KEY, cloneOldPayload);
|
||||
at.mergeMetrics(payloadNew);
|
||||
// Called once above for test setup.
|
||||
sinon.assert.calledTwice(MockasyncStorage.setItem);
|
||||
// The calledWith does a deepEqual check on all the JSON elements.
|
||||
sinon.assert.calledWith(MockasyncStorage.setItem,
|
||||
AdvancedTelemetry.METRICS_KEY, mergedPayload);
|
||||
});
|
||||
});
|
||||
});
|
||||
36
gaia/apps/system/test/unit/airplane_mode_icon_test.js
Executable file
36
gaia/apps/system/test/unit/airplane_mode_icon_test.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
/* global AirplaneModeIcon */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/airplane_mode_icon.js');
|
||||
|
||||
suite('system/AirplaneModeIcon', function() {
|
||||
var subject, manager;
|
||||
|
||||
setup(function() {
|
||||
manager = {
|
||||
enabled: false
|
||||
};
|
||||
subject = new AirplaneModeIcon(manager);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('AirplaneMode is deactivated', function() {
|
||||
manager.enabled = false;
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
|
||||
test('AirplaneMode is activated', function() {
|
||||
manager.enabled = true;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
});
|
||||
173
gaia/apps/system/test/unit/airplane_mode_service_helper_test.js
Executable file
173
gaia/apps/system/test/unit/airplane_mode_service_helper_test.js
Executable file
|
|
@ -0,0 +1,173 @@
|
|||
/* global MocksHelper, BaseModule, MockNavigatorSettings,
|
||||
Bluetooth, WifiManager */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_bluetooth.js');
|
||||
requireApp('system/test/unit/mock_wifi_manager.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/airplane_mode_service_helper.js');
|
||||
|
||||
var mocksForAirplaneModeServiceHelper = new MocksHelper([
|
||||
'Bluetooth',
|
||||
'WifiManager',
|
||||
'NavigatorSettings'
|
||||
]).init();
|
||||
|
||||
suite('system/airplane_mode_service_helper.js', function() {
|
||||
var subject, settingsCore;
|
||||
var realMozSettings, realWifiManager, realNfc, realBluetooth;
|
||||
var services = ['ril.data', 'geolocation', 'wifi', 'nfc', 'bluetooth'];
|
||||
mocksForAirplaneModeServiceHelper.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realWifiManager = navigator.mozWifiManager;
|
||||
navigator.mozWifiManager = WifiManager;
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
realNfc = navigator.mozNfc;
|
||||
navigator.mozNfc = {};
|
||||
realBluetooth = navigator.mozBluetooth;
|
||||
Object.defineProperty(navigator, 'mozBluetooth', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return Bluetooth;
|
||||
}
|
||||
});
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozNfc = realNfc;
|
||||
navigator.mozWifiManager = realWifiManager;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
Object.defineProperty(navigator, 'mozBluetooth', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return realBluetooth;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
settingsCore = BaseModule.instantiate('SettingsCore');
|
||||
settingsCore.start();
|
||||
subject = BaseModule.instantiate('AirplaneModeServiceHelper');
|
||||
});
|
||||
teardown(function() {
|
||||
settingsCore.stop();
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
suite('init', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
});
|
||||
|
||||
services.forEach(function(key) {
|
||||
test('should set initial values of _settings for ' + key,
|
||||
function() {
|
||||
MockNavigatorSettings.mTriggerObservers(
|
||||
key + '.enabled', { settingValue: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('_suspend should work as expected when services are enabled',
|
||||
function() {
|
||||
var fakeNfc = {};
|
||||
suiteSetup(function() {
|
||||
if (!navigator.mozNfc) {
|
||||
navigator.mozNfc = fakeNfc;
|
||||
}
|
||||
});
|
||||
suiteTeardown(function() {
|
||||
if (navigator.mozNfc === fakeNfc) {
|
||||
delete navigator.mozNfc;
|
||||
}
|
||||
});
|
||||
setup(function() {
|
||||
subject.start();
|
||||
services.forEach(function(key) {
|
||||
MockNavigatorSettings.mTriggerObservers(key + '.enabled', {
|
||||
settingValue: true
|
||||
});
|
||||
MockNavigatorSettings.mTriggerObservers(key + '.suspended', {
|
||||
settingValue: false
|
||||
});
|
||||
});
|
||||
sinon.spy(window, 'dispatchEvent');
|
||||
});
|
||||
teardown(function() {
|
||||
window.dispatchEvent.restore();
|
||||
});
|
||||
test('turn on airplane mode, thus all ".enabled" should be false ' +
|
||||
'and all ".suspended" should be true', function() {
|
||||
subject.updateStatus(true);
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
services.forEach(function(key) {
|
||||
if (key === 'bluetooth') {
|
||||
assert.ok(window.dispatchEvent.calledTwice);
|
||||
} else {
|
||||
assert.equal(
|
||||
MockNavigatorSettings.mSettings[key + '.enabled'], false);
|
||||
assert.equal(
|
||||
MockNavigatorSettings.mSettings[key + '.suspended'], true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('_unsuspend should work as expected when airplane mode is on',
|
||||
function() {
|
||||
test('turn on airplane mode, thus all ".enabled" should be false ' +
|
||||
'and all ".suspended" should be true', function() {
|
||||
// enable airplane mode, thus suspend all services
|
||||
services.forEach(function(key) {
|
||||
subject._unsuspend(key + '.suspended');
|
||||
});
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
services.forEach(function(key) {
|
||||
assert.equal(MockNavigatorSettings.mSettings[key + '.suspended'],
|
||||
false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('restoring enabled settings', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
services.forEach(function(key) {
|
||||
MockNavigatorSettings.mTriggerObservers(key + '.enabled', {
|
||||
settingValue: false
|
||||
});
|
||||
MockNavigatorSettings.mTriggerObservers(key + '.suspended', {
|
||||
settingValue: true
|
||||
});
|
||||
});
|
||||
sinon.spy(window, 'dispatchEvent');
|
||||
});
|
||||
teardown(function() {
|
||||
window.dispatchEvent.restore();
|
||||
});
|
||||
test('turn on all services, then turn on airplane mode, ' +
|
||||
'and turn off airplane mode. All ".suspended" and ".enabled" ' +
|
||||
'should be just the same', function() {
|
||||
subject.updateStatus(false);
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
services.forEach(function(key) {
|
||||
if (key === 'bluetooth') {
|
||||
assert.ok(window.dispatchEvent.calledTwice);
|
||||
} else {
|
||||
assert.equal(MockNavigatorSettings.mSettings[key + '.enabled'],
|
||||
true);
|
||||
assert.equal(
|
||||
MockNavigatorSettings.mSettings[key + '.suspended'], false);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
200
gaia/apps/system/test/unit/airplane_mode_test.js
Executable file
200
gaia/apps/system/test/unit/airplane_mode_test.js
Executable file
|
|
@ -0,0 +1,200 @@
|
|||
/* global MockNavigatorSettings, MocksHelper,
|
||||
MockNavigatorMozMobileConnections, MockAirplaneModeServiceHelper,
|
||||
MockLazyLoader, BaseModule, AirplaneModeIcon */
|
||||
'use strict';
|
||||
|
||||
requireApp(
|
||||
'system/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/test/unit/mock_wifi_manager.js');
|
||||
requireApp('system/test/unit/mock_airplane_mode_service_helper.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/airplane_mode_icon.js');
|
||||
requireApp('system/js/airplane_mode.js');
|
||||
|
||||
var mocksForAirplaneMode = new MocksHelper([
|
||||
'WifiManager',
|
||||
'NavigatorMozMobileConnections',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/airplane_mode.js', function() {
|
||||
var realSettings;
|
||||
var realMobileConnections;
|
||||
var subject;
|
||||
|
||||
mocksForAirplaneMode.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
sinon.spy(MockLazyLoader, 'load');
|
||||
realSettings = window.navigator.mozSettings;
|
||||
window.navigator.mozSettings = MockNavigatorSettings;
|
||||
realMobileConnections = window.navigator.mozMobileConnections;
|
||||
window.navigator.mozMobileConnections = MockNavigatorMozMobileConnections;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.navigator.mozSettings = realSettings;
|
||||
MockNavigatorMozMobileConnections.mTeardown();
|
||||
window.navigator.mozMobileConnections = realMobileConnections;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('AirplaneMode');
|
||||
window.AirplaneModeServiceHelper = MockAirplaneModeServiceHelper;
|
||||
subject.start();
|
||||
subject.airplaneModeServiceHelper = new MockAirplaneModeServiceHelper();
|
||||
subject.icon = new AirplaneModeIcon(subject);
|
||||
this.sinon.stub(subject.icon, 'update');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('should lazy load icon', function() {
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(['js/airplane_mode_icon.js']));
|
||||
});
|
||||
|
||||
suite('set enabled to true', function() {
|
||||
suite('but _enabled is true already, do nothing', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(subject.airplaneModeServiceHelper, 'updateStatus');
|
||||
subject._enabled = true;
|
||||
subject.enabled = true;
|
||||
});
|
||||
test('nothing happend', function() {
|
||||
assert.isFalse(subject.airplaneModeServiceHelper.updateStatus.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_enabled is false, keep running', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject.airplaneModeServiceHelper, 'updateStatus');
|
||||
subject._enabled = false;
|
||||
|
||||
// we have to make eventListeners to the newest state
|
||||
MockNavigatorMozMobileConnections.mAddMobileConnection();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
// we have to make eventListeners to the newest state
|
||||
MockNavigatorMozMobileConnections.mTeardown();
|
||||
});
|
||||
|
||||
suite('conn0 is enabling, conn1 is enabling', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject, '_updateAirplaneModeStatus');
|
||||
|
||||
setConnection(0, 'enabling');
|
||||
setConnection(1, 'enabling');
|
||||
subject.enabled = true;
|
||||
});
|
||||
test('no further steps because we are waiting for other events',
|
||||
function() {
|
||||
assert.isTrue(subject._updateAirplaneModeStatus.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('conn0 is enabling, conn1 is enabled', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject, '_updateAirplaneModeStatus');
|
||||
|
||||
setConnection(0, 'enabling');
|
||||
setConnection(1, 'enabled');
|
||||
subject.enabled = true;
|
||||
});
|
||||
test('no further steps because we are waiting for other events',
|
||||
function() {
|
||||
assert.isTrue(subject._updateAirplaneModeStatus.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('conn0 is enabled, conn1 is enabled', function() {
|
||||
// we will wait for these two services
|
||||
suiteSetup(function() {
|
||||
setSettingOnServiceHelper('wifi.enabled', true);
|
||||
setSettingOnServiceHelper('bluetooth.enabled', true);
|
||||
});
|
||||
suiteTeardown(function() {
|
||||
setSettingOnServiceHelper('wifi.enabled', false);
|
||||
setSettingOnServiceHelper('bluetooth.enabled', false);
|
||||
});
|
||||
setup(function() {
|
||||
setConnection(0, 'enabled');
|
||||
setConnection(1, 'enabled');
|
||||
subject.enabled = true;
|
||||
});
|
||||
test('no further steps because we are waiting for other events',
|
||||
function() {
|
||||
// but because we are still waiting for the other window event,
|
||||
// we we will not execute further steps
|
||||
var checkedActions = subject._getCheckedActions(true);
|
||||
assert.isFalse(
|
||||
subject._areCheckedActionsAllDone(checkedActions));
|
||||
});
|
||||
});
|
||||
|
||||
suite('conn0 is enabled, conn1 is enabled', function() {
|
||||
setup(function() {
|
||||
setConnection(0, 'enabled');
|
||||
setConnection(1, 'enabled');
|
||||
|
||||
this.sinon.stub(subject, 'writeSetting');
|
||||
subject.enabled = true;
|
||||
});
|
||||
test('all other services are also done, we are in airplaneMode',
|
||||
function() {
|
||||
emitEvent('wifi-disabled');
|
||||
emitEvent('bluetooth-disabled');
|
||||
emitEvent('radio-disabled');
|
||||
|
||||
assert.deepEqual(subject.writeSetting.getCall(0).args[0], {
|
||||
'airplaneMode.status': 'enabled',
|
||||
'airplaneMode.enabled': true,
|
||||
'ril.radio.disabled': true
|
||||
});
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('AirplaneMode is enabled now', function() {
|
||||
suite('but users want to dial out an emergency call', function() {
|
||||
setup(function() {
|
||||
subject._enabled = true;
|
||||
setConnection(0, 'enabled');
|
||||
setConnection(1, 'enabled');
|
||||
});
|
||||
test('we will leave airplane mode', function() {
|
||||
emitEvent('radiostatechange', 'enabled');
|
||||
emitEvent('wifi-enabled');
|
||||
emitEvent('bluetooth-enabled');
|
||||
emitEvent('radio-enabled');
|
||||
|
||||
assert.isTrue(subject.enabled);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// test helpers
|
||||
function setSettingOnServiceHelper(key, value) {
|
||||
subject.airplaneModeServiceHelper._settings[key] = value;
|
||||
}
|
||||
|
||||
function setConnection(connIndex, status) {
|
||||
MockNavigatorMozMobileConnections[connIndex].radioState = status;
|
||||
}
|
||||
|
||||
function emitEvent(eventName, detail) {
|
||||
var evt = new CustomEvent(eventName, {
|
||||
detail: detail || null
|
||||
});
|
||||
window.dispatchEvent(evt);
|
||||
}
|
||||
});
|
||||
36
gaia/apps/system/test/unit/alarm_icon_test.js
Executable file
36
gaia/apps/system/test/unit/alarm_icon_test.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
/* global AlarmIcon */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/alarm_icon.js');
|
||||
|
||||
suite('system/AlarmIcon', function() {
|
||||
var subject, manager;
|
||||
|
||||
setup(function() {
|
||||
manager = {
|
||||
enabled: false
|
||||
};
|
||||
subject = new AlarmIcon(manager);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Alarm is enabled', function() {
|
||||
manager.enabled = true;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Alarm is disabled', function() {
|
||||
manager.enabled = false;
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
70
gaia/apps/system/test/unit/alarm_monitor_test.js
Executable file
70
gaia/apps/system/test/unit/alarm_monitor_test.js
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
/* global MocksHelper, BaseModule, MockNavigatorSettings,
|
||||
MockLazyLoader */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/alarm_icon.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/alarm_monitor.js');
|
||||
|
||||
var mocksForAlarmMonitor = new MocksHelper([
|
||||
'NavigatorSettings',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/AlarmMonitor', function() {
|
||||
var subject, settingsCore, realMozSettings;
|
||||
mocksForAlarmMonitor.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
settingsCore = BaseModule.instantiate('SettingsCore');
|
||||
settingsCore.start();
|
||||
subject = BaseModule.instantiate('AlarmMonitor');
|
||||
this.sinon.spy(MockLazyLoader, 'load');
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
settingsCore.stop();
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Should lazy load icon', function() {
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(['js/alarm_icon.js']));
|
||||
});
|
||||
|
||||
suite('Update icon', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject.icon, 'update');
|
||||
});
|
||||
|
||||
test('Should be enabled if setting value is true', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('alarm.enabled',
|
||||
{ settingValue: true });
|
||||
assert.isTrue(subject.enabled);
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
|
||||
test('Should be enabled if setting value is false', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('alarm.enabled',
|
||||
{ settingValue: false });
|
||||
assert.isFalse(subject.enabled);
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
92
gaia/apps/system/test/unit/app_authentication_dialog_test.js
Executable file
92
gaia/apps/system/test/unit/app_authentication_dialog_test.js
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
'use strict';
|
||||
/* global AppAuthenticationDialog */
|
||||
/* global AppWindow */
|
||||
/* global MocksHelper */
|
||||
/* global MockL10n */
|
||||
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
var mocksForAppAuthDialog = new MocksHelper([
|
||||
'AppWindow'
|
||||
]).init();
|
||||
|
||||
suite('system/AppAuthenticationDialog', function() {
|
||||
var stubById, stubQuerySelector, realL10n;
|
||||
mocksForAppAuthDialog.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
var e = document.createElement('div');
|
||||
stubQuerySelector = this.sinon.stub(e, 'querySelector');
|
||||
stubQuerySelector.returns(document.createElement('div'));
|
||||
stubById.returns(e);
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/app_authentication_dialog.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
stubQuerySelector.restore();
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
test('new', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var auth1 = new AppAuthenticationDialog(app1);
|
||||
assert.ok(app1);
|
||||
assert.ok(auth1);
|
||||
});
|
||||
|
||||
test('show/hide', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
|
||||
var auth1 = new AppAuthenticationDialog(app1);
|
||||
var evt = new CustomEvent('mozbrowserusernameandpasswordrequired', {
|
||||
detail: {
|
||||
host: '',
|
||||
realm: '',
|
||||
path: 'whatever',
|
||||
authenticate: function() {}
|
||||
}
|
||||
});
|
||||
var stubStopPropagation = this.sinon.stub(evt, 'stopPropagation');
|
||||
auth1.handleEvent(evt);
|
||||
auth1.hide();
|
||||
|
||||
assert.isFalse(auth1.element.classList.contains('visible'));
|
||||
|
||||
auth1.show();
|
||||
|
||||
assert.isTrue(auth1.element.classList.contains('visible'));
|
||||
assert.isTrue(stubStopPropagation.called);
|
||||
});
|
||||
|
||||
test('favicon.ico request should not show dialog', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var auth1 = new AppAuthenticationDialog(app1);
|
||||
var detail = {
|
||||
host: '',
|
||||
path: 'favicon.ico',
|
||||
realm: '',
|
||||
cancel: function() {}
|
||||
};
|
||||
var cancelSpy = this.sinon.spy(detail, 'cancel');
|
||||
var evt = new CustomEvent('mozbrowserusernameandpasswordrequired', {
|
||||
detail: detail
|
||||
});
|
||||
auth1.handleEvent(evt);
|
||||
assert.isUndefined(auth1.element);
|
||||
assert.isTrue(cancelSpy.called);
|
||||
});
|
||||
});
|
||||
1530
gaia/apps/system/test/unit/app_chrome_test.js
Executable file
1530
gaia/apps/system/test/unit/app_chrome_test.js
Executable file
File diff suppressed because it is too large
Load diff
1791
gaia/apps/system/test/unit/app_install_manager_test.js
Executable file
1791
gaia/apps/system/test/unit/app_install_manager_test.js
Executable file
File diff suppressed because it is too large
Load diff
163
gaia/apps/system/test/unit/app_modal_dialog_test.js
Executable file
163
gaia/apps/system/test/unit/app_modal_dialog_test.js
Executable file
|
|
@ -0,0 +1,163 @@
|
|||
/* global MocksHelper, MockL10n, AppWindow, AppModalDialog */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/test/unit/mock_orientation_manager.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
|
||||
var mocksForAppModalDialog = new MocksHelper([
|
||||
'AppWindow'
|
||||
]).init();
|
||||
|
||||
suite('system/AppModalDialog', function() {
|
||||
var realL10n, app, md, fragment;
|
||||
mocksForAppModalDialog.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
|
||||
requireApp('system/js/app_modal_dialog.js',
|
||||
function() {
|
||||
app = new AppWindow(fakeAppConfig1);
|
||||
md = new AppModalDialog(app);
|
||||
|
||||
fragment = document.createElement('div');
|
||||
fragment.innerHTML = md.view();
|
||||
document.body.appendChild(fragment);
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
document.body.removeChild(fragment);
|
||||
fragment = null;
|
||||
md = null;
|
||||
app = null;
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake',
|
||||
name: 'Fake Application'
|
||||
};
|
||||
|
||||
var fakeAlertEvent = {
|
||||
type: 'mozbrowsermodalprompt',
|
||||
preventDefault: function() {},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
type: 'alert',
|
||||
title: 'alert title',
|
||||
message: 'alert message',
|
||||
unblock: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
var fakeConfirmEvent = {
|
||||
type: 'mozbrowsermodalprompt',
|
||||
preventDefault: function() {},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
type: 'confirm',
|
||||
title: 'confirm title',
|
||||
message: 'confirm message',
|
||||
unblock: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
var fakePromptEvent = {
|
||||
type: 'mozbrowsermodalprompt',
|
||||
preventDefault: function() {},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
type: 'prompt',
|
||||
title: 'prompt title',
|
||||
message: 'prompt message',
|
||||
unblock: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
var fakeCustomPromptEvent = {
|
||||
type: 'mozbrowsermodalprompt',
|
||||
preventDefault: function() {},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
type: 'custom-prompt',
|
||||
unblock: function() {},
|
||||
buttons: [{'messageType': 'custom', 'message': 'Resend'},
|
||||
{'messageType': 'builtin', 'message': 'cancel'}]
|
||||
}
|
||||
};
|
||||
|
||||
test('New', function() {
|
||||
assert.isDefined(md.instanceID);
|
||||
});
|
||||
|
||||
test('Sets visible to false when showing', function() {
|
||||
md.handleEvent(fakeAlertEvent);
|
||||
assert.isTrue(md.isVisible());
|
||||
});
|
||||
|
||||
test('Sets visible to false when hidding', function() {
|
||||
md.handleEvent(fakeAlertEvent);
|
||||
md.hide();
|
||||
assert.isFalse(md.isVisible());
|
||||
});
|
||||
|
||||
test('Alert', function() {
|
||||
var stubStopPropagation =
|
||||
this.sinon.stub(fakeAlertEvent, 'stopPropagation');
|
||||
md.handleEvent(fakeAlertEvent);
|
||||
|
||||
assert.isTrue(md.element.classList.contains('visible'));
|
||||
assert.isTrue(md.elements.alert.classList.contains('visible'));
|
||||
assert.equal(md.elements.alertTitle.innerHTML, 'alert title');
|
||||
assert.equal(md.elements.alertMessage.innerHTML, 'alert message');
|
||||
assert.isTrue(stubStopPropagation.called);
|
||||
});
|
||||
|
||||
test('Confirm', function() {
|
||||
md.handleEvent(fakeConfirmEvent);
|
||||
|
||||
assert.isTrue(md.element.classList.contains('visible'));
|
||||
assert.isTrue(md.elements.confirm.classList.contains('visible'));
|
||||
assert.equal(md.elements.confirmTitle.innerHTML, 'confirm title');
|
||||
assert.equal(md.elements.confirmMessage.innerHTML, 'confirm message');
|
||||
});
|
||||
|
||||
test('Prompt', function() {
|
||||
md.handleEvent(fakePromptEvent);
|
||||
|
||||
assert.isTrue(md.element.classList.contains('visible'));
|
||||
assert.isTrue(md.elements.prompt.classList.contains('visible'));
|
||||
assert.equal(md.elements.promptTitle.innerHTML, 'prompt title');
|
||||
assert.equal(md.elements.promptMessage.innerHTML, 'prompt message');
|
||||
});
|
||||
|
||||
test('CustomPrompt', function() {
|
||||
md.handleEvent(fakeCustomPromptEvent);
|
||||
|
||||
assert.isTrue(md.element.classList.contains('visible'));
|
||||
assert.isTrue(md.elements.customPrompt.classList.contains('visible'));
|
||||
});
|
||||
|
||||
test('Ignore Dialog Titles containing App Origin URL', function() {
|
||||
var fakeAlertBadTitleEvent = fakeAlertEvent;
|
||||
fakeAlertBadTitleEvent.detail.title = fakeAppConfig1.url;
|
||||
|
||||
md.handleEvent(fakeAlertBadTitleEvent);
|
||||
|
||||
assert.isTrue(md.element.classList.contains('visible'));
|
||||
assert.isTrue(md.elements.alert.classList.contains('visible'));
|
||||
assert.equal(md.elements.alertTitle.innerHTML, fakeAppConfig1.name);
|
||||
});
|
||||
|
||||
});
|
||||
291
gaia/apps/system/test/unit/app_statusbar_test.js
Executable file
291
gaia/apps/system/test/unit/app_statusbar_test.js
Executable file
|
|
@ -0,0 +1,291 @@
|
|||
/* global MockAppWindow, AppStatusbar, MocksHelper, MockTouchForwarder */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
require('/test/unit/mock_touch_forwarder.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/app_statusbar.js');
|
||||
|
||||
var mocksForAppStatusbar = new MocksHelper([
|
||||
'AppWindow',
|
||||
'TouchForwarder'
|
||||
]).init();
|
||||
|
||||
suite('system/AppStatusbar', function() {
|
||||
mocksForAppStatusbar.attachTestHelpers();
|
||||
var app;
|
||||
var subject;
|
||||
setup(function() {
|
||||
this.sinon.useFakeTimers();
|
||||
app = new MockAppWindow({ chrome: { navigation: false }});
|
||||
subject = new AppStatusbar(app);
|
||||
this.sinon.stub(app, 'isFullScreen').returns(true);
|
||||
subject.screen = document.createElement('div');
|
||||
subject.chromeBar = document.createElement('div');
|
||||
subject.titleBar = document.createElement('div');
|
||||
});
|
||||
|
||||
suite('Reset destination if browser is destroyed', function() {
|
||||
test('Suspend', function() {
|
||||
app.element.dispatchEvent(new CustomEvent('_suspended'));
|
||||
assert.isNull(subject._touchForwarder.destination);
|
||||
});
|
||||
|
||||
test('Resume', function() {
|
||||
var newBrowserElement = document.createElement('iframe');
|
||||
app.browser = {
|
||||
element: newBrowserElement
|
||||
};
|
||||
app.element.dispatchEvent(new CustomEvent('_resumed'));
|
||||
assert.deepEqual(subject._touchForwarder.destination, newBrowserElement);
|
||||
});
|
||||
});
|
||||
|
||||
suite('fullscreen mode >', function() {
|
||||
function forgeTouchEvent(type, x, y) {
|
||||
var touch = document.createTouch(window, null, 42, x, y,
|
||||
x, y, x, y,
|
||||
0, 0, 0, 0);
|
||||
var touchList = document.createTouchList(touch);
|
||||
var touches = (type == 'touchstart' || type == 'touchmove') ?
|
||||
touchList : null;
|
||||
var changed = (type == 'touchmove') ?
|
||||
null : touchList;
|
||||
|
||||
var e = document.createEvent('TouchEvent');
|
||||
e.initTouchEvent(type, true, true,
|
||||
null, null, false, false, false, false,
|
||||
touches, null, changed);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
function forgeMouseEvent(type, x, y) {
|
||||
var e = document.createEvent('MouseEvent');
|
||||
|
||||
e.initMouseEvent(type, true, true, window, 1, x, y, x, y,
|
||||
false, false, false, false, 0, null);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
function fakeDispatch(type, x, y) {
|
||||
var e;
|
||||
if (type.startsWith('mouse')) {
|
||||
e = forgeMouseEvent(type, x, y);
|
||||
} else {
|
||||
e = forgeTouchEvent(type, x, y);
|
||||
}
|
||||
subject.handleStatusbarTouch(e, 24);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
suite('Revealing the StatusBar >', function() {
|
||||
var transitionEndSpy;
|
||||
var element;
|
||||
setup(function() {
|
||||
element = subject.titleBar;
|
||||
transitionEndSpy = this.sinon.spy(element, 'addEventListener');
|
||||
});
|
||||
|
||||
function assertStatusBarReleased() {
|
||||
assert.isFalse(element.classList.contains('dragged'));
|
||||
}
|
||||
|
||||
function assertChromeBarDragging(isDragging) {
|
||||
assert.equal(subject.chromeBar.classList.contains('dragging'),
|
||||
isDragging);
|
||||
}
|
||||
|
||||
teardown(function() {
|
||||
this.sinon.clock.tick(10000);
|
||||
});
|
||||
|
||||
test('it should prevent default on mouse events',
|
||||
function() {
|
||||
var mousedown = fakeDispatch('mousedown', 100, 0);
|
||||
var mousemove = fakeDispatch('mousemove', 100, 2);
|
||||
var mouseup = fakeDispatch('mouseup', 100, 2);
|
||||
|
||||
assert.isTrue(mousedown.defaultPrevented);
|
||||
assert.isTrue(mousemove.defaultPrevented);
|
||||
assert.isTrue(mouseup.defaultPrevented);
|
||||
});
|
||||
|
||||
test('it should prevent default on all touch events to prevent reflows',
|
||||
function() {
|
||||
var touchstart = fakeDispatch('touchstart', 100, 0);
|
||||
var touchmove = fakeDispatch('touchmove', 100, 2);
|
||||
var touchend = fakeDispatch('touchend', 100, 2);
|
||||
|
||||
assert.isTrue(touchstart.defaultPrevented);
|
||||
assert.isTrue(touchmove.defaultPrevented);
|
||||
assert.isTrue(touchend.defaultPrevented);
|
||||
});
|
||||
|
||||
test('chromeBar dragging, then dragged then released when above ' +
|
||||
'threshold', function() {
|
||||
assertChromeBarDragging(false);
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
assertChromeBarDragging(true);
|
||||
fakeDispatch('touchmove', 100, 24);
|
||||
assertChromeBarDragging(true);
|
||||
fakeDispatch('touchend', 100, 25);
|
||||
assertChromeBarDragging(false);
|
||||
assert.isTrue(element.classList.contains('dragged'));
|
||||
});
|
||||
|
||||
test('chromeBar dragging then released when below threshold', function() {
|
||||
assertChromeBarDragging(false);
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
assertChromeBarDragging(true);
|
||||
fakeDispatch('touchmove', 100, 2);
|
||||
assertChromeBarDragging(true);
|
||||
fakeDispatch('touchend', 100, 2);
|
||||
assertChromeBarDragging(false);
|
||||
assertStatusBarReleased();
|
||||
});
|
||||
|
||||
test('it should stop the propagation of the events at first', function() {
|
||||
var fakeEvt = {
|
||||
stopImmediatePropagation: function() {},
|
||||
preventDefault: function() {},
|
||||
type: 'fake'
|
||||
};
|
||||
this.sinon.spy(fakeEvt, 'stopImmediatePropagation');
|
||||
subject.handleStatusbarTouch(fakeEvt, 24);
|
||||
sinon.assert.calledOnce(fakeEvt.stopImmediatePropagation);
|
||||
});
|
||||
|
||||
test('it should translate the statusbar on touchmove', function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 5);
|
||||
var transform = 'translateY(calc(5px - 100%))';
|
||||
assert.equal(element.style.transform, transform);
|
||||
fakeDispatch('touchend', 100, 5);
|
||||
});
|
||||
|
||||
test('it should set the dragged class on touchstart', function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
assert.isFalse(element.classList.contains('dragged'));
|
||||
fakeDispatch('touchmove', 100, 24);
|
||||
fakeDispatch('touchend', 100, 25);
|
||||
assert.isTrue(element.classList.contains('dragged'));
|
||||
});
|
||||
|
||||
test('it should not translate the statusbar more than its height',
|
||||
function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 5);
|
||||
fakeDispatch('touchmove', 100, 15);
|
||||
var transform = 'translateY(calc(15px - 100%))';
|
||||
assert.equal(element.style.transform, transform);
|
||||
fakeDispatch('touchend', 100, 15);
|
||||
});
|
||||
|
||||
suite('after the gesture', function() {
|
||||
suite('when the StatusBar is not fully displayed', function() {
|
||||
setup(function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 5);
|
||||
fakeDispatch('touchend', 100, 5);
|
||||
});
|
||||
|
||||
test('it should hide it right away', function() {
|
||||
assertStatusBarReleased();
|
||||
});
|
||||
});
|
||||
|
||||
suite('when the StatusBar is fully displayed', function() {
|
||||
setup(function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 5);
|
||||
fakeDispatch('touchmove', 100, 24);
|
||||
fakeDispatch('touchend', 100, 24);
|
||||
});
|
||||
|
||||
test('it should not hide it right away', function() {
|
||||
assert.equal(subject.titleBar.style.transform, '');
|
||||
assert.equal(subject.titleBar.style.transition, '');
|
||||
assert.ok(subject.titleBar.classList.contains('dragged'));
|
||||
});
|
||||
|
||||
test('but after 5 seconds', function() {
|
||||
this.sinon.clock.tick(5000);
|
||||
assertStatusBarReleased();
|
||||
});
|
||||
|
||||
test('or if the utility tray hides', function() {
|
||||
window.dispatchEvent(new CustomEvent('utilitytraywillshow'));
|
||||
assertStatusBarReleased();
|
||||
});
|
||||
|
||||
test('or if the user interacts with the app', function() {
|
||||
// We're faking a touchstart event on the app iframe
|
||||
var iframe = app.browser.element;
|
||||
subject._touchForwarder.destination = window;
|
||||
|
||||
var e = forgeTouchEvent('touchstart', 100, 100);
|
||||
window.dispatchEvent(e);
|
||||
|
||||
assertStatusBarReleased();
|
||||
subject._touchForwarder.destination = iframe;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Touch forwarding in fullscreen >', function() {
|
||||
var forwardSpy;
|
||||
|
||||
setup(function() {
|
||||
forwardSpy = this.sinon.spy(MockTouchForwarder.prototype, 'forward');
|
||||
});
|
||||
|
||||
test('it should forward taps to the app', function() {
|
||||
var touchstart = fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 2);
|
||||
var touchend = fakeDispatch('touchend', 100, 2);
|
||||
|
||||
assert.isTrue(forwardSpy.calledTwice);
|
||||
var call = forwardSpy.firstCall;
|
||||
assert.equal(call.args[0], touchstart);
|
||||
call = forwardSpy.getCall(1);
|
||||
assert.equal(call.args[0], touchend);
|
||||
});
|
||||
|
||||
suite('if it\'s not a tap and the statusbar is not fully displayed',
|
||||
function() {
|
||||
test('it should not forward any events', function() {
|
||||
fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 8);
|
||||
fakeDispatch('touchend', 100, 8);
|
||||
|
||||
assert.isTrue(forwardSpy.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
test('it should forward touchmove once the statusbar is shown',
|
||||
function() {
|
||||
var touchstart = fakeDispatch('touchstart', 100, 0);
|
||||
fakeDispatch('touchmove', 100, 6);
|
||||
var secondMove = fakeDispatch('touchmove', 100, 26);
|
||||
var thirdMove = fakeDispatch('touchmove', 100, 28);
|
||||
var touchend = fakeDispatch('touchend', 100, 2);
|
||||
|
||||
assert.equal(forwardSpy.callCount, 4);
|
||||
var call = forwardSpy.firstCall;
|
||||
assert.equal(call.args[0], touchstart);
|
||||
call = forwardSpy.getCall(1);
|
||||
assert.equal(call.args[0], secondMove);
|
||||
call = forwardSpy.getCall(2);
|
||||
assert.equal(call.args[0], thirdMove);
|
||||
call = forwardSpy.getCall(3);
|
||||
assert.equal(call.args[0], touchend);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
84
gaia/apps/system/test/unit/app_test.js
Executable file
84
gaia/apps/system/test/unit/app_test.js
Executable file
|
|
@ -0,0 +1,84 @@
|
|||
/* global MocksHelper, BaseModule, MockApplications,
|
||||
MockLazyLoader, App, Deferred */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/launcher.js');
|
||||
requireApp('system/js/core.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/test/unit/deferred.js');
|
||||
requireApp('system/js/app.js');
|
||||
|
||||
var mocksForLauncher = new MocksHelper([
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/app', function() {
|
||||
var subject;
|
||||
mocksForLauncher.attachTestHelpers();
|
||||
var FakeLauncher, FakeSettingsCore, FakeCore;
|
||||
var fakeLauncherStartDeferred;
|
||||
var fakeApplicationReadyDeferred;
|
||||
var fakeLazyLoaderDeferred;
|
||||
var fakeCoreStartDeferred;
|
||||
|
||||
suiteSetup(function() {
|
||||
window.applications = MockApplications;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
delete window.applications;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
fakeLazyLoaderDeferred = new Deferred();
|
||||
fakeLauncherStartDeferred = new Deferred();
|
||||
fakeApplicationReadyDeferred = new Deferred();
|
||||
fakeCoreStartDeferred = new Deferred();
|
||||
this.sinon.stub(MockLazyLoader, 'load').returns(
|
||||
fakeLauncherStartDeferred.promise);
|
||||
FakeCore = {
|
||||
start: sinon.spy(function() {
|
||||
return fakeCoreStartDeferred.promise;
|
||||
})
|
||||
};
|
||||
FakeSettingsCore = {
|
||||
start: this.sinon.spy()
|
||||
};
|
||||
FakeLauncher = {
|
||||
start: sinon.spy(function() {
|
||||
return fakeLauncherStartDeferred.promise;
|
||||
})
|
||||
};
|
||||
subject = new App();
|
||||
this.sinon.stub(MockApplications, 'waitForReady').returns(
|
||||
fakeApplicationReadyDeferred.promise);
|
||||
this.sinon.stub(BaseModule, 'instantiate', function(name) {
|
||||
switch (name) {
|
||||
case 'Core':
|
||||
return FakeCore;
|
||||
case 'SettingsCore':
|
||||
return FakeSettingsCore;
|
||||
case 'Launcher':
|
||||
return FakeLauncher;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Should launch SettingsCore, Launcher, Core', function(done) {
|
||||
subject.start().then(done, done);
|
||||
fakeLazyLoaderDeferred.resolve();
|
||||
fakeApplicationReadyDeferred.resolve();
|
||||
fakeLauncherStartDeferred.resolve();
|
||||
fakeCoreStartDeferred.resolve();
|
||||
Promise.all([
|
||||
fakeApplicationReadyDeferred.promise,
|
||||
fakeLauncherStartDeferred.promise
|
||||
]).then(function() {
|
||||
assert.isDefined(window.core);
|
||||
});
|
||||
});
|
||||
});
|
||||
770
gaia/apps/system/test/unit/app_text_selection_dialog_test.js
Executable file
770
gaia/apps/system/test/unit/app_text_selection_dialog_test.js
Executable file
|
|
@ -0,0 +1,770 @@
|
|||
/* global MocksHelper, MockService, AppTextSelectionDialog,
|
||||
MockSettingsListener */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_statusbar.js');
|
||||
|
||||
var mocksForAppTextSelectionDialog = new MocksHelper([
|
||||
'SettingsListener',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/AppTextSelectionDialog', function() {
|
||||
var td, fragment;
|
||||
var fakeTextSelectInAppEvent;
|
||||
mocksForAppTextSelectionDialog.attachTestHelpers();
|
||||
var mockDetail = {};
|
||||
setup(function(done) {
|
||||
MockService.mockQueryWith('LayoutManager.width', 360);
|
||||
MockService.mockQueryWith('LayoutManager.height', 480);
|
||||
MockService.mockQueryWith('Statusbar.height', 50);
|
||||
mockDetail = {
|
||||
type: 'caretstatechanged',
|
||||
detail: {
|
||||
commands: {},
|
||||
rect: {}
|
||||
},
|
||||
isCollapsed: false
|
||||
};
|
||||
|
||||
requireApp('system/js/base_ui.js');
|
||||
|
||||
requireApp('system/js/app_text_selection_dialog.js',
|
||||
function() {
|
||||
fragment = document.createElement('div');
|
||||
fragment.id = 'text-selection-dialog-root';
|
||||
document.body.appendChild(fragment);
|
||||
td = new AppTextSelectionDialog();
|
||||
fragment.innerHTML = td.view();
|
||||
td._isCommandSendable = true;
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
fakeTextSelectInAppEvent = {
|
||||
type: 'mozChromeEvent',
|
||||
preventDefault: function() {},
|
||||
stopPropagation: function() {}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
// navigator.mozL10n = realL10n;
|
||||
document.body.removeChild(fragment);
|
||||
fragment = null;
|
||||
td.globalStates.resetAllStates();
|
||||
td = null;
|
||||
mockDetail = {
|
||||
detail: {}
|
||||
};
|
||||
});
|
||||
|
||||
function verifyClickableOptions(config) {
|
||||
var lastOption;
|
||||
for (var item1 in config) {
|
||||
if(config[item1]) {
|
||||
lastOption = item1;
|
||||
mockDetail.detail.commands['can' + item1] = true;
|
||||
} else {
|
||||
mockDetail.detail.commands['can' + item1] = false;
|
||||
}
|
||||
}
|
||||
mockDetail.detail.collapsed = false;
|
||||
mockDetail.type = 'caretstatechanged';
|
||||
mockDetail.detail.caretVisible = true;
|
||||
mockDetail.detail.selectionVisible = true;
|
||||
mockDetail.detail.selectionEditable = true;
|
||||
fakeTextSelectInAppEvent.detail = mockDetail;
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
|
||||
if (lastOption) {
|
||||
assert.equal(td.element.classList.contains('visible'), true,
|
||||
'dialog should display');
|
||||
} else {
|
||||
assert.equal(td.element.classList.contains('visible'), false,
|
||||
'dialog should not display');
|
||||
return;
|
||||
}
|
||||
|
||||
for (var item2 in config) {
|
||||
var element = td.elements[item2.toLowerCase()];
|
||||
if (config[item2]) {
|
||||
assert.equal(element.classList.contains('hidden'),
|
||||
false, 'option of ' + item2 + ' should display');
|
||||
} else {
|
||||
assert.equal(element.classList.contains('hidden'),
|
||||
true, 'option of ' + item2 + ' should be hidden');
|
||||
}
|
||||
}
|
||||
assert.equal(
|
||||
td.elements[lastOption.toLowerCase()].classList.contains('last-option'),
|
||||
true, 'last-option class should be added to the last element of array');
|
||||
}
|
||||
|
||||
function emitClickEvent(ele) {
|
||||
var evt = document.createEvent('CustomEvent');
|
||||
evt.initCustomEvent('click', true, false, null);
|
||||
ele.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
test('test global states is the same in two apps', function() {
|
||||
var td2 = new AppTextSelectionDialog();
|
||||
assert.isTrue(td.globalStates === td2.globalStates);
|
||||
});
|
||||
|
||||
test('test appTSDs is correctly updated in global states', function() {
|
||||
assert.isTrue(td.globalStates.appTSDs.size == 1);
|
||||
assert.isTrue(td.globalStates.appTSDs.has(td));
|
||||
|
||||
var td2 = new AppTextSelectionDialog();
|
||||
assert.isTrue(td.globalStates.appTSDs.size == 2);
|
||||
assert.isTrue(td.globalStates.appTSDs.has(td2));
|
||||
});
|
||||
|
||||
test('switch settings value of copypaste.enabled', function() {
|
||||
var stubStart = this.sinon.stub(td, 'start');
|
||||
var stubStop = this.sinon.stub(td, 'stop');
|
||||
var td2 = new AppTextSelectionDialog();
|
||||
var stubStart2 = this.sinon.stub(td2, 'start');
|
||||
var stubStop2 = this.sinon.stub(td2, 'stop');
|
||||
|
||||
MockSettingsListener.mTriggerCallback('copypaste.enabled', false);
|
||||
assert.isFalse(td.globalStates._isPrefOn);
|
||||
assert.isTrue(stubStop.calledOnce);
|
||||
assert.isTrue(stubStop2.calledOnce);
|
||||
|
||||
MockSettingsListener.mTriggerCallback('copypaste.enabled', true);
|
||||
assert.isTrue(td.globalStates._isPrefOn);
|
||||
assert.isTrue(stubStart.calledOnce);
|
||||
assert.isTrue(stubStart2.calledOnce);
|
||||
});
|
||||
|
||||
test('_doCommand', function(done) {
|
||||
this.sinon.stub(td, 'close');
|
||||
window.addEventListener('mozContentEvent',
|
||||
function onReceiveMozContentEvent(evt) {
|
||||
window.removeEventListener('mozContentEvent', onReceiveMozContentEvent);
|
||||
assert.deepEqual(evt.detail, {
|
||||
type: 'copypaste-do-command',
|
||||
cmd: 'testCommand'
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
td._doCommand(fakeTextSelectInAppEvent, 'testCommand', true);
|
||||
assert.isTrue(td.close.calledOnce,
|
||||
'should call close when trigger _doCommand');
|
||||
});
|
||||
|
||||
test('_doCommand in app', function() {
|
||||
var stubPreventDefault = this.sinon.stub(fakeTextSelectInAppEvent,
|
||||
'preventDefault');
|
||||
var stubStopPropagation = this.sinon.stub(fakeTextSelectInAppEvent,
|
||||
'stopPropagation');
|
||||
this.sinon.stub(td, 'close');
|
||||
td.app = {
|
||||
element: true
|
||||
};
|
||||
td.textualmenuDetail = {
|
||||
sendDoCommandMsg: function() {}
|
||||
};
|
||||
this.sinon.stub(td.textualmenuDetail, 'sendDoCommandMsg');
|
||||
td._doCommand(fakeTextSelectInAppEvent, 'testCommand', true);
|
||||
assert.isTrue(td.textualmenuDetail.sendDoCommandMsg
|
||||
.calledWith('testCommand'));
|
||||
assert.isTrue(td.close.calledOnce,
|
||||
'should call close when trigger _doCommand');
|
||||
assert.isTrue(stubPreventDefault.calledOnce);
|
||||
assert.isTrue(stubStopPropagation.calledOnce);
|
||||
});
|
||||
|
||||
test('_doCommand, when _isCommandSendable is false', function() {
|
||||
this.sinon.stub(td, 'close');
|
||||
td._isCommandSendable = false;
|
||||
td._doCommand();
|
||||
assert.isFalse(td.close.calledOnce,
|
||||
'should not call close');
|
||||
});
|
||||
|
||||
test('_doCommand, when _isCommandSendable is true and close dialog directly',
|
||||
function() {
|
||||
this.sinon.stub(td, 'close');
|
||||
td._doCommand(fakeTextSelectInAppEvent, 'testCommand', true);
|
||||
assert.isTrue(td.close.calledOnce,
|
||||
'should call close');
|
||||
});
|
||||
|
||||
test('when user press a button and move finger out of it', function() {
|
||||
td.render();
|
||||
td._isCommandSendable = false;
|
||||
td.elements.cut.dispatchEvent(new CustomEvent('mousedown'));
|
||||
assert.isTrue(td._isCommandSendable, 'should set _isCommandSendable true' +
|
||||
' when mousedown');
|
||||
td.elements.cut.dispatchEvent(new CustomEvent('mouseout'));
|
||||
assert.isFalse(td._isCommandSendable, 'should set _isCommandSendable' +
|
||||
' false when mouseleave');
|
||||
});
|
||||
|
||||
test('copyHandler', function() {
|
||||
var stubDoCommand = this.sinon.stub(td, '_doCommand');
|
||||
var stubSetTimeout = this.sinon.stub(window, 'setTimeout').returns(123);
|
||||
td.copyHandler(null);
|
||||
assert.isTrue(td.globalStates.hasCutOrCopied());
|
||||
assert.isTrue(stubDoCommand.calledWith(null, 'copy'));
|
||||
assert.isTrue(stubSetTimeout.calledOnce);
|
||||
});
|
||||
|
||||
test('cutHandler', function() {
|
||||
var stubDoCommand = this.sinon.stub(td, '_doCommand');
|
||||
var stubSetTimeout = this.sinon.stub(window, 'setTimeout').returns(123);
|
||||
td.cutHandler(null);
|
||||
assert.isTrue(td.globalStates.hasCutOrCopied());
|
||||
assert.isTrue(stubDoCommand.calledWith(null, 'cut'));
|
||||
assert.isTrue(stubSetTimeout.calledOnce);
|
||||
});
|
||||
|
||||
test('pasteHandler', function() {
|
||||
var stubDoCommand = this.sinon.stub(td, '_doCommand');
|
||||
var stubClearTimeout = this.sinon.stub(window, 'clearTimeout');
|
||||
td.pasteHandler(null);
|
||||
assert.isFalse(td.globalStates.hasCutOrCopied());
|
||||
assert.isTrue(stubDoCommand.calledWith(null, 'paste'));
|
||||
assert.isTrue(stubClearTimeout.calledOnce);
|
||||
});
|
||||
|
||||
test('close', function() {
|
||||
td._transitionState = 'opened';
|
||||
td.render();
|
||||
var stubHide = this.sinon.stub(td, 'hide');
|
||||
this.sinon.stub(td.element, 'blur');
|
||||
td.close();
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
assert.isTrue(td.element.blur.called);
|
||||
});
|
||||
|
||||
test('updateDialogPosition', function() {
|
||||
td.element = document.createElement('div');
|
||||
var stubChangeTransitionState = this.sinon.stub(td,
|
||||
'_changeTransitionState');
|
||||
this.sinon.stub(td, 'calculateDialogPostion').returns(
|
||||
{top: 123, left: 321});
|
||||
td.updateDialogPosition();
|
||||
assert.equal(td.element.style.top, '123px');
|
||||
assert.equal(td.element.style.left, '321px');
|
||||
assert.isTrue(stubChangeTransitionState.calledWith('opened'));
|
||||
});
|
||||
|
||||
suite('handleEvent caretstatechanged event', function() {
|
||||
var stubClose, stubHide, stubShow, stubRender, stubEvent;
|
||||
var testDetail;
|
||||
setup(function() {
|
||||
stubClose = this.sinon.stub(td, 'close');
|
||||
stubHide = this.sinon.stub(td, 'hide');
|
||||
stubShow = this.sinon.stub(td, 'show');
|
||||
stubRender = this.sinon.stub(td, 'render');
|
||||
stubEvent = this.sinon.stub(fakeTextSelectInAppEvent, 'preventDefault');
|
||||
testDetail = {
|
||||
collapsed: false,
|
||||
selectionVisible: true,
|
||||
caretVisible: true,
|
||||
rect: {
|
||||
top: 20,
|
||||
bottom: 30,
|
||||
left: 10,
|
||||
right: 20
|
||||
},
|
||||
commands: {
|
||||
canPaste: true,
|
||||
canSelectAll: true
|
||||
}
|
||||
};
|
||||
|
||||
fakeTextSelectInAppEvent.detail = {
|
||||
type: 'caretstatechanged',
|
||||
detail: testDetail
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
td.globalStates.resetAllStates();
|
||||
});
|
||||
|
||||
test('tap on other place, and the caret is collapsed',
|
||||
function() {
|
||||
testDetail.collapsed = true;
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isFalse(stubShow.calledOnce);
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
});
|
||||
|
||||
test('press caret', function() {
|
||||
testDetail.reason = 'presscaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubHide.calledOnce, 'should hide bubble since user would' +
|
||||
' like to move caret');
|
||||
});
|
||||
|
||||
test('tap on caret while the selection is collapsed',
|
||||
function() {
|
||||
testDetail.collapsed = true;
|
||||
testDetail.reason = 'taponcaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubShow.calledWith(testDetail));
|
||||
assert.isFalse(testDetail.commands.canSelectAll);
|
||||
});
|
||||
|
||||
test('should not render when bubble has showed before', function() {
|
||||
td._injected = true;
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isFalse(stubRender.calledOnce);
|
||||
});
|
||||
|
||||
test('should call hide when timeout of shortcut has reached and ' +
|
||||
'single-tap on the context', function() {
|
||||
testDetail.collapsed = true;
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
});
|
||||
|
||||
test('should call hide when selection is changed to invisible', function() {
|
||||
testDetail.caretVisible = false;
|
||||
testDetail.reason = 'visibilitychange';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
});
|
||||
|
||||
test('should show bubble if reason is updateposition, and has selection',
|
||||
function() {
|
||||
testDetail.reason = 'updateposition';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubShow.calledWith(testDetail));
|
||||
});
|
||||
|
||||
test('should hide bubble when selection is collapsed, and not cut or' +
|
||||
'copied', function() {
|
||||
testDetail.collapsed = true;
|
||||
testDetail.reason = 'updateposition';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
});
|
||||
|
||||
test('should show bubble when selection is collapsed after pressing and ' +
|
||||
'release caret', function() {
|
||||
td._transitionState = 'opened';
|
||||
testDetail.collapsed = true;
|
||||
testDetail.reason = 'presscaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
testDetail.reason = 'releasecaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
|
||||
assert.isTrue(stubHide.calledOnce);
|
||||
assert.isTrue(stubShow.calledWith(testDetail));
|
||||
assert.isTrue(stubHide.calledBefore(stubShow));
|
||||
});
|
||||
|
||||
test('should hide bubble when selection is collapsed after pressing and ' +
|
||||
'release caret', function() {
|
||||
td._transitionState = 'closed';
|
||||
testDetail.collapsed = true;
|
||||
testDetail.reason = 'presscaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
testDetail.reason = 'releasecaret';
|
||||
td.handleEvent(fakeTextSelectInAppEvent);
|
||||
|
||||
assert.isTrue(stubHide.calledTwice);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_elementEventHandler', function() {
|
||||
test('on mousedown', function() {
|
||||
var stubPreventDefault = this.sinon.stub(fakeTextSelectInAppEvent,
|
||||
'preventDefault');
|
||||
td._isCommandSendable = false;
|
||||
fakeTextSelectInAppEvent.type = 'mousedown';
|
||||
td._elementEventHandler(fakeTextSelectInAppEvent);
|
||||
assert.isTrue(td._isCommandSendable);
|
||||
assert.isTrue(stubPreventDefault.calledOnce);
|
||||
delete fakeTextSelectInAppEvent.type;
|
||||
});
|
||||
|
||||
test('on transitionend', function() {
|
||||
var stubChangeTransitionState = this.sinon.stub(td,
|
||||
'_changeTransitionState');
|
||||
td._transitionState = 'closing';
|
||||
td._elementEventHandler({ type: 'transitionend' });
|
||||
assert.isTrue(stubChangeTransitionState.calledWith('closed'));
|
||||
});
|
||||
|
||||
test('on click', function() {
|
||||
var fakeEvt = {
|
||||
type: 'click',
|
||||
target: {
|
||||
dataset: {
|
||||
action: 'cut'
|
||||
}
|
||||
}
|
||||
};
|
||||
var stubCutHandler = this.sinon.stub(td,
|
||||
'cutHandler');
|
||||
td._elementEventHandler(fakeEvt);
|
||||
assert.isTrue(stubCutHandler.calledWith(fakeEvt));
|
||||
});
|
||||
|
||||
test('on mouseout', function() {
|
||||
td._isCommandSendable = true;
|
||||
td._elementEventHandler({ type: 'mouseout' });
|
||||
assert.isFalse(td._isCommandSendable);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_changeTransitionState', function() {
|
||||
setup(function() {
|
||||
td.element = document.createElement('div');
|
||||
});
|
||||
|
||||
test('change state to opened', function() {
|
||||
td._changeTransitionState('opened');
|
||||
assert.isTrue(td.element.classList.contains('active'));
|
||||
assert.isTrue(td.element.classList.contains('visible'));
|
||||
assert.equal(td._transitionState, 'opened');
|
||||
});
|
||||
|
||||
test('change state to opened', function() {
|
||||
td.element.classList.add('visible');
|
||||
td._changeTransitionState('closing');
|
||||
assert.isFalse(td.element.classList.contains('visible'));
|
||||
assert.equal(td._transitionState, 'closing');
|
||||
});
|
||||
|
||||
test('change state to opened', function() {
|
||||
td.element.classList.add('active');
|
||||
td._changeTransitionState('closed');
|
||||
assert.isFalse(td.element.classList.contains('active'));
|
||||
assert.equal(td._transitionState, 'closed');
|
||||
});
|
||||
});
|
||||
|
||||
suite('check functionality of each button', function() {
|
||||
var stubDoCommand;
|
||||
setup(function() {
|
||||
stubDoCommand = sinon.stub(td, '_doCommand');
|
||||
td.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
td.stop();
|
||||
stubDoCommand = null;
|
||||
});
|
||||
|
||||
test('option display', function() {
|
||||
verifyClickableOptions({
|
||||
'Paste': false,
|
||||
'Copy': false,
|
||||
'Cut': true,
|
||||
'SelectAll': true
|
||||
});
|
||||
|
||||
verifyClickableOptions({
|
||||
'Paste': true,
|
||||
'Copy': false,
|
||||
'Cut': false,
|
||||
'SelectAll': false
|
||||
});
|
||||
});
|
||||
|
||||
test('option handler, selectAll', function() {
|
||||
verifyClickableOptions({
|
||||
'Paste': true,
|
||||
'Copy': true,
|
||||
'Cut': true,
|
||||
'SelectAll': true
|
||||
});
|
||||
emitClickEvent(td.elements.selectall);
|
||||
assert.equal(stubDoCommand.getCall(0).args[1], 'selectall');
|
||||
});
|
||||
|
||||
test('option handler, paste', function() {
|
||||
verifyClickableOptions({
|
||||
'Paste': true,
|
||||
'Copy': true,
|
||||
'Cut': true,
|
||||
'SelectAll': true
|
||||
});
|
||||
emitClickEvent(td.elements.paste);
|
||||
assert.equal(stubDoCommand.getCall(0).args[1], 'paste');
|
||||
});
|
||||
|
||||
test('option handler, cut', function() {
|
||||
verifyClickableOptions({
|
||||
'Paste': true,
|
||||
'Copy': true,
|
||||
'Cut': true,
|
||||
'SelectAll': true
|
||||
});
|
||||
emitClickEvent(td.elements.cut);
|
||||
assert.equal(stubDoCommand.getCall(0).args[1], 'cut');
|
||||
});
|
||||
|
||||
test('option handler, copy', function() {
|
||||
verifyClickableOptions({
|
||||
'Paste': true,
|
||||
'Copy': true,
|
||||
'Cut': true,
|
||||
'SelectAll': true
|
||||
});
|
||||
emitClickEvent(td.elements.copy);
|
||||
assert.equal(stubDoCommand.getCall(0).args[1], 'copy');
|
||||
});
|
||||
});
|
||||
|
||||
suite('dialog position', function() {
|
||||
var windowHeight;
|
||||
var windowWidth;
|
||||
setup(function() {
|
||||
windowHeight = MockService.mockQueryWith('LayoutManager.height');
|
||||
windowWidth = MockService.mockQueryWith('LayoutManager.width');
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP = 40;
|
||||
td.DISTANCE_FROM_MENUBOTTOM_TO_SELECTEDAREA = 12;
|
||||
td.DISTANCE_FROM_BOUNDARY = 5;
|
||||
td.TEXTDIALOG_WIDTH = 48;
|
||||
td.TEXTDIALOG_HEIGHT = 46;
|
||||
});
|
||||
|
||||
test('if space above is enough', function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = windowHeight - 120;
|
||||
positionDetail.rect.bottom = windowHeight - 20;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.top * positionDetail.zoomFactor -
|
||||
td.TEXTDIALOG_HEIGHT - td.DISTANCE_FROM_MENUBOTTOM_TO_SELECTEDAREA,
|
||||
left: ((positionDetail.rect.left + positionDetail.rect.right) *
|
||||
positionDetail.zoomFactor - td.numOfSelectOptions *
|
||||
td.TEXTDIALOG_WIDTH)/ 2
|
||||
});
|
||||
});
|
||||
|
||||
test('if no space above', function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 100;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP,
|
||||
left: ((positionDetail.rect.left + positionDetail.rect.right) *
|
||||
positionDetail.zoomFactor -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH)/ 2
|
||||
});
|
||||
});
|
||||
|
||||
test('if no space above and underneath', function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 10;
|
||||
positionDetail.rect.left = windowWidth - 10;
|
||||
positionDetail.rect.right = windowWidth;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: (positionDetail.rect.top * positionDetail.zoomFactor +
|
||||
positionDetail.rect.bottom * positionDetail.zoomFactor -
|
||||
td.TEXTDIALOG_HEIGHT) / 2,
|
||||
left: windowWidth -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH -
|
||||
td.DISTANCE_FROM_BOUNDARY
|
||||
});
|
||||
});
|
||||
|
||||
test('if utility bubble can overlay the header, and not app', function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 100;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP,
|
||||
left: ((positionDetail.rect.left + positionDetail.rect.right) *
|
||||
positionDetail.zoomFactor -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH)/ 2
|
||||
});
|
||||
});
|
||||
|
||||
test('if the utility bubble is triggered in app and appChrome is maxmized',
|
||||
function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
td.app = {
|
||||
appChrome: {
|
||||
isMaximized: function() {
|
||||
return true;
|
||||
},
|
||||
scrollable: {
|
||||
scrollTop: 25
|
||||
},
|
||||
height: 40
|
||||
}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 150;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP + td.app.appChrome.height -
|
||||
td.app.appChrome.scrollable.scrollTop,
|
||||
left: ((positionDetail.rect.left + positionDetail.rect.right) *
|
||||
positionDetail.zoomFactor -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH)/ 2
|
||||
});
|
||||
});
|
||||
|
||||
test('if the utility bubble is triggered in app and appChrome is ' +
|
||||
'not maximized',
|
||||
function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
td.app = {
|
||||
appChrome: {
|
||||
isMaximized: function() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 150;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP + 50,
|
||||
left: ((positionDetail.rect.left + positionDetail.rect.right) *
|
||||
positionDetail.zoomFactor -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH)/ 2
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('if utility bubble can overlay the header and zoom factor is 2 ',
|
||||
function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 100;
|
||||
positionDetail.rect.left = windowWidth - 300;
|
||||
positionDetail.rect.right = windowWidth - 100;
|
||||
positionDetail.zoomFactor = 2;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
var posTop;
|
||||
if (positionDetail.rect.bottom * positionDetail.zoomFactor >=
|
||||
windowHeight) {
|
||||
posTop = (positionDetail.rect.top * positionDetail.zoomFactor +
|
||||
windowHeight - td.TEXTDIALOG_HEIGHT) / 2;
|
||||
} else {
|
||||
posTop = ((positionDetail.rect.top + positionDetail.rect.bottom) *
|
||||
positionDetail.zoomFactor - td.TEXTDIALOG_HEIGHT) / 2;
|
||||
}
|
||||
assert.deepEqual(result, {
|
||||
top: posTop,
|
||||
left: windowWidth - td.numOfSelectOptions * td.TEXTDIALOG_WIDTH -
|
||||
td.DISTANCE_FROM_BOUNDARY
|
||||
});
|
||||
});
|
||||
|
||||
test('if utility bubble can overlay the left boundary',
|
||||
function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 100;
|
||||
positionDetail.rect.left = 10;
|
||||
positionDetail.rect.right = 20;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP,
|
||||
left: td.DISTANCE_FROM_BOUNDARY
|
||||
});
|
||||
});
|
||||
|
||||
test('if utility bubble can overlay the right boundary',
|
||||
function() {
|
||||
var positionDetail = {
|
||||
rect: {}
|
||||
};
|
||||
positionDetail.rect.top = 10;
|
||||
positionDetail.rect.bottom = windowHeight - 100;
|
||||
positionDetail.rect.left = windowWidth - 10;
|
||||
positionDetail.rect.right = windowWidth;
|
||||
positionDetail.zoomFactor = 1;
|
||||
td.textualmenuDetail = positionDetail;
|
||||
td.numOfSelectOptions = 3;
|
||||
var result =
|
||||
td.calculateDialogPostion(0, 0);
|
||||
assert.deepEqual(result, {
|
||||
top: positionDetail.rect.bottom * positionDetail.zoomFactor +
|
||||
td.DISTANCE_FROM_SELECTEDAREA_TO_MENUTOP,
|
||||
left: windowWidth -
|
||||
td.numOfSelectOptions * td.TEXTDIALOG_WIDTH -
|
||||
td.DISTANCE_FROM_BOUNDARY
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
409
gaia/apps/system/test/unit/app_transition_controller_test.js
Executable file
409
gaia/apps/system/test/unit/app_transition_controller_test.js
Executable file
|
|
@ -0,0 +1,409 @@
|
|||
/* global MocksHelper, MockAppWindow, MockService, AppTransitionController,
|
||||
MockHomescreenWindow */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_homescreen_window.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_app_window_manager.js');
|
||||
requireApp('system/test/unit/mock_layout_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForAppTransitionController = new MocksHelper([
|
||||
'AppWindow', 'AppWindowManager', 'LayoutManager',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/AppTransitionController', function() {
|
||||
var stubById;
|
||||
mocksForAppTransitionController.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
requireApp('system/js/app_transition_controller.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
test('New as closed', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
assert.isTrue(acn1._transitionState === 'closed');
|
||||
});
|
||||
|
||||
test('Open', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
assert.deepEqual(acn1._transitionState, 'closed');
|
||||
acn1.requireOpen();
|
||||
assert.deepEqual(acn1._transitionState, 'opening');
|
||||
});
|
||||
|
||||
test('Open with immediate animation', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
this.sinon.stub(app1, 'publish');
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
assert.deepEqual(acn1._transitionState, 'closed');
|
||||
acn1.requireOpen('immediate');
|
||||
assert.deepEqual(acn1._transitionState, 'opened');
|
||||
sinon.assert.calledWith(app1.publish, 'opening');
|
||||
});
|
||||
|
||||
test('Close', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
acn1._transitionState = 'opened';
|
||||
acn1.requireClose();
|
||||
assert.deepEqual(acn1._transitionState, 'closing');
|
||||
});
|
||||
|
||||
test('Close with immediate animation', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
this.sinon.stub(app1, 'publish');
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
acn1._transitionState = 'opened';
|
||||
acn1.requireClose('immediate');
|
||||
assert.deepEqual(acn1._transitionState, 'closed');
|
||||
sinon.assert.calledWith(app1.publish, 'closing');
|
||||
});
|
||||
|
||||
test('Closed notfication', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
acn1._transitionState = 'closing';
|
||||
acn1.handleEvent({ type: '_closed' });
|
||||
});
|
||||
|
||||
test('Opened notification', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubRequestForeground = this.sinon.stub(app1, 'requestForeground');
|
||||
acn1._transitionState = 'opening';
|
||||
acn1.handleEvent({ type: '_opened' });
|
||||
assert.isTrue(stubRequestForeground.calledOnce);
|
||||
});
|
||||
|
||||
test('Animation start event', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
acn1._transitionState = 'opening';
|
||||
acn1.handleEvent({ type: 'animationstart' });
|
||||
});
|
||||
|
||||
test('Animation end event', function() {
|
||||
MockService.mockQueryWith('isBusyLoading', false);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var spy = this.sinon.spy();
|
||||
acn1._transitionState = 'opening';
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: spy
|
||||
});
|
||||
assert.isTrue(spy.called);
|
||||
assert.equal(acn1._transitionState, 'opened');
|
||||
});
|
||||
|
||||
test('Animation end event when closing', function() {
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var spy = this.sinon.spy();
|
||||
acn1._transitionState = 'closing';
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: spy
|
||||
});
|
||||
assert.isTrue(spy.called);
|
||||
assert.equal(acn1._transitionState, 'closed');
|
||||
});
|
||||
|
||||
test('Complete on animationend on the Browser when loading', function() {
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
this.sinon.stub(app1, 'isBrowser').returns(true);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var spy = this.sinon.spy();
|
||||
acn1._transitionState = 'opening';
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: spy
|
||||
});
|
||||
assert.isTrue(spy.called);
|
||||
assert.equal(acn1._transitionState, 'opened');
|
||||
});
|
||||
|
||||
test('Complete on _loaded event if we discarded the animationend',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stopStub = this.sinon.stub();
|
||||
acn1._transitionState = 'opening';
|
||||
|
||||
app1.element.classList.add('transition-opening');
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: stopStub
|
||||
});
|
||||
assert.isFalse(app1.element.classList.contains('transition-opening'));
|
||||
assert.equal(acn1._transitionState, 'opening');
|
||||
|
||||
MockService.mockQueryWith('isBusyLoading', false);
|
||||
acn1.handleEvent({
|
||||
type: '_loaded',
|
||||
stopPropagation: stopStub
|
||||
});
|
||||
assert.equal(acn1._transitionState, 'opened');
|
||||
});
|
||||
|
||||
test('Discard animationend event if system is busy', function() {
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var spy = this.sinon.spy();
|
||||
var stubPublish = this.sinon.stub(app1, 'publish');
|
||||
acn1._transitionState = 'opening';
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: spy
|
||||
});
|
||||
assert.equal(acn1._transitionState, 'opening');
|
||||
assert.isFalse(stubPublish.called);
|
||||
});
|
||||
|
||||
test('Discard animationend event if system is busy', function() {
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
app1.isHomescreen = true;
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var spy = this.sinon.spy();
|
||||
acn1._transitionState = 'opening';
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: spy
|
||||
});
|
||||
assert.isTrue(stubFocus.called);
|
||||
});
|
||||
|
||||
test('Handle opening', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubReviveBrowser = this.sinon.stub(app1, 'reviveBrowser');
|
||||
acn1.handle_opening();
|
||||
assert.isTrue(stubReviveBrowser.called);
|
||||
});
|
||||
|
||||
test('Handle opening', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubReviveBrowser = this.sinon.stub(app1, 'reviveBrowser');
|
||||
acn1.handle_opening();
|
||||
assert.isTrue(stubReviveBrowser.called);
|
||||
});
|
||||
|
||||
test('Handle opening of callscreen window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubSetOrientation = this.sinon.stub(app1, 'setOrientation');
|
||||
app1.isCallscreenWindow = true;
|
||||
acn1.handle_opening();
|
||||
assert.isTrue(stubSetOrientation.calledOnce);
|
||||
});
|
||||
|
||||
test('Warm launch event', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
app1.loaded = true;
|
||||
acn1.handle_opening();
|
||||
var stubPublish = this.sinon.stub(app1, 'publish');
|
||||
app1.element.dispatchEvent(new CustomEvent('_opened'));
|
||||
assert.isTrue(stubPublish.called);
|
||||
assert.equal(stubPublish.getCall(0).args[1].type, 'w');
|
||||
});
|
||||
|
||||
test('Focus will happen after loaded and opened', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
|
||||
app1.loaded = false;
|
||||
acn1._transitionState = 'opening';
|
||||
MockService.mockQueryWith('getTopMostUI', {
|
||||
name: 'AppWindowManager'
|
||||
});
|
||||
MockService.mockQueryWith('getTopMostWindow', app1);
|
||||
|
||||
MockService.mockQueryWith('isBusyLoading', true);
|
||||
acn1.handleEvent({
|
||||
type: 'animationend',
|
||||
stopPropagation: function() {}
|
||||
});
|
||||
assert.isFalse(stubFocus.called);
|
||||
|
||||
MockService.mockQueryWith('isBusyLoading', false);
|
||||
acn1.handleEvent({
|
||||
type: '_loaded',
|
||||
stopPropagation: function() {}
|
||||
});
|
||||
acn1.handle_opened();
|
||||
|
||||
assert.isTrue(stubFocus.called);
|
||||
});
|
||||
|
||||
test('Focus will happen once next paint', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
app1.loaded = true;
|
||||
MockService.mockQueryWith('getTopMostUI', {
|
||||
name: 'AppWindowManager'
|
||||
});
|
||||
MockService.mockQueryWith('getTopMostWindow', app1);
|
||||
|
||||
acn1._transitionState = 'opened';
|
||||
|
||||
acn1.handle_opened();
|
||||
|
||||
assert.isTrue(stubFocus.called);
|
||||
});
|
||||
|
||||
test('Should focus homescreen\'s activity', function() {
|
||||
var app1 = new MockHomescreenWindow('fake');
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
this.sinon.stub(app1, 'setNFCFocus');
|
||||
app1.loaded = true;
|
||||
MockService.mockQueryWith('getTopMostUI', {
|
||||
name: 'AppWindowManager'
|
||||
});
|
||||
MockService.mockQueryWith('getTopMostWindow', app1);
|
||||
|
||||
acn1._transitionState = 'opened';
|
||||
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubFocus.called);
|
||||
assert.isTrue(app1.setNFCFocus.calledWith(true));
|
||||
});
|
||||
|
||||
test('Do not focus if we are not top most window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
this.sinon.stub(app1, 'setNFCFocus');
|
||||
app1.loaded = true;
|
||||
MockService.mockQueryWith('getTopMostUI', {
|
||||
name: 'AppWindowManager'
|
||||
});
|
||||
MockService.mockQueryWith('getTopMostWindow', null);
|
||||
|
||||
acn1._transitionState = 'opened';
|
||||
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubFocus.notCalled);
|
||||
assert.isFalse(app1.setNFCFocus.called);
|
||||
});
|
||||
|
||||
test('Do not focus on alwaysLowered window', function() {
|
||||
var alwaysLoweredConfig = Object.assign({}, fakeAppConfig1);
|
||||
alwaysLoweredConfig.stayBackground = true;
|
||||
var app1 = new MockAppWindow(alwaysLoweredConfig);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
app1.loaded = true;
|
||||
acn1._transitionState = 'opened';
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubFocus.notCalled);
|
||||
});
|
||||
|
||||
test('Do not focus the search window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
app1.CLASS_NAME = 'SearchWindow';
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubFocus = this.sinon.stub(app1, 'focus');
|
||||
app1.loaded = true;
|
||||
MockService.mockQueryWith('getTopMostUI', {
|
||||
name: 'AppWindowManager'
|
||||
});
|
||||
MockService.mockQueryWith('getTopMostWindow', app1);
|
||||
|
||||
acn1._transitionState = 'opened';
|
||||
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubFocus.notCalled);
|
||||
});
|
||||
|
||||
suite('Opened', function() {
|
||||
var app1, acn1, stubRequestForeground, stubSetOrientation, stubShow;
|
||||
setup(function() {
|
||||
this.sinon.useFakeTimers();
|
||||
app1 = new MockAppWindow(fakeAppConfig1);
|
||||
acn1 = new AppTransitionController(app1);
|
||||
stubRequestForeground = this.sinon.stub(app1, 'requestForeground');
|
||||
stubSetOrientation = this.sinon.stub(app1, 'setOrientation');
|
||||
stubShow = this.sinon.stub(app1, 'show');
|
||||
this.sinon.stub(app1, 'reviveBrowser');
|
||||
});
|
||||
|
||||
test('Handle opened', function() {
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubRequestForeground.calledOnce);
|
||||
assert.isTrue(stubShow.called);
|
||||
assert.isTrue(stubSetOrientation.called);
|
||||
assert.isTrue(app1.reviveBrowser.called);
|
||||
});
|
||||
|
||||
test('Handle opened when the transition is immediate', function() {
|
||||
acn1.currentAnimation = 'immediate';
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubShow.called);
|
||||
assert.isTrue(stubSetOrientation.called);
|
||||
assert.isTrue(app1.reviveBrowser.called);
|
||||
|
||||
assert.isFalse(stubRequestForeground.calledOnce);
|
||||
this.sinon.clock.tick();
|
||||
assert.isTrue(stubRequestForeground.calledOnce);
|
||||
});
|
||||
|
||||
test('Handle opened if the new window is callscreenWindow', function() {
|
||||
app1.isCallscreenWindow = true;
|
||||
acn1.handle_opened();
|
||||
assert.isTrue(stubRequestForeground.calledOnce);
|
||||
assert.isTrue(stubShow.called);
|
||||
assert.isFalse(stubSetOrientation.called);
|
||||
app1.element.classList.remove('callscreenWindow');
|
||||
});
|
||||
});
|
||||
|
||||
test('Handle closing for attention windows', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
var stubSetVisible = this.sinon.stub(app1, 'setVisible');
|
||||
acn1.handle_closing();
|
||||
assert.isTrue(stubSetVisible.calledWith(false));
|
||||
});
|
||||
|
||||
test('Handle closed', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
this.sinon.stub(app1, 'setNFCFocus');
|
||||
acn1.handle_closed();
|
||||
assert.isTrue(app1.setNFCFocus.calledWith(false));
|
||||
});
|
||||
|
||||
test('Do not send to background in closed handler for attention windows',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var acn1 = new AppTransitionController(app1);
|
||||
acn1.handle_closed();
|
||||
});
|
||||
});
|
||||
1262
gaia/apps/system/test/unit/app_usage_metrics_test.js
Executable file
1262
gaia/apps/system/test/unit/app_usage_metrics_test.js
Executable file
File diff suppressed because it is too large
Load diff
508
gaia/apps/system/test/unit/app_window_factory_test.js
Executable file
508
gaia/apps/system/test/unit/app_window_factory_test.js
Executable file
|
|
@ -0,0 +1,508 @@
|
|||
/* global MocksHelper,
|
||||
AppWindowFactory,
|
||||
MockApplications,
|
||||
AppWindow,
|
||||
HomescreenLauncher,
|
||||
appWindowFactory,
|
||||
MockAppWindow,
|
||||
MockService
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_manifest_helper.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_homescreen_window.js');
|
||||
requireApp('system/test/unit/mock_homescreen_launcher.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_manifest_helper.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForAppWindowFactory = new MocksHelper([
|
||||
'AppWindow', 'HomescreenLauncher',
|
||||
'HomescreenWindow', 'Applications', 'ManifestHelper', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/AppWindowFactory', function() {
|
||||
mocksForAppWindowFactory.attachTestHelpers();
|
||||
var stubById;
|
||||
var fakeLaunchConfig1 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://fakeapp1.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 1',
|
||||
'manifestURL': 'app://fakeapp1.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp1.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 1'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig2 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://fakeapp2.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 2',
|
||||
'manifestURL': 'app://fakeapp2.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp2.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 2'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig3 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://fakeapp3.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 3',
|
||||
'manifestURL': 'app://fakeapp3.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp3.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 3'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig4 = {
|
||||
'isActivity': true,
|
||||
'url': 'app://fakeapp4.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 4',
|
||||
'manifestURL': 'app://fakeapp4.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp4.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 4'
|
||||
},
|
||||
target: {
|
||||
disposition: 'inline'
|
||||
},
|
||||
extra: {
|
||||
manifestURL: 'app://fakeapp3.gaiamobile.org/manifest.webapp'
|
||||
}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig5 = {
|
||||
'isActivity': true,
|
||||
'url': 'app://fakeapp5.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 5',
|
||||
'manifestURL': 'app://fakeapp5.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp5.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 5'
|
||||
},
|
||||
target: {},
|
||||
extra: {
|
||||
manifestURL: 'app://fakeapp3.gaiamobile.org/manifest.webapp'
|
||||
}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig6 = {
|
||||
'isActivity': false,
|
||||
'url': window.location.href,
|
||||
'name': 'System',
|
||||
'manifestURL': 'app://system.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://system.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'System'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig7 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://search.gaiamobile.org/index.html',
|
||||
'name': 'search',
|
||||
'manifestURL': 'app://search.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://search.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Search',
|
||||
'role': 'search',
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var fakeLaunchConfig8 = {
|
||||
'isActivity': false,
|
||||
'showApp': false,
|
||||
'url': 'app://findmydevice.gaiamobile.org/index.html',
|
||||
'name': 'Find my device',
|
||||
'manifestURL': 'app://findmydevice.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://findmydevice.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Find my device',
|
||||
'role': 'system',
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
var realApplications;
|
||||
|
||||
setup(function(done) {
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig1);
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig2);
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig3);
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig4);
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig5);
|
||||
|
||||
realApplications = window.applications;
|
||||
window.applications = MockApplications;
|
||||
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
window.homescreenLauncher = new HomescreenLauncher();
|
||||
window.homescreenLauncher.start();
|
||||
|
||||
requireApp('system/js/browser_config_helper.js');
|
||||
requireApp('system/js/app_window_factory.js', function() {
|
||||
window.appWindowFactory = new AppWindowFactory();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.homescreenLauncher = undefined;
|
||||
window.appWindowFactory.stop();
|
||||
window.appWindowFactory = undefined;
|
||||
stubById.restore();
|
||||
window.applications = realApplications;
|
||||
realApplications = null;
|
||||
});
|
||||
|
||||
suite('isLaunchingWindow', function() {
|
||||
var app;
|
||||
setup(function() {
|
||||
app = new MockAppWindow();
|
||||
this.sinon.stub(window, 'AppWindow').returns(app);
|
||||
window.applications.ready = true;
|
||||
window.appWindowFactory.start();
|
||||
});
|
||||
|
||||
test('Launching app', function() {
|
||||
window.dispatchEvent(new CustomEvent('webapps-launch',
|
||||
{detail: fakeLaunchConfig1}));
|
||||
assert.isTrue(window.appWindowFactory.isLaunchingWindow());
|
||||
app.element.dispatchEvent(new CustomEvent('_opened', {
|
||||
detail: app
|
||||
}));
|
||||
assert.isFalse(window.appWindowFactory.isLaunchingWindow());
|
||||
});
|
||||
|
||||
test('Ignore background app', function() {
|
||||
window.dispatchEvent(new CustomEvent('open-app',
|
||||
{detail: fakeLaunchConfig8}));
|
||||
assert.isFalse(window.appWindowFactory.isLaunchingWindow());
|
||||
});
|
||||
});
|
||||
|
||||
suite('_findBrowserInstance', function() {
|
||||
var mockApp, mockApp2, unpinnedApps;
|
||||
|
||||
setup(function() {
|
||||
mockApp = {
|
||||
requestOpen: this.sinon.stub(),
|
||||
isBrowser: function() {},
|
||||
launchTime: 1
|
||||
};
|
||||
|
||||
mockApp2 = {
|
||||
requestOpen: this.sinon.stub(),
|
||||
isBrowser: function() {},
|
||||
launchTime: 2
|
||||
};
|
||||
|
||||
unpinnedApps = [mockApp, mockApp2];
|
||||
this.sinon.stub(MockService, 'query', function(key) {
|
||||
switch (key) {
|
||||
case 'AppWindowManager.getUnpinnedWindows':
|
||||
return unpinnedApps;
|
||||
case 'AppWindowManager.getActiveApp':
|
||||
return mockApp;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('returns nothing if not trying to open the Browser', function() {
|
||||
this.sinon.stub(appWindowFactory, '_isSearch').returns(false);
|
||||
var instance = appWindowFactory._findBrowserInstance();
|
||||
assert.isFalse(!!(instance));
|
||||
});
|
||||
|
||||
test('returns nothing if the Browser is already active', function() {
|
||||
this.sinon.stub(appWindowFactory, '_isSearch').returns(true);
|
||||
this.sinon.stub(mockApp, 'isBrowser').returns(true);
|
||||
var instance = appWindowFactory._findBrowserInstance();
|
||||
assert.isFalse(!!(instance));
|
||||
});
|
||||
|
||||
test('returns the last used unpinned page', function() {
|
||||
this.sinon.stub(appWindowFactory, '_isSearch').returns(true);
|
||||
this.sinon.stub(mockApp, 'isBrowser').returns(false);
|
||||
var instance = appWindowFactory._findBrowserInstance();
|
||||
assert.equal(instance, mockApp2);
|
||||
});
|
||||
});
|
||||
|
||||
suite('check for open-app queueing', function() {
|
||||
var applicationsReady;
|
||||
var eventHandlerSpy, preEventHandlerSpy, queuePendingEventSpy;
|
||||
var openAppEvent;
|
||||
|
||||
setup(function() {
|
||||
openAppEvent = new CustomEvent('open-app', {'detail': {}});
|
||||
applicationsReady = window.applications.ready;
|
||||
eventHandlerSpy =
|
||||
this.sinon.spy(window.appWindowFactory, 'handleEvent');
|
||||
preEventHandlerSpy =
|
||||
this.sinon.spy(window.appWindowFactory, 'preHandleEvent');
|
||||
queuePendingEventSpy =
|
||||
this.sinon.spy(window.appWindowFactory, '_queuePendingEvent');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.applications.ready = applicationsReady;
|
||||
});
|
||||
|
||||
suite('open-app delivered, applications.ready is false', function() {
|
||||
setup(function() {
|
||||
window.applications.ready = false;
|
||||
window.appWindowFactory.start();
|
||||
window.dispatchEvent(openAppEvent);
|
||||
});
|
||||
|
||||
test('handleEvent not called', function() {
|
||||
sinon.assert.notCalled(eventHandlerSpy);
|
||||
});
|
||||
|
||||
test('preHandleEvent called', function() {
|
||||
sinon.assert.called(preEventHandlerSpy);
|
||||
});
|
||||
|
||||
test('_queuePendingEvent called', function() {
|
||||
sinon.assert.calledOnce(queuePendingEventSpy);
|
||||
});
|
||||
});
|
||||
|
||||
suite('open-app delivered, applications.ready is true', function() {
|
||||
setup(function() {
|
||||
window.applications.ready = true;
|
||||
window.appWindowFactory.start();
|
||||
window.dispatchEvent(openAppEvent);
|
||||
});
|
||||
|
||||
test('preHandleEvent called', function() {
|
||||
sinon.assert.called(preEventHandlerSpy);
|
||||
});
|
||||
|
||||
test('handleEvent called after open-app',
|
||||
function() {
|
||||
sinon.assert.calledWithExactly(eventHandlerSpy, openAppEvent);
|
||||
});
|
||||
});
|
||||
|
||||
suite('open-app delivered, applicationready event', function() {
|
||||
var handlePendingSpy;
|
||||
setup(function() {
|
||||
window.applications.ready = false;
|
||||
window.appWindowFactory.start();
|
||||
window.dispatchEvent(openAppEvent);
|
||||
handlePendingSpy =
|
||||
this.sinon.spy(window.appWindowFactory, '_handlePendingEvents');
|
||||
window.dispatchEvent(new CustomEvent('applicationready'));
|
||||
});
|
||||
|
||||
test('preHandleEvent called', function() {
|
||||
sinon.assert.called(preEventHandlerSpy);
|
||||
});
|
||||
|
||||
test('_queuePendingEvent called', function() {
|
||||
sinon.assert.calledOnce(queuePendingEventSpy);
|
||||
});
|
||||
|
||||
test('_handlePendingEvents called', function() {
|
||||
sinon.assert.calledOnce(handlePendingSpy);
|
||||
});
|
||||
|
||||
test('handleEvent called', function() {
|
||||
sinon.assert.called(eventHandlerSpy);
|
||||
});
|
||||
|
||||
test('pending events cleared', function() {
|
||||
assert.equal(0, window.appWindowFactory._queueEvents.length);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('handle event', function() {
|
||||
setup(function() {
|
||||
window.appWindowFactory.start();
|
||||
});
|
||||
|
||||
test('call event without manifestURL/url', function() {
|
||||
var stubBrowserConfigHelper = this.sinon.stub(window,
|
||||
'BrowserConfigHelper');
|
||||
appWindowFactory.handleEvent({
|
||||
detail: {
|
||||
url: null,
|
||||
manifestURL: null
|
||||
}
|
||||
});
|
||||
assert.isFalse(stubBrowserConfigHelper.calledWithNew());
|
||||
});
|
||||
|
||||
test('classic app launch', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'webapps-launch',
|
||||
detail: fakeLaunchConfig1
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig1.url);
|
||||
});
|
||||
|
||||
test('a second applaunch', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'webapps-launch',
|
||||
detail: fakeLaunchConfig2
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig2.url);
|
||||
});
|
||||
|
||||
test('redirect applaunch', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'appopenwindow',
|
||||
detail: fakeLaunchConfig2
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig2.url);
|
||||
});
|
||||
|
||||
test('open a new window', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'openwindow',
|
||||
detail: fakeLaunchConfig2
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig2.url);
|
||||
});
|
||||
|
||||
test('opening from a system message', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'open-app',
|
||||
detail: fakeLaunchConfig3
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig3.url);
|
||||
});
|
||||
|
||||
test('app launch with multiscreen.enabled', function() {
|
||||
this.sinon.stub(MockService, 'query', function(key) {
|
||||
return key == 'MultiScreenController.enabled';
|
||||
});
|
||||
this.sinon.stub(MockService, 'request', function() {
|
||||
return Promise.resolve(1);
|
||||
});
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'webapps-launch',
|
||||
detail: fakeLaunchConfig1
|
||||
});
|
||||
assert.isTrue(MockService.request.calledWith('chooseDisplay'));
|
||||
assert.equal(MockService.request.getCall(0).args[1].url,
|
||||
fakeLaunchConfig1.url);
|
||||
});
|
||||
|
||||
test('opening a first activity', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'open-app',
|
||||
detail: fakeLaunchConfig4
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchactivity');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig4.url);
|
||||
});
|
||||
|
||||
test('webapps-close with search app', function() {
|
||||
var stubPublish = this.sinon.stub(appWindowFactory, 'publish');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'webapps-close',
|
||||
detail: fakeLaunchConfig5
|
||||
});
|
||||
assert.isTrue(stubPublish.calledOnce);
|
||||
assert.equal(stubPublish.getCall(0).args[0], 'killapp');
|
||||
assert.equal(stubPublish.getCall(0).args[1].url, fakeLaunchConfig5.url);
|
||||
});
|
||||
|
||||
test('opening a second activity', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'open-app',
|
||||
detail: fakeLaunchConfig5
|
||||
});
|
||||
assert.isTrue(stubDispatchEvent.called);
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'launchapp');
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].detail.url,
|
||||
fakeLaunchConfig5.url);
|
||||
});
|
||||
|
||||
test('open system app', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'open-app',
|
||||
detail: fakeLaunchConfig6
|
||||
});
|
||||
assert.isFalse(stubDispatchEvent.called);
|
||||
});
|
||||
|
||||
test('launch an already-running app', function() {
|
||||
var app = new AppWindow();
|
||||
var stubReviveBrowser = this.sinon.stub(app, 'reviveBrowser');
|
||||
MockService.mockQueryWith('getApp', app);
|
||||
appWindowFactory.handleEvent({
|
||||
type: 'open-app',
|
||||
detail: fakeLaunchConfig5
|
||||
});
|
||||
assert.isTrue(stubReviveBrowser.called);
|
||||
});
|
||||
|
||||
test('open-app with search app', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
this.sinon.stub(appWindowFactory, '_findBrowserInstance').returns(null);
|
||||
appWindowFactory.launch(fakeLaunchConfig7);
|
||||
assert.ok(stubDispatchEvent.notCalled);
|
||||
|
||||
fakeLaunchConfig7.url = 'app://search.gaiamobile.org/newtab.html';
|
||||
appWindowFactory.launch(fakeLaunchConfig7);
|
||||
assert.ok(stubDispatchEvent.calledOnce);
|
||||
});
|
||||
|
||||
test('open-app with search app and unpinned instance', function() {
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
var app = {
|
||||
requestOpen: this.sinon.stub()
|
||||
};
|
||||
this.sinon.stub(appWindowFactory, '_findBrowserInstance').returns(app);
|
||||
appWindowFactory.launch(fakeLaunchConfig7);
|
||||
assert.ok(stubDispatchEvent.notCalled);
|
||||
|
||||
fakeLaunchConfig7.url = 'app://search.gaiamobile.org/newtab.html';
|
||||
appWindowFactory.launch(fakeLaunchConfig7);
|
||||
assert.ok(stubDispatchEvent.notCalled);
|
||||
assert.ok(app.requestOpen);
|
||||
});
|
||||
});
|
||||
});
|
||||
1405
gaia/apps/system/test/unit/app_window_manager_test.js
Executable file
1405
gaia/apps/system/test/unit/app_window_manager_test.js
Executable file
File diff suppressed because it is too large
Load diff
3443
gaia/apps/system/test/unit/app_window_test.js
Executable file
3443
gaia/apps/system/test/unit/app_window_test.js
Executable file
File diff suppressed because it is too large
Load diff
163
gaia/apps/system/test/unit/applications_test.js
Executable file
163
gaia/apps/system/test/unit/applications_test.js
Executable file
|
|
@ -0,0 +1,163 @@
|
|||
'use strict';
|
||||
/* global Applications, MockAppsMgmt, MockApp, MockL10n*/
|
||||
|
||||
requireApp('system/test/unit/mock_apps_mgmt.js');
|
||||
requireApp('system/test/unit/mock_app.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/js/applications.js');
|
||||
|
||||
suite('applications test', function() {
|
||||
var realMozApps, testApplications, realL10n;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozApps = navigator.mozApps;
|
||||
navigator.mozApps = { mgmt: MockAppsMgmt };
|
||||
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozApps = realMozApps;
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
/**
|
||||
* Since the script still initialize itself, we should not allow
|
||||
* the "global" instance from being responsive in our tests here.
|
||||
*/
|
||||
if (window.applications) {
|
||||
window.applications.stop();
|
||||
window.applications = null;
|
||||
}
|
||||
window.sessionStorage.removeItem('webapps-registry-ready');
|
||||
testApplications = new Applications();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
testApplications.stop();
|
||||
});
|
||||
|
||||
suite('init tests', function() {
|
||||
var clock;
|
||||
setup(function() {
|
||||
clock = this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('webapps-registry-ready is "no" applications.ready should be false',
|
||||
function() {
|
||||
testApplications.start();
|
||||
clock.tick(1);
|
||||
assert.isFalse(testApplications.ready);
|
||||
});
|
||||
|
||||
test('webapps-registry-ready is "yes" applications.ready should be ture',
|
||||
function() {
|
||||
window.sessionStorage.setItem('webapps-registry-ready', 'yes');
|
||||
testApplications.start();
|
||||
clock.tick(1);
|
||||
assert.isTrue(testApplications.ready);
|
||||
});
|
||||
|
||||
test('fire "mozChromeEvent" to let applications.ready be true',
|
||||
function() {
|
||||
testApplications.start();
|
||||
var evt = new CustomEvent('mozChromeEvent',
|
||||
{ detail: { type: 'webapps-registry-ready' } });
|
||||
window.dispatchEvent(evt);
|
||||
clock.tick(1);
|
||||
assert.isTrue(testApplications.ready);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getByManifestURL tests', function() {
|
||||
var app;
|
||||
|
||||
setup(function() {
|
||||
app = new MockApp({
|
||||
manifestURL:'https://testapp.aaa.org/manifest.webapp'});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
app = null;
|
||||
});
|
||||
|
||||
test('Should not be found App.', function() {
|
||||
var testApp = testApplications.getByManifestURL(app.manifestURL);
|
||||
assert.equal(testApp, null);
|
||||
});
|
||||
|
||||
test('Should be found App.', function() {
|
||||
testApplications.installedApps[app.manifestURL] = app;
|
||||
var testApp = testApplications.getByManifestURL(app.manifestURL);
|
||||
assert.equal(testApp.manifestURL, app.manifestURL);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('fireEvent tests', function() {
|
||||
var called;
|
||||
|
||||
setup(function() {
|
||||
called = false;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
called = false;
|
||||
});
|
||||
|
||||
test('Trigger oninstall', function() {
|
||||
window.addEventListener('applicationinstall', function mozAppTest() {
|
||||
window.removeEventListener('applicationinstall', mozAppTest);
|
||||
called = true;
|
||||
});
|
||||
testApplications.start();
|
||||
navigator.mozApps.mgmt.mTriggerOninstall(new MockApp());
|
||||
assert.isTrue(called);
|
||||
});
|
||||
|
||||
test('Trigger onuninstall', function() {
|
||||
window.addEventListener('applicationuninstall', function mozAppTest() {
|
||||
window.removeEventListener('applicationuninstall', mozAppTest);
|
||||
called = true;
|
||||
});
|
||||
testApplications.start();
|
||||
navigator.mozApps.mgmt.mTriggerOnuninstall(new MockApp());
|
||||
assert.isTrue(called);
|
||||
});
|
||||
|
||||
test('Trigger fireApplicationReadyEvent', function() {
|
||||
window.addEventListener('applicationready', function mozAppTest() {
|
||||
window.removeEventListener('applicationready', mozAppTest);
|
||||
called = true;
|
||||
});
|
||||
testApplications.fireApplicationReadyEvent();
|
||||
assert.isTrue(called);
|
||||
});
|
||||
|
||||
test('Trigger fireApplicationInstallEvent', function() {
|
||||
window.addEventListener('applicationinstall', function mozAppTest() {
|
||||
window.removeEventListener('applicationinstall', mozAppTest);
|
||||
called = true;
|
||||
});
|
||||
testApplications.fireApplicationInstallEvent(new MockApp());
|
||||
assert.isTrue(called);
|
||||
});
|
||||
|
||||
test('Trigger fireApplicationUninstallEvent', function() {
|
||||
window.addEventListener('applicationuninstall', function mozAppTest() {
|
||||
window.removeEventListener('applicationuninstall', mozAppTest);
|
||||
called = true;
|
||||
});
|
||||
testApplications.fireApplicationUninstallEvent(new MockApp());
|
||||
assert.isTrue(called);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
260
gaia/apps/system/test/unit/attention_toaster_test.js
Executable file
260
gaia/apps/system/test/unit/attention_toaster_test.js
Executable file
|
|
@ -0,0 +1,260 @@
|
|||
/* global MocksHelper, MockAppWindow, MockService, AttentionToaster */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_rocketbar.js');
|
||||
|
||||
var mocksForAttentionToaster = new MocksHelper([
|
||||
'AppWindow', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/AttentionToaster', function() {
|
||||
var stubById;
|
||||
mocksForAttentionToaster.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
this.sinon.stub(window, 'requestAnimationFrame');
|
||||
this.sinon.useFakeTimers();
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
requireApp('system/js/attention_toaster.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
test('Enter uninit state while the attention window is closed.', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
assert.isTrue(at1._currentToasterState === 'uninit');
|
||||
});
|
||||
|
||||
test('Enter uninit state while the attention window requests to open.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
assert.isTrue(at1._currentToasterState === 'uninit');
|
||||
app1.element.dispatchEvent(new CustomEvent('_requestopen'));
|
||||
assert.equal(at1._currentToasterState, 'uninit');
|
||||
});
|
||||
|
||||
test('Enter closed state while the attention window is closed.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
assert.isTrue(at1._currentToasterState === 'uninit');
|
||||
app1.element.dispatchEvent(new CustomEvent('_closed'));
|
||||
assert.notEqual(at1._currentToasterState, 'closed');
|
||||
window.requestAnimationFrame.yield();
|
||||
assert.equal(at1._currentToasterState, 'closed');
|
||||
});
|
||||
|
||||
test('Enter opening state while open event comes.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1._currentToasterState = 'closed';
|
||||
at1.processStateChange('open');
|
||||
assert.equal(at1._currentToasterState, 'opening');
|
||||
});
|
||||
|
||||
test('Enter opened state while the attention window transition ends.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'opening';
|
||||
app1.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
assert.equal(at1._currentToasterState, 'opened');
|
||||
});
|
||||
|
||||
test('Enter closing state while the attention window display timeout.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'opened';
|
||||
at1._enter_opened();
|
||||
MockService.mockQueryWith('locked', false);
|
||||
MockService.mockQueryWith('getTopMostWindow', {
|
||||
CLASS_NAME: 'AppWindow'
|
||||
});
|
||||
this.sinon.clock.tick(at1.TOASTER_TIMEOUT);
|
||||
assert.equal(at1._currentToasterState, 'closing');
|
||||
});
|
||||
|
||||
test('Enter opening state if being at closed state for 30sec.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'closing';
|
||||
at1._enter_closed('complete');
|
||||
this.sinon.clock.tick(at1.RESPAWN_TIMEOUT);
|
||||
assert.equal(at1._currentToasterState, 'opening');
|
||||
});
|
||||
|
||||
test('Enter closed state while the attention window transition ends.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'closing';
|
||||
app1.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
assert.equal(at1._currentToasterState, 'closed');
|
||||
});
|
||||
|
||||
test('Enter opening state again while lockscreen window is opened.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'closed';
|
||||
app1.element.dispatchEvent(new CustomEvent('_lockscreen-appopened'));
|
||||
assert.equal(at1._currentToasterState, 'opening');
|
||||
});
|
||||
|
||||
test('Enter opening state again while secure window is closed.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'closed';
|
||||
app1.element.dispatchEvent(new CustomEvent('_secure-appclosed'));
|
||||
assert.equal(at1._currentToasterState, 'opening');
|
||||
});
|
||||
|
||||
test('Enter closing state while lockscreen window is closed.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'opened';
|
||||
app1.element.dispatchEvent(new CustomEvent('_lockscreen-appclosed'));
|
||||
assert.isTrue(at1._currentToasterState === 'closing');
|
||||
});
|
||||
|
||||
test('Enter closing state while secure window is opened.',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.start();
|
||||
at1._currentToasterState = 'opened';
|
||||
app1.element.dispatchEvent(new CustomEvent('_secure-appopened'));
|
||||
assert.equal(at1._currentToasterState, 'closing');
|
||||
});
|
||||
|
||||
test('Should not enter closing state if system is locked', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
MockService.mockQueryWith('locked', true);
|
||||
MockService.mockQueryWith('getTopMostWindow', {
|
||||
isFullScreen: function() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
at1._currentToasterState = 'opened';
|
||||
at1._enter_opened();
|
||||
this.sinon.clock.tick(at1.TOASTER_TIMEOUT);
|
||||
assert.equal(at1._currentToasterState, 'opened');
|
||||
});
|
||||
|
||||
test('Should enter closing state if fullscreen secure app is opened',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
MockService.mockQueryWith('locked', true);
|
||||
MockService.mockQueryWith('getTopMostWindow', {
|
||||
isFullScreen: function() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
at1._currentToasterState = 'opened';
|
||||
at1._enter_opened();
|
||||
this.sinon.clock.tick(at1.TOASTER_TIMEOUT);
|
||||
assert.equal(at1._currentToasterState, 'closing');
|
||||
});
|
||||
|
||||
test('Should not trigger state change if the app is hidden or active',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
app1.element.dispatchEvent(new CustomEvent('_lockscreen-appopened'));
|
||||
assert.equal(at1._currentToasterState, 'uninit');
|
||||
});
|
||||
|
||||
test('becomeToaster()', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
at1.becomeToaster();
|
||||
assert.isTrue(app1.element.classList.contains('toaster-mode'));
|
||||
assert.isTrue(app1.resized);
|
||||
});
|
||||
|
||||
test('recoverLayout()',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
var stubRealResize = this.sinon.stub(app1, '_resize');
|
||||
var stubPublish = this.sinon.stub(app1, 'publish');
|
||||
at1.becomeToaster();
|
||||
app1.element.classList.add('displayed');
|
||||
at1.recoverLayout();
|
||||
assert.isFalse(app1.element.classList.contains('toaster-mode'));
|
||||
assert.isFalse(app1.element.classList.contains('displayed'));
|
||||
assert.isTrue(stubPublish.calledWith('recovering'));
|
||||
assert.isTrue(stubRealResize.called);
|
||||
assert.isFalse(app1.resized);
|
||||
});
|
||||
|
||||
test('open the toaster after resize and repaint', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
var stubTryWaitForFullRepaint =
|
||||
this.sinon.stub(app1, 'tryWaitForFullRepaint');
|
||||
var stubSetVisible = this.sinon.stub(app1, 'setVisible');
|
||||
var stubProcessStateChange = this.sinon.stub(at1, 'processStateChange');
|
||||
at1._currentToasterState = 'closed';
|
||||
at1._enter_closed('init');
|
||||
stubTryWaitForFullRepaint.getCall(0).args[0]();
|
||||
assert.isTrue(stubProcessStateChange.calledWith('open'));
|
||||
assert.isFalse(stubSetVisible.called);
|
||||
});
|
||||
|
||||
test('Only open the toaster while we are from uninit state.', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
var stubProcessStateChange = this.sinon.stub(at1, 'processStateChange');
|
||||
at1._currentToasterState = 'closed';
|
||||
at1._enter_closed('complete');
|
||||
assert.isFalse(stubProcessStateChange.called);
|
||||
});
|
||||
|
||||
test('Send the app to background once closed.', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
var stubSetVisible = this.sinon.stub(app1, 'setVisible');
|
||||
at1._currentToasterState = 'closed';
|
||||
at1._enter_closed('complete');
|
||||
assert.isTrue(stubSetVisible.calledWith(false));
|
||||
});
|
||||
|
||||
test('Bring the app to foreground once opening.', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var at1 = new AttentionToaster(app1);
|
||||
var stubSetVisible = this.sinon.stub(app1, 'setVisible');
|
||||
at1._currentToasterState = 'opening';
|
||||
at1._enter_opening();
|
||||
assert.isTrue(stubSetVisible.calledWith(true));
|
||||
});
|
||||
});
|
||||
527
gaia/apps/system/test/unit/attention_window_manager_test.js
Executable file
527
gaia/apps/system/test/unit/attention_window_manager_test.js
Executable file
|
|
@ -0,0 +1,527 @@
|
|||
/* globals attentionWindowManager, AttentionWindowManager, MockService,
|
||||
MockAttentionWindow, MocksHelper, MockHomescreenWindow,
|
||||
MockAppWindow, MockService */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_attention_window.js');
|
||||
requireApp('system/test/unit/mock_homescreen_window.js');
|
||||
requireApp('system/test/unit/mock_attention_indicator.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForAttentionWindowManager = new MocksHelper([
|
||||
'AttentionWindow', 'Service',
|
||||
'HomescreenWindow'
|
||||
]).init();
|
||||
|
||||
suite('system/AttentionWindowManager', function() {
|
||||
mocksForAttentionWindowManager.attachTestHelpers();
|
||||
var stubById;
|
||||
var att1, att2, att3;
|
||||
setup(function(done) {
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
|
||||
att1 = new MockAttentionWindow(fakeAttentionConfig);
|
||||
att2 = new MockAttentionWindow(fakeAttentionConfig);
|
||||
att3 = new MockAttentionWindow(fakeAttentionConfig);
|
||||
|
||||
requireApp('system/js/attention_window_manager.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockService.mockQueryWith('AppWindowManager.getActiveWindow', null);
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
var fakeAttentionConfig = {
|
||||
url: 'app://www.fakef/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://www.fakef/ManifestURL',
|
||||
origin: 'app://www.fakef'
|
||||
};
|
||||
|
||||
suite('Hierarchy functions', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(MockService, 'request');
|
||||
window.attentionWindowManager = new AttentionWindowManager();
|
||||
window.attentionWindowManager.start();
|
||||
});
|
||||
teardown(function() {
|
||||
window.attentionWindowManager.stop();
|
||||
window.attentionWindowManager = null;
|
||||
});
|
||||
test('Should be active if there is an opened window', function() {
|
||||
window.dispatchEvent(new CustomEvent('attentionopened', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(attentionWindowManager.isActive());
|
||||
});
|
||||
test('Should not be active if there is no opened window', function() {
|
||||
assert.isFalse(attentionWindowManager.isActive());
|
||||
});
|
||||
test('start should register hierarchy', function() {
|
||||
assert.isTrue(
|
||||
MockService.request.calledWith('registerHierarchy',
|
||||
attentionWindowManager));
|
||||
});
|
||||
test('stop should unregister hierarchy', function() {
|
||||
attentionWindowManager.stop();
|
||||
assert.isTrue(
|
||||
MockService.request.calledWith('unregisterHierarchy',
|
||||
attentionWindowManager));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Maintain attention indicator', function() {
|
||||
var sytemStub;
|
||||
setup(function() {
|
||||
window.attentionWindowManager = new AttentionWindowManager();
|
||||
window.attentionWindowManager.start();
|
||||
sytemStub = this.sinon.stub(MockService, 'request');
|
||||
});
|
||||
teardown(function() {
|
||||
window.attentionWindowManager.stop();
|
||||
window.attentionWindowManager = null;
|
||||
});
|
||||
test('When there is an attention window closed', function() {
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
attentionWindowManager._instances = [att1];
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(sytemStub.calledWith('makeAmbientIndicatorActive'));
|
||||
});
|
||||
|
||||
test('When there is an attention window requests to open', function() {
|
||||
attentionWindowManager._openedInstances = new Map();
|
||||
attentionWindowManager._instances = [att1];
|
||||
window.dispatchEvent(new CustomEvent('attentionopened', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(sytemStub.calledWith('makeAmbientIndicatorInactive'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('get shown window count', function() {
|
||||
setup(function() {
|
||||
window.attentionWindowManager = new AttentionWindowManager();
|
||||
window.attentionWindowManager.start();
|
||||
});
|
||||
teardown(function() {
|
||||
window.attentionWindowManager.stop();
|
||||
window.attentionWindowManager = null;
|
||||
});
|
||||
test('should not take hidden window into account when updating indicator',
|
||||
function() {
|
||||
window.dispatchEvent(new CustomEvent('attentioncreated', {
|
||||
detail: att1
|
||||
}));
|
||||
this.sinon.stub(att1, 'isHidden').returns(true);
|
||||
window.dispatchEvent(new CustomEvent('attentioncreated', {
|
||||
detail: att2
|
||||
}));
|
||||
this.sinon.stub(MockService, 'request');
|
||||
window.dispatchEvent(new CustomEvent('attentionopened', {
|
||||
detail: att2
|
||||
}));
|
||||
assert.isTrue(MockService.request
|
||||
.calledWith('makeAmbientIndicatorInactive'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('fullscreen mode', function() {
|
||||
var realFullScreen;
|
||||
|
||||
setup(function() {
|
||||
realFullScreen = document.mozFullScreen;
|
||||
Object.defineProperty(document, 'mozFullScreen', {
|
||||
configurable: true,
|
||||
get: function() { return true; }
|
||||
});
|
||||
window.attentionWindowManager = new AttentionWindowManager();
|
||||
window.attentionWindowManager.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Object.defineProperty(document, 'mozFullScreen', {
|
||||
configurable: true,
|
||||
get: function() { return realFullScreen; }
|
||||
});
|
||||
window.attentionWindowManager.stop();
|
||||
window.attentionWindowManager = null;
|
||||
});
|
||||
|
||||
test('should exit fullscreen when opening attention',
|
||||
function() {
|
||||
var cancelSpy = this.sinon.spy(document, 'mozCancelFullScreen');
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map();
|
||||
attentionWindowManager._topMostWindow = null;
|
||||
var spyReadyForAtt1 = this.sinon.stub(att1, 'ready');
|
||||
window.dispatchEvent(new CustomEvent('attentionrequestopen', {
|
||||
detail: att1
|
||||
}));
|
||||
spyReadyForAtt1.getCall(0).args[0]();
|
||||
sinon.assert.calledOnce(cancelSpy);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Handle events', function() {
|
||||
setup(function() {
|
||||
window.attentionWindowManager = new AttentionWindowManager();
|
||||
window.attentionWindowManager.start();
|
||||
});
|
||||
teardown(function() {
|
||||
window.attentionWindowManager.stop();
|
||||
window.attentionWindowManager = null;
|
||||
});
|
||||
|
||||
test('broadcast secure app opened event', function() {
|
||||
attentionWindowManager._instances =
|
||||
new Map([[att3, att3], [att2, att2], [att1, att1]]);
|
||||
var stubBroadcast = [
|
||||
this.sinon.stub(att1, 'broadcast'),
|
||||
this.sinon.stub(att2, 'broadcast'),
|
||||
this.sinon.stub(att3, 'broadcast')
|
||||
];
|
||||
window.dispatchEvent(new CustomEvent('secure-appopened'));
|
||||
assert.isTrue(stubBroadcast[0].calledWith('secure-appopened'));
|
||||
assert.isTrue(stubBroadcast[1].calledWith('secure-appopened'));
|
||||
assert.isTrue(stubBroadcast[2].calledWith('secure-appopened'));
|
||||
});
|
||||
|
||||
test('broadcast secure app closed event', function() {
|
||||
attentionWindowManager._instances =
|
||||
new Map([[att3, att3], [att2, att2], [att1, att1]]);
|
||||
var stubBroadcast = [
|
||||
this.sinon.stub(att1, 'broadcast'),
|
||||
this.sinon.stub(att2, 'broadcast'),
|
||||
this.sinon.stub(att3, 'broadcast')
|
||||
];
|
||||
window.dispatchEvent(new CustomEvent('secure-appclosed'));
|
||||
assert.isTrue(stubBroadcast[0].calledWith('secure-appclosed'));
|
||||
assert.isTrue(stubBroadcast[1].calledWith('secure-appclosed'));
|
||||
assert.isTrue(stubBroadcast[2].calledWith('secure-appclosed'));
|
||||
});
|
||||
|
||||
test('broadcast lockscreen app opened event', function() {
|
||||
attentionWindowManager._instances =
|
||||
new Map([[att3, att3], [att2, att2], [att1, att1]]);
|
||||
var stubBroadcast = [
|
||||
this.sinon.stub(att1, 'broadcast'),
|
||||
this.sinon.stub(att2, 'broadcast'),
|
||||
this.sinon.stub(att3, 'broadcast')
|
||||
];
|
||||
window.dispatchEvent(new CustomEvent('lockscreen-appopened'));
|
||||
assert.isTrue(stubBroadcast[0].calledWith('lockscreen-appopened'));
|
||||
assert.isTrue(stubBroadcast[1].calledWith('lockscreen-appopened'));
|
||||
assert.isTrue(stubBroadcast[2].calledWith('lockscreen-appopened'));
|
||||
});
|
||||
|
||||
test('broadcast lockscreen app closed event', function() {
|
||||
attentionWindowManager._instances =
|
||||
new Map([[att3, att3], [att2, att2], [att1, att1]]);
|
||||
var stubBroadcast = [
|
||||
this.sinon.stub(att1, 'broadcast'),
|
||||
this.sinon.stub(att2, 'broadcast'),
|
||||
this.sinon.stub(att3, 'broadcast')
|
||||
];
|
||||
window.dispatchEvent(new CustomEvent('lockscreen-appclosed'));
|
||||
assert.isTrue(stubBroadcast[0].calledWith('lockscreen-appclosed'));
|
||||
assert.isTrue(stubBroadcast[1].calledWith('lockscreen-appclosed'));
|
||||
assert.isTrue(stubBroadcast[2].calledWith('lockscreen-appclosed'));
|
||||
});
|
||||
|
||||
test('broadcast languagechange event', function() {
|
||||
attentionWindowManager._instances =
|
||||
new Map([[att3, att3], [att2, att2], [att1, att1]]);
|
||||
var stubBroadcast = [
|
||||
this.sinon.stub(att1, 'broadcast'),
|
||||
this.sinon.stub(att2, 'broadcast'),
|
||||
this.sinon.stub(att3, 'broadcast')
|
||||
];
|
||||
window.dispatchEvent(new CustomEvent('languagechange'));
|
||||
assert.isTrue(stubBroadcast[0].calledWith('languagechange'));
|
||||
assert.isTrue(stubBroadcast[1].calledWith('languagechange'));
|
||||
assert.isTrue(stubBroadcast[2].calledWith('languagechange'));
|
||||
});
|
||||
|
||||
test('System resize request', function() {
|
||||
attentionWindowManager._topMostWindow = att1;
|
||||
var stubResize = this.sinon.stub(att1, 'resize');
|
||||
attentionWindowManager.respondToHierarchyEvent({
|
||||
type: 'system-resize',
|
||||
detail: {
|
||||
}
|
||||
});
|
||||
assert.isTrue(stubResize.called);
|
||||
});
|
||||
|
||||
test('System resize request (w/ waitUntil)', function() {
|
||||
attentionWindowManager._topMostWindow = att1;
|
||||
var p = Promise.resolve();
|
||||
var stubResize =
|
||||
this.sinon.stub(att1, 'resize').returns(p);
|
||||
var stubWaitUntil = this.sinon.stub();
|
||||
attentionWindowManager.respondToHierarchyEvent({
|
||||
type: 'system-resize',
|
||||
detail: {
|
||||
waitUntil: stubWaitUntil
|
||||
}
|
||||
});
|
||||
assert.isTrue(stubResize.called);
|
||||
assert.isTrue(stubWaitUntil.calledWith(p));
|
||||
});
|
||||
|
||||
test('Home button', function() {
|
||||
MockService.mockQueryWith('locked', false);
|
||||
MockService.mockQueryWith('getHomescreen', new MockHomescreenWindow());
|
||||
this.sinon.stub(MockService.mQueries.getHomescreen, 'ready');
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att3, att3], [att2, att2]]);
|
||||
var stubCloseForAtt3 = this.sinon.stub(att3, 'close');
|
||||
var stubCloseForAtt2 = this.sinon.stub(att2, 'close');
|
||||
attentionWindowManager.respondToHierarchyEvent(new CustomEvent('home'));
|
||||
MockService.mQueries.getHomescreen.ready.yield();
|
||||
assert.isTrue(stubCloseForAtt2.called);
|
||||
assert.isTrue(stubCloseForAtt3.called);
|
||||
});
|
||||
|
||||
test('Home button, but no active window', function() {
|
||||
var stubGetHomescreen =
|
||||
this.sinon.stub(MockService, 'query');
|
||||
attentionWindowManager._openedInstances = new Map();
|
||||
attentionWindowManager.respondToHierarchyEvent(new CustomEvent('home'));
|
||||
assert.isFalse(stubGetHomescreen.calledWith('getHomescreen'));
|
||||
});
|
||||
|
||||
test('HoldHome event', function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att3, att3], [att2, att2]]);
|
||||
var stubCloseForAtt3 = this.sinon.stub(att3, 'close');
|
||||
var stubCloseForAtt2 = this.sinon.stub(att2, 'close');
|
||||
attentionWindowManager.respondToHierarchyEvent(
|
||||
new CustomEvent('holdhome'));
|
||||
assert.isTrue(stubCloseForAtt2.called);
|
||||
assert.isTrue(stubCloseForAtt3.called);
|
||||
});
|
||||
|
||||
test('Emergency alert is shown', function() {
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
var stubClose = this.sinon.stub(att1, 'close');
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('emergencyalert')
|
||||
);
|
||||
assert.isTrue(stubClose.called);
|
||||
});
|
||||
|
||||
test('If update prompt is showing we should close.',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
|
||||
var stubCloseForAtt1 = this.sinon.stub(att1, 'close');
|
||||
var stubCloseForAtt2 = this.sinon.stub(att2, 'close');
|
||||
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('updatepromptshown')
|
||||
);
|
||||
assert.isTrue(stubCloseForAtt1.called);
|
||||
assert.isTrue(stubCloseForAtt2.called);
|
||||
});
|
||||
|
||||
test('If an app is launching due to request we should close.',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
var stubCloseForAtt1 = this.sinon.stub(att1, 'close');
|
||||
var stubCloseForAtt2 = this.sinon.stub(att2, 'close');
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('launchapp')
|
||||
);
|
||||
assert.isTrue(stubCloseForAtt1.called);
|
||||
assert.isTrue(stubCloseForAtt2.called);
|
||||
});
|
||||
|
||||
|
||||
test('If an app is launching by system message we should not close.',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
var stubCloseForAtt1 = this.sinon.stub(att1, 'close');
|
||||
var stubCloseForAtt2 = this.sinon.stub(att2, 'close');
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('launchapp', {detail: {stayBackground: true}})
|
||||
);
|
||||
assert.isFalse(stubCloseForAtt1.called);
|
||||
assert.isFalse(stubCloseForAtt2.called);
|
||||
});
|
||||
|
||||
test('AttentionWindow is terminated', function() {
|
||||
this.sinon.stub(attentionWindowManager, 'updateClassState');
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
assert.isTrue(attentionWindowManager._openedInstances.has(att1));
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('attentionterminated', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isFalse(attentionWindowManager._openedInstances.has(att1));
|
||||
assert.isFalse(attentionWindowManager.updateClassState.called);
|
||||
});
|
||||
|
||||
test('AttentionWindow is terminated with crash', function() {
|
||||
this.sinon.stub(attentionWindowManager, 'updateClassState');
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
att1.isCrashed = true;
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('attentionterminated', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isFalse(attentionWindowManager._openedInstances.has(att1));
|
||||
assert.isTrue(attentionWindowManager.updateClassState.called);
|
||||
att1.isCrashed = false;
|
||||
});
|
||||
|
||||
test('AttentionWindow is requesting to open', function() {
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
var stubSetVisibleForAtt1 = this.sinon.stub(att1, 'setVisible');
|
||||
var stubSetVisibleForAtt2 = this.sinon.stub(att2, 'setVisible');
|
||||
var stubOpenForAtt2 = this.sinon.stub(att2, 'open');
|
||||
var stubPromoteForAtt2 = this.sinon.stub(att2, 'promote');
|
||||
var stubDemoteForAtt1 = this.sinon.stub(att1, 'demote');
|
||||
var spy = this.sinon.spy(att2, 'ready');
|
||||
|
||||
attentionWindowManager.handleEvent(
|
||||
new CustomEvent('attentionrequestopen', {
|
||||
detail: att2
|
||||
})
|
||||
);
|
||||
spy.getCall(0).args[0]();
|
||||
assert.isTrue(stubSetVisibleForAtt1.calledWith(false));
|
||||
assert.isTrue(stubSetVisibleForAtt2.calledWith(true));
|
||||
assert.isTrue(stubOpenForAtt2.called);
|
||||
assert.isTrue(stubPromoteForAtt2.called);
|
||||
assert.isTrue(stubDemoteForAtt1.called);
|
||||
assert.deepEqual(att2, attentionWindowManager._topMostWindow);
|
||||
});
|
||||
|
||||
suite('AttentionWindow is closed', function() {
|
||||
test('choose the next opened instance to bring to foreground',
|
||||
function() {
|
||||
var stubDemoteForAtt1 = this.sinon.stub(att1, 'demote');
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2], [att3, att3]]);
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(stubDemoteForAtt1.called);
|
||||
});
|
||||
|
||||
test('updates the global attention class', function() {
|
||||
var manager = attentionWindowManager;
|
||||
manager._openedInstances = new Map([[att1, att1], [att2, att2]]);
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(manager.screen.classList.contains('attention'));
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att2
|
||||
}));
|
||||
assert.isFalse(manager.screen.classList.contains('attention'));
|
||||
});
|
||||
|
||||
test('should publish deactivated if no opened instances',
|
||||
function() {
|
||||
var caught = false;
|
||||
window.addEventListener('attentionwindowmanager-deactivated',
|
||||
function inactive() {
|
||||
window.removeEventListener('attentionwindowmanager-deactivated',
|
||||
inactive);
|
||||
caught = true;
|
||||
});
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isFalse(caught);
|
||||
window.dispatchEvent(new CustomEvent('attentionclosed', {
|
||||
detail: att2
|
||||
}));
|
||||
assert.isTrue(caught);
|
||||
});
|
||||
});
|
||||
|
||||
suite('AttentionWindow is requesting to close', function() {
|
||||
test('No other opened instances and no active app window', function() {
|
||||
MockService.mockQueryWith('AppWindowManager.getActiveWindow', null);
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
var stubClose = this.sinon.stub(att1, 'close');
|
||||
window.dispatchEvent(new CustomEvent('attentionrequestclose', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(stubClose.called);
|
||||
});
|
||||
|
||||
test('No other opened instances and no active app window', function() {
|
||||
var app = new MockAppWindow();
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
attentionWindowManager._topMostWindow = att1;
|
||||
var stubClose = this.sinon.stub(att1, 'close');
|
||||
var spyReadyForApp = this.sinon.stub(app, 'ready');
|
||||
MockService.mockQueryWith('AppWindowManager.getActiveWindow', app);
|
||||
window.dispatchEvent(new CustomEvent('attentionrequestclose', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isFalse(stubClose.called);
|
||||
spyReadyForApp.getCall(0).args[0]();
|
||||
assert.isTrue(stubClose.called);
|
||||
});
|
||||
|
||||
test('Having opened instances', function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
attentionWindowManager._topMostWindow = att1;
|
||||
var stubClose = this.sinon.stub(att1, 'close');
|
||||
var spyReadyForAtt2 = this.sinon.stub(att2, 'ready');
|
||||
window.dispatchEvent(new CustomEvent('attentionrequestclose', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isFalse(stubClose.called);
|
||||
spyReadyForAtt2.getCall(0).args[0]();
|
||||
assert.isTrue(stubClose.called);
|
||||
});
|
||||
|
||||
test('Having opened instances but the closing one is not top most',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances =
|
||||
new Map([[att1, att1], [att2, att2]]);
|
||||
attentionWindowManager._topMostWindow = att2;
|
||||
var stubClose = this.sinon.stub(att1, 'close');
|
||||
window.dispatchEvent(new CustomEvent('attentionrequestclose', {
|
||||
detail: att1
|
||||
}));
|
||||
assert.isTrue(stubClose.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('updateClassState()', function() {
|
||||
test('should add a global class when there are attention windows',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances = new Map([[att1, att1]]);
|
||||
attentionWindowManager.updateClassState();
|
||||
assert.isTrue(attentionWindowManager.screen.classList
|
||||
.contains('attention'));
|
||||
});
|
||||
|
||||
test('should not add a global class when there are no attention windows',
|
||||
function() {
|
||||
attentionWindowManager._openedInstances = new Map();
|
||||
attentionWindowManager.updateClassState();
|
||||
assert.isFalse(attentionWindowManager.screen.classList
|
||||
.contains('attention'));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
155
gaia/apps/system/test/unit/attention_window_test.js
Executable file
155
gaia/apps/system/test/unit/attention_window_test.js
Executable file
|
|
@ -0,0 +1,155 @@
|
|||
/* globals AttentionWindow, MocksHelper, MockApplications,
|
||||
MockL10n, MockLayoutManager, MockManifestHelper, BaseModule,
|
||||
MockContextMenu */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_orientation_manager.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_manifest_helper.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/test/unit/mock_screen_layout.js');
|
||||
requireApp('system/test/unit/mock_layout_manager.js');
|
||||
requireApp('system/test/unit/mock_app_chrome.js');
|
||||
requireApp('system/test/unit/mock_context_menu.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForAttentionWindow = new MocksHelper([
|
||||
'OrientationManager', 'Applications', 'SettingsListener',
|
||||
'ManifestHelper', 'LayoutManager', 'ScreenLayout',
|
||||
'AppChrome', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/AttentionWindow', function() {
|
||||
mocksForAttentionWindow.attachTestHelpers();
|
||||
var stubById;
|
||||
var realApplications, realLayoutManager;
|
||||
var realL10n;
|
||||
var fakeAttentionConfig = {
|
||||
'url': 'app://fakeatt.gaiamobile.org/pick.html',
|
||||
'manifestURL': 'app://fakeatt.gaiamobile.org/manifest.webapp',
|
||||
iframe: document.createElement('iframe'),
|
||||
origin: 'app://fakeatt.gaiamobile.org',
|
||||
name: 'fake',
|
||||
manifest: {
|
||||
orientation: 'default',
|
||||
icons: {
|
||||
'128': 'fake.icon'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setup(function(done) {
|
||||
realLayoutManager = window.layoutManager;
|
||||
window.layoutManager = new MockLayoutManager();
|
||||
MockApplications.mRegisterMockApp(fakeAttentionConfig);
|
||||
realApplications = window.applications;
|
||||
window.applications = MockApplications;
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
this.sinon.useFakeTimers();
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
this.sinon.stub(HTMLElement.prototype, 'querySelector',
|
||||
function() {
|
||||
return document.createElement('div');
|
||||
});
|
||||
requireApp('system/js/browser_config_helper.js');
|
||||
requireApp('system/js/browser_frame.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/app_window.js');
|
||||
requireApp('system/js/browser_mixin.js');
|
||||
requireApp('system/js/attention_window.js', function() {
|
||||
this.sinon.stub(BaseModule, 'instantiate', function(name) {
|
||||
if (name === 'BrowserContextMenu') {
|
||||
return MockContextMenu;
|
||||
}
|
||||
});
|
||||
done();
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.layoutManager = realLayoutManager;
|
||||
navigator.mozL10n = realL10n;
|
||||
window.applications = realApplications;
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
suite('attention window instance.', function() {
|
||||
test('show()', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
this.sinon.stub(attention, '_resize');
|
||||
attention.show();
|
||||
assert.equal(attention.element.style.width, '');
|
||||
assert.isTrue(attention._resize.calledOnce, '_resize called.');
|
||||
});
|
||||
|
||||
test('show should re-translate the fake notification', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
this.sinon.stub(attention, '_resize');
|
||||
MockManifestHelper.prototype.name = 'translated';
|
||||
this.sinon.clock.tick(); // l10n ready
|
||||
assert.equal(attention.notificationTitle.textContent, 'translated');
|
||||
|
||||
attention.show();
|
||||
MockManifestHelper.prototype.name = 'translated by show';
|
||||
this.sinon.clock.tick(); // l10n ready
|
||||
assert.equal(attention.notificationTitle.textContent,
|
||||
'translated by show');
|
||||
});
|
||||
|
||||
test('clear the fake notification node when removed.', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
attention.destroy();
|
||||
assert.isNull(attention.notification);
|
||||
});
|
||||
|
||||
test('make a fake notification', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
assert.isNotNull(attention.notification);
|
||||
assert.isTrue(attention.notification.classList
|
||||
.contains('attention-notification'));
|
||||
});
|
||||
|
||||
test('translate the fake notification', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
MockManifestHelper.prototype.name = 'translated';
|
||||
this.sinon.clock.tick(); // l10n ready
|
||||
assert.equal(attention.notificationTitle.textContent, 'translated');
|
||||
});
|
||||
|
||||
test('ready', function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
var callback1 = this.sinon.spy();
|
||||
attention.loaded = false;
|
||||
attention.ready(callback1);
|
||||
attention.element.dispatchEvent(new CustomEvent('_loaded'));
|
||||
this.sinon.clock.tick(0);
|
||||
assert.isTrue(callback1.called);
|
||||
|
||||
var callback2 = this.sinon.spy();
|
||||
attention.loaded = true;
|
||||
var stubTryWaitForFullRepaint =
|
||||
this.sinon.stub(attention, 'tryWaitForFullRepaint');
|
||||
attention.ready(callback2);
|
||||
stubTryWaitForFullRepaint.getCall(0).args[0]();
|
||||
this.sinon.clock.tick(0);
|
||||
assert.isTrue(callback2.called);
|
||||
});
|
||||
|
||||
test('_languagechange should re-translate the fake notification',
|
||||
function() {
|
||||
var attention = new AttentionWindow(fakeAttentionConfig);
|
||||
MockManifestHelper.prototype.name = 'translated';
|
||||
this.sinon.clock.tick(); // l10n ready
|
||||
assert.equal(attention.notificationTitle.textContent, 'translated');
|
||||
|
||||
attention.element.dispatchEvent(new CustomEvent('_languagechange'));
|
||||
MockManifestHelper.prototype.name = 'translated by languagechange';
|
||||
this.sinon.clock.tick(); // l10n ready
|
||||
assert.equal(attention.notificationTitle.textContent,
|
||||
'translated by languagechange');
|
||||
});
|
||||
});
|
||||
});
|
||||
229
gaia/apps/system/test/unit/audio_channel_controller_test.js
Executable file
229
gaia/apps/system/test/unit/audio_channel_controller_test.js
Executable file
|
|
@ -0,0 +1,229 @@
|
|||
/* global AudioChannelController */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/audio_channel_controller.js');
|
||||
|
||||
suite('system/AudioChannelController', function() {
|
||||
var subject;
|
||||
var mockApp = {
|
||||
instanceID: 'appID' ,
|
||||
element: {}
|
||||
};
|
||||
var mockChannel = {
|
||||
_domRequest: {},
|
||||
name: 'channelName' ,
|
||||
isActive: function() {
|
||||
return mockChannel._domRequest;
|
||||
},
|
||||
setMuted: function() {
|
||||
return mockChannel._domRequest;
|
||||
},
|
||||
setVolume: function() {
|
||||
return mockChannel._domRequest;
|
||||
},
|
||||
_triggerDomRequestOnsuccess: function() {
|
||||
mockChannel._domRequest.onsuccess({
|
||||
target: { result: true }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
mockApp.element = sinon.extend(mockApp.element, sinon.EventTarget);
|
||||
mockChannel = sinon.extend(mockChannel, sinon.EventTarget);
|
||||
subject = new AudioChannelController(mockApp, mockChannel);
|
||||
});
|
||||
|
||||
suite('Initialize the module', function() {
|
||||
test('Audio channel is not active', function() {
|
||||
assert.equal(subject.isActive(), false);
|
||||
});
|
||||
|
||||
test('Audio channel is not playing', function() {
|
||||
assert.equal(subject.isPlaying(), false);
|
||||
});
|
||||
|
||||
test('Audio channel is not fading out', function() {
|
||||
assert.equal(subject.isFadingOut(), false);
|
||||
});
|
||||
|
||||
test('It is not vibrating', function() {
|
||||
assert.equal(subject.isVibrating(), false);
|
||||
});
|
||||
|
||||
test('It is not vibrating', function() {
|
||||
assert.equal(subject.isVibrating(), false);
|
||||
});
|
||||
|
||||
test('The policy is empty', function() {
|
||||
assert.equal(Object.keys(subject._policy).length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Event handlers', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(subject, 'publish');
|
||||
});
|
||||
|
||||
test('Handle activestatechanged event', function() {
|
||||
mockChannel.dispatchEvent(
|
||||
new sinon.CustomEvent('activestatechanged', {}, mockChannel)
|
||||
);
|
||||
mockChannel._triggerDomRequestOnsuccess();
|
||||
assert.ok(subject.publish.withArgs('statechanged').calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Deal with policies', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(subject, '_play');
|
||||
this.sinon.spy(subject, '_pause');
|
||||
this.sinon.spy(subject, '_fadeOut');
|
||||
this.sinon.spy(subject, '_fadeIn');
|
||||
this.sinon.spy(subject, '_vibrate');
|
||||
});
|
||||
|
||||
test('Set policy', function() {
|
||||
var policy = { isAllowedToPlay: true };
|
||||
var audioChanel = subject.setPolicy(policy);
|
||||
assert.deepEqual(subject._policy, policy);
|
||||
assert.ok(audioChanel instanceof AudioChannelController);
|
||||
});
|
||||
|
||||
test('Get policy', function() {
|
||||
var expectedPolicy = { isAllowedToPlay: true };
|
||||
var policy = subject.setPolicy(expectedPolicy)
|
||||
.proceedPolicy()
|
||||
.getPolicy();
|
||||
assert.deepEqual(policy, expectedPolicy);
|
||||
});
|
||||
|
||||
test('Play the audio channel', function() {
|
||||
subject
|
||||
.setPolicy({ isAllowedToPlay: true })
|
||||
.proceedPolicy();
|
||||
assert.ok(subject._play.calledOnce);
|
||||
assert.ok(subject._pause.notCalled);
|
||||
assert.ok(subject._fadeOut.notCalled);
|
||||
assert.ok(subject._fadeIn.notCalled);
|
||||
assert.ok(subject._vibrate.notCalled);
|
||||
});
|
||||
|
||||
test('Pause the audio channel', function() {
|
||||
subject
|
||||
.setPolicy({ isAllowedToPlay: false })
|
||||
.proceedPolicy();
|
||||
assert.ok(subject._pause.calledOnce);
|
||||
assert.ok(subject._play.notCalled);
|
||||
assert.ok(subject._fadeOut.notCalled);
|
||||
assert.ok(subject._fadeIn.notCalled);
|
||||
assert.ok(subject._vibrate.notCalled);
|
||||
});
|
||||
|
||||
test('Fade in the audio channel', function() {
|
||||
subject
|
||||
.setPolicy({ isNeededToFadeOut: false })
|
||||
.proceedPolicy();
|
||||
assert.ok(subject._fadeIn.calledOnce);
|
||||
assert.ok(subject._play.notCalled);
|
||||
assert.ok(subject._pause.notCalled);
|
||||
assert.ok(subject._fadeOut.notCalled);
|
||||
assert.ok(subject._vibrate.notCalled);
|
||||
});
|
||||
|
||||
test('Fade out the audio channel', function() {
|
||||
subject
|
||||
.setPolicy({ isNeededToFadeOut: true })
|
||||
.proceedPolicy();
|
||||
assert.ok(subject._fadeOut.calledOnce);
|
||||
assert.ok(subject._play.calledOnce);
|
||||
assert.ok(subject._pause.notCalled);
|
||||
assert.ok(subject._fadeIn.notCalled);
|
||||
assert.ok(subject._vibrate.notCalled);
|
||||
});
|
||||
|
||||
test('Vibrate for the audio channel', function() {
|
||||
subject
|
||||
.setPolicy({ isNeededToVibrate: true })
|
||||
.proceedPolicy();
|
||||
assert.ok(subject._vibrate.calledOnce);
|
||||
assert.ok(subject._play.notCalled);
|
||||
assert.ok(subject._pause.notCalled);
|
||||
assert.ok(subject._fadeOut.notCalled);
|
||||
assert.ok(subject._fadeIn.notCalled);
|
||||
});
|
||||
|
||||
test('Do nothing', function() {
|
||||
subject.setPolicy().proceedPolicy();
|
||||
assert.ok(subject._play.notCalled);
|
||||
assert.ok(subject._pause.notCalled);
|
||||
assert.ok(subject._fadeOut.notCalled);
|
||||
assert.ok(subject._fadeIn.notCalled);
|
||||
assert.ok(subject._vibrate.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Handle audio channel', function() {
|
||||
test('Play the audio channel', function() {
|
||||
subject._play();
|
||||
assert.equal(subject.isPlaying(), true);
|
||||
});
|
||||
|
||||
test('Fade in the audio channel', function() {
|
||||
this.sinon.spy(subject, '_setVolume');
|
||||
var FADE_IN_VOLUME = 1;
|
||||
subject._fadeIn();
|
||||
assert.ok(subject._setVolume.withArgs(FADE_IN_VOLUME).calledOnce);
|
||||
assert.equal(subject.isFadingOut(), false);
|
||||
});
|
||||
|
||||
test('Fade out the audio channel', function() {
|
||||
this.sinon.spy(subject, '_play');
|
||||
this.sinon.spy(subject, '_setVolume');
|
||||
var FADE_OUT_VOLUME = 0.2;
|
||||
subject._fadeOut();
|
||||
assert.ok(subject._play.calledOnce);
|
||||
assert.ok(subject._setVolume.withArgs(FADE_OUT_VOLUME).calledOnce);
|
||||
assert.equal(subject.isFadingOut(), true);
|
||||
});
|
||||
|
||||
test('Pause the audio channel', function() {
|
||||
subject._pause();
|
||||
assert.equal(subject.isPlaying(), false);
|
||||
});
|
||||
|
||||
suite('Vibrate for the audio channel', function() {
|
||||
test('Start vibration', function() {
|
||||
subject._vibrate();
|
||||
assert.equal(subject.isVibrating(), true);
|
||||
});
|
||||
|
||||
test('Stop vibration', function() {
|
||||
var VIBRATION_DURATION = 1000;
|
||||
var clock = this.sinon.useFakeTimers();
|
||||
subject._vibrate();
|
||||
clock.tick(VIBRATION_DURATION);
|
||||
assert.equal(subject.isVibrating(), false);
|
||||
});
|
||||
});
|
||||
|
||||
test('Set the volume of audio channel', function() {
|
||||
this.sinon.spy(mockChannel, 'setVolume');
|
||||
subject._setVolume(1);
|
||||
assert.ok(mockChannel.setVolume.withArgs(1).calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('Destroy', function() {
|
||||
this.sinon.spy(subject, 'publish');
|
||||
subject.destroy();
|
||||
assert.ok(subject.publish.withArgs('destroyed').calledOnce);
|
||||
});
|
||||
|
||||
test('Generate instance ID', function() {
|
||||
var instanceID = mockApp.instanceID + '_' + mockChannel.name;
|
||||
subject._generateID();
|
||||
assert.equal(subject.instanceID, instanceID);
|
||||
});
|
||||
});
|
||||
445
gaia/apps/system/test/unit/audio_channel_policy_test.js
Executable file
445
gaia/apps/system/test/unit/audio_channel_policy_test.js
Executable file
|
|
@ -0,0 +1,445 @@
|
|||
/* global BaseModule */
|
||||
/* global MockAudioChannelController */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_audio_channel_controller.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/audio_channel_policy.js');
|
||||
|
||||
suite('system/AudioChannelPolicy', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('AudioChannelPolicy');
|
||||
});
|
||||
|
||||
test('Initialize the module', function() {
|
||||
assert.ok(subject._isVibrateEnabled);
|
||||
});
|
||||
|
||||
suite('Policies for handling audio channels', function() {
|
||||
/**
|
||||
* Check the policies.
|
||||
*
|
||||
* @param {Array|Object} audioChannels
|
||||
* The audio channels for generating policies.
|
||||
* @param {Object} expectedPolicy
|
||||
* The policy for the audio channels.
|
||||
* @param {Boolean} [isSameApp]
|
||||
* If true, the audio channels belong to same app.
|
||||
* Otherwise each audio channel belong to different app.
|
||||
*/
|
||||
function checkPolicy(audioChannels, expectedPolicy, isSameApp) {
|
||||
var appID = 0;
|
||||
audioChannels = Array.isArray(audioChannels) ?
|
||||
audioChannels : [audioChannels];
|
||||
expectedPolicy.activeAudioChannels =
|
||||
Array.isArray(expectedPolicy.activeAudioChannels) ?
|
||||
expectedPolicy.activeAudioChannels :
|
||||
[expectedPolicy.activeAudioChannels];
|
||||
audioChannels.map(function(obj) {
|
||||
var activeAudioChannels = new Map();
|
||||
obj.activeAudioChannels = Array.isArray(obj.activeAudioChannels) ?
|
||||
obj.activeAudioChannels : [obj.activeAudioChannels];
|
||||
var newAudioChannel =
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: appID }, { name: obj.newAudioChannel }
|
||||
);
|
||||
// Array to map.
|
||||
obj.activeAudioChannels.forEach(function(audioChannel, i) {
|
||||
if (!isSameApp) {
|
||||
appID++;
|
||||
}
|
||||
activeAudioChannels.set(i,
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: appID }, { name: audioChannel }
|
||||
)
|
||||
);
|
||||
});
|
||||
return {
|
||||
newAudioChannel: newAudioChannel,
|
||||
activeAudioChannels: activeAudioChannels
|
||||
};
|
||||
}).forEach(function(obj) {
|
||||
var newAudioChannel = obj.newAudioChannel;
|
||||
var activeAudioChannels = obj.activeAudioChannels;
|
||||
subject.applyPolicy(newAudioChannel, activeAudioChannels);
|
||||
assert.deepEqual(newAudioChannel._policy,
|
||||
expectedPolicy.newAudioChannel);
|
||||
activeAudioChannels.forEach(function(audioChannel, i) {
|
||||
assert.deepEqual(
|
||||
audioChannel._policy,
|
||||
expectedPolicy.activeAudioChannels[i]
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test('Play active and new audio channels', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'alarm',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'system', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'system',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'ringer',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'telephony',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'notification',
|
||||
activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'notification',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'system' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'ringer' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Pause active audio channel and ' +
|
||||
'play new audio channel', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'normal' },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: false,
|
||||
isNeededToVibrate: false,
|
||||
isNeededToResumeWhenOtherEnds: false,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Pause active audio channel, ' +
|
||||
'play new audio channel, ' +
|
||||
'and resume the pause audio channel when other ends', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'content' }
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: false,
|
||||
isNeededToVibrate: false,
|
||||
isNeededToResumeWhenOtherEnds: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Fade out active audio channel', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'alarm' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'normal' },
|
||||
{ newAudioChannel: 'publicnotification',
|
||||
activeAudioChannels: 'content' },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Fade out new audio channel', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'normal',
|
||||
activeAudioChannels: 'publicnotification' },
|
||||
{ newAudioChannel: 'content', activeAudioChannels: 'notification' },
|
||||
{ newAudioChannel: 'content',
|
||||
activeAudioChannels: 'publicnotification' }
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: true,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Vibrate for active audio channel', function(){
|
||||
checkPolicy(
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'ringer' },
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: false,
|
||||
isNeededToVibrate: true,
|
||||
isNeededToResumeWhenOtherEnds: true
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Vibrate for new audio channel', function(){
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'telephony' },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: false,
|
||||
isNeededToVibrate: true
|
||||
},
|
||||
activeAudioChannels: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Deconflict conflicted policy', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels:
|
||||
['system', 'telephony', 'publicnotification'] },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels:
|
||||
['system', 'telephony', 'publicnotification'] },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels:
|
||||
['system', 'telephony', 'publicnotification'] },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: false,
|
||||
isNeededToVibrate: true
|
||||
},
|
||||
activeAudioChannels: [
|
||||
{
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
{
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
{
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('All audio channels belong to same app', function() {
|
||||
checkPolicy(
|
||||
[
|
||||
{ newAudioChannel: 'normal', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'telephony', activeAudioChannels: 'content' },
|
||||
{ newAudioChannel: 'alarm', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'ringer', activeAudioChannels: 'telephony' },
|
||||
{ newAudioChannel: 'notification', activeAudioChannels: 'telephony' },
|
||||
],
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
// Do nothing for active audio channels.
|
||||
activeAudioChannels: {}
|
||||
},
|
||||
// All audio channels belong to same app.
|
||||
true
|
||||
);
|
||||
|
||||
checkPolicy(
|
||||
{
|
||||
newAudioChannel: 'normal',
|
||||
activeAudioChannels: [
|
||||
'content', 'alarm', 'system', 'ringer', 'telephony',
|
||||
'notification', 'publicnotification'
|
||||
]
|
||||
},
|
||||
{
|
||||
newAudioChannel: {
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false,
|
||||
},
|
||||
activeAudioChannels: [{}, {}, {}, {}, {}, {}, {}]
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
test('All audio channel except normal audio channel ' +
|
||||
'can play in background', function() {
|
||||
['content', 'alarm', 'system', 'ringer', 'telephony',
|
||||
'notification', 'publicnotification'].forEach(function(name) {
|
||||
var newAudioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: name }
|
||||
);
|
||||
var activeAudioChannels = new Map();
|
||||
subject.applyPolicy(newAudioChannel, activeAudioChannels,
|
||||
{ isNewAudioChannelInBackground: true });
|
||||
assert.deepEqual(
|
||||
newAudioChannel._policy,
|
||||
{
|
||||
isAllowedToPlay: true,
|
||||
isNeededToFadeOut: false
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Observe vibration.enabled', function() {
|
||||
test('Observed', function() {
|
||||
var index = subject.constructor.SETTINGS.indexOf('vibration.enabled');
|
||||
assert.ok(index !== -1);
|
||||
});
|
||||
|
||||
test('Enabled', function() {
|
||||
subject['_observe_vibration.enabled'](true);
|
||||
assert.equal(subject._isVibrateEnabled, true);
|
||||
});
|
||||
|
||||
test('Disabled', function() {
|
||||
subject['_observe_vibration.enabled'](false);
|
||||
assert.equal(subject._isVibrateEnabled, false);
|
||||
});
|
||||
});
|
||||
|
||||
test('Fade out new audio channel', function() {
|
||||
var isNeeded = [
|
||||
{ activeChannelName: 'notification', newChannelName: 'normal' },
|
||||
{ activeChannelName: 'notification', newChannelName: 'content' },
|
||||
{ activeChannelName: 'publicnotification', newChannelName: 'normal' },
|
||||
{ activeChannelName: 'publicnotification', newChannelName: 'content' }
|
||||
].map(function(obj) {
|
||||
return subject._isNeededToFadeOutForNewAudioChannel(
|
||||
obj.activeChannelName, obj.newChannelName
|
||||
);
|
||||
}).every(elem => elem);
|
||||
assert.equal(isNeeded, true);
|
||||
});
|
||||
|
||||
test('Fade out active audio channel', function() {
|
||||
var isNeeded = [
|
||||
{ activeChannelName: 'alarm', newChannelName: 'ringer' },
|
||||
{ activeChannelName: 'alarm', newChannelName: 'telephony' },
|
||||
{ activeChannelName: 'normal', newChannelName: 'notification' },
|
||||
{ activeChannelName: 'normal', newChannelName: 'publicnotification' },
|
||||
{ activeChannelName: 'content', newChannelName: 'notification' },
|
||||
{ activeChannelName: 'content', newChannelName: 'publicnotification' }
|
||||
].map(function(obj) {
|
||||
return subject._isNeededToFadeOutForActiveAudioChannel(
|
||||
obj.activeChannelName, obj.newChannelName
|
||||
);
|
||||
}).every(elem => elem);
|
||||
assert.equal(isNeeded, true);
|
||||
});
|
||||
|
||||
test('Vibrate for active audio channel', function() {
|
||||
var isNeeded = [
|
||||
{ activeChannelName: 'ringer', newChannelName: 'ringer' }
|
||||
].map(function(obj) {
|
||||
return subject._isNeededToVibrateForActiveAudioChannel(
|
||||
obj.activeChannelName, obj.newChannelName
|
||||
);
|
||||
}).every(elem => elem);
|
||||
assert.equal(isNeeded, true);
|
||||
});
|
||||
|
||||
test('Resume active audio channel when other ends', function() {
|
||||
var isNeeded = [
|
||||
{ activeChannelName: 'content', newChannelName: 'content' },
|
||||
{ activeChannelName: 'content', newChannelName: 'alarm' },
|
||||
{ activeChannelName: 'content', newChannelName: 'ringer' },
|
||||
{ activeChannelName: 'content', newChannelName: 'telephony' }
|
||||
].map(function(obj) {
|
||||
return subject._isNeededToResumeWhenOtherEndsForActiveAudioChannel(
|
||||
obj.activeChannelName, obj.newChannelName
|
||||
);
|
||||
}).every(elem => elem);
|
||||
assert.equal(isNeeded, true);
|
||||
});
|
||||
});
|
||||
418
gaia/apps/system/test/unit/audio_channel_service_test.js
Executable file
418
gaia/apps/system/test/unit/audio_channel_service_test.js
Executable file
|
|
@ -0,0 +1,418 @@
|
|||
/* global BaseModule, MockAudioChannelController, MockService */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_audio_channel_controller.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/audio_channel_service.js');
|
||||
|
||||
suite('system/AudioChannelService', function() {
|
||||
var subject;
|
||||
var audioChannels;
|
||||
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('AudioChannelService');
|
||||
subject.audioChannelPolicy = {
|
||||
applyPolicy: function() {}
|
||||
};
|
||||
audioChannels = new Map();
|
||||
['normal', 'notification', 'telephony'].forEach((name) => {
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: name }
|
||||
);
|
||||
audioChannels.set(name, audioChannel);
|
||||
this.sinon.spy(audioChannel, 'setPolicy');
|
||||
this.sinon.spy(audioChannel, 'proceedPolicy');
|
||||
});
|
||||
subject.service = MockService;
|
||||
MockService.mockQueryWith('SystemWindow.getAudioChannels', audioChannels);
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
subject.audioChannelPolicy = undefined;
|
||||
});
|
||||
|
||||
test('Should initial the module correctly', function() {
|
||||
assert.equal(subject._activeAudioChannels.size, 0);
|
||||
assert.equal(subject._interruptedAudioChannels.length, 0);
|
||||
});
|
||||
|
||||
test('Set all audio channels belonged to System app as muted', function() {
|
||||
audioChannels.forEach(function(audioChannel) {
|
||||
assert.ok(audioChannel.setPolicy.calledOnce);
|
||||
assert.ok(audioChannel.setPolicy.calledWith({ isAllowedToPlay: false }));
|
||||
assert.ok(audioChannel.proceedPolicy.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('Handle audiochannelstatechanged event', function() {
|
||||
this.sinon.spy(subject, '_manageAudioChannels');
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
var event = new CustomEvent('audiochannelstatechanged', {
|
||||
detail: audioChannel
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
assert.ok(subject._manageAudioChannels.calledOnce);
|
||||
});
|
||||
|
||||
test('Handle audiochanneldestroyed event', function() {
|
||||
this.sinon.spy(subject, '_deleteAudioChannelFromInterruptedAudioChannels');
|
||||
this.sinon.spy(subject, '_resumeAudioChannels');
|
||||
var instanceID = 'theAudioChannelID';
|
||||
var audioChannel = { instanceID: instanceID };
|
||||
var event = new CustomEvent('audiochanneldestroyed', {
|
||||
detail: audioChannel
|
||||
});
|
||||
// The audio channel is playing.
|
||||
subject._activeAudioChannels.set(instanceID, audioChannel);
|
||||
window.dispatchEvent(event);
|
||||
assert.ok(!subject._activeAudioChannels.has(instanceID));
|
||||
assert.ok(subject._deleteAudioChannelFromInterruptedAudioChannels
|
||||
.withArgs(audioChannel).calledOnce);
|
||||
assert.ok(subject._resumeAudioChannels.calledOnce);
|
||||
});
|
||||
|
||||
suite('Handle hierarchytopmostwindowchanged event', function() {
|
||||
var app;
|
||||
var event;
|
||||
|
||||
setup(function() {
|
||||
event = new CustomEvent('hierarchytopmostwindowchanged');
|
||||
app = {
|
||||
instanceID: 'appID',
|
||||
audioChannels: new Map()
|
||||
};
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
app, { name: 'normal' }
|
||||
);
|
||||
this.sinon.stub(audioChannel, 'isPlaying', function() {
|
||||
return true;
|
||||
});
|
||||
app.audioChannels.set('normal', audioChannel);
|
||||
window.Service = {
|
||||
query: function() {
|
||||
return app;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete window.Service;
|
||||
});
|
||||
|
||||
test('Resume all active audio channels in the app', function() {
|
||||
this.sinon.spy(subject, '_resumeAudioChannels');
|
||||
window.dispatchEvent(event);
|
||||
assert.ok(subject._resumeAudioChannels.withArgs(app).calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('Handle systemwindowaudiochannelsregistered event', function() {
|
||||
var event = new CustomEvent('systemwindowaudiochannelsregistered');
|
||||
this.sinon.spy(subject, '_muteSystemAudioChannels');
|
||||
window.dispatchEvent(event);
|
||||
assert.ok(subject._muteSystemAudioChannels.calledOnce);
|
||||
});
|
||||
|
||||
suite('Manage audio channels', function() {
|
||||
var audioChannel;
|
||||
|
||||
setup(function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
});
|
||||
|
||||
test('Handle new and active audio channels', function() {
|
||||
var isActiveStub = this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return true;
|
||||
});
|
||||
this.sinon.spy(subject.audioChannelPolicy, 'applyPolicy');
|
||||
this.sinon.spy(subject, '_handleAudioChannel');
|
||||
this.sinon.stub(subject, '_isAudioChannelInBackground', function() {
|
||||
return false;
|
||||
});
|
||||
subject._manageAudioChannels(audioChannel);
|
||||
assert.ok(isActiveStub.calledOnce);
|
||||
assert.ok(subject.audioChannelPolicy.applyPolicy.calledOnce);
|
||||
assert.ok(subject._isAudioChannelInBackground
|
||||
.withArgs(audioChannel).calledOnce);
|
||||
assert.ok(subject._handleAudioChannel
|
||||
.withArgs(audioChannel).calledOnce);
|
||||
});
|
||||
|
||||
test('Handle inactive audio channel ', function() {
|
||||
this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return false;
|
||||
});
|
||||
this.sinon.spy(subject, 'publish');
|
||||
subject._manageAudioChannels(audioChannel);
|
||||
var channel = { channel: 'none' };
|
||||
assert.ok(subject.publish
|
||||
.withArgs('audiochannelchanged', channel).calledOnce);
|
||||
});
|
||||
|
||||
suite('Foreground/background audio channel', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return true;
|
||||
});
|
||||
this.sinon.spy(subject, 'publish');
|
||||
});
|
||||
|
||||
test('In foreground', function() {
|
||||
var channel = { channel: 'content' };
|
||||
this.sinon.stub(subject, '_isAudioChannelInBackground', function() {
|
||||
return false;
|
||||
});
|
||||
this.sinon.stub(subject, '_getTopPriorityAudioChannel', function() {
|
||||
return channel.channel;
|
||||
});
|
||||
subject._manageAudioChannels(audioChannel);
|
||||
assert.ok(subject.publish
|
||||
.withArgs('visibleaudiochannelchanged', channel).calledOnce);
|
||||
assert.ok(subject.publish
|
||||
.withArgs('audiochannelchanged', channel).calledOnce);
|
||||
});
|
||||
|
||||
test('In background', function() {
|
||||
var channel = { channel: 'content' };
|
||||
this.sinon.stub(subject, '_isAudioChannelInBackground', function() {
|
||||
return true;
|
||||
});
|
||||
this.sinon.stub(subject, '_getTopPriorityAudioChannel', function() {
|
||||
return channel.channel;
|
||||
});
|
||||
subject._manageAudioChannels(audioChannel);
|
||||
assert.ok(subject.publish
|
||||
.withArgs('visibleaudiochannelchanged', channel).notCalled);
|
||||
assert.ok(subject.publish
|
||||
.withArgs('audiochannelchanged', channel).calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('Reset and resume audio channels', function() {
|
||||
var isActiveStub = this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return false;
|
||||
});
|
||||
this.sinon.spy(subject, '_resetAudioChannel');
|
||||
this.sinon.spy(subject, '_resumeAudioChannels');
|
||||
subject._manageAudioChannels(audioChannel);
|
||||
assert.ok(isActiveStub.calledOnce);
|
||||
assert.ok(subject._resetAudioChannel.withArgs(audioChannel).calledOnce);
|
||||
assert.ok(subject._resumeAudioChannels.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Reset the audio channel', function() {
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(subject, '_handleAudioChannel');
|
||||
});
|
||||
|
||||
test('Set audio channel as default state as muted', function() {
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
subject._resetAudioChannel(audioChannel);
|
||||
assert.deepEqual(audioChannel._policy, { isAllowedToPlay: false });
|
||||
assert.ok(subject._handleAudioChannel.withArgs(audioChannel).calledOnce);
|
||||
});
|
||||
|
||||
test('Fade in audio channel', function() {
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'notification' }
|
||||
);
|
||||
this.sinon.spy(subject, '_fadeInFadedOutAudioChannels');
|
||||
subject._resetAudioChannel(audioChannel);
|
||||
assert.ok(subject._fadeInFadedOutAudioChannels.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Handle audio channel', function() {
|
||||
var audioChannel;
|
||||
|
||||
setup(function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
});
|
||||
|
||||
test('Play the audio channel', function() {
|
||||
audioChannel.setPolicy({
|
||||
isAllowedToPlay: true
|
||||
});
|
||||
subject._handleAudioChannel(audioChannel);
|
||||
assert.ok(subject._activeAudioChannels.has(audioChannel.instanceID));
|
||||
});
|
||||
|
||||
test('Pause the audio channel', function() {
|
||||
subject._activeAudioChannels.set(audioChannel.instanceID, audioChannel);
|
||||
audioChannel.setPolicy({
|
||||
isAllowedToPlay: false
|
||||
});
|
||||
subject._handleAudioChannel(audioChannel);
|
||||
assert.ok(!subject._activeAudioChannels.has(audioChannel.instanceID));
|
||||
});
|
||||
|
||||
test('Resume the audio channel when other audio channel ends', function() {
|
||||
audioChannel.setPolicy({
|
||||
isAllowedToPlay: false,
|
||||
isNeededToResumeWhenOtherEnds: true
|
||||
});
|
||||
subject._handleAudioChannel(audioChannel);
|
||||
var interruptedAudioChannels = subject._interruptedAudioChannels;
|
||||
assert.equal(interruptedAudioChannels.length, 1);
|
||||
assert.deepEqual(interruptedAudioChannels.pop(), audioChannel);
|
||||
});
|
||||
});
|
||||
|
||||
test('Fade in audio channel', function() {
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
this.sinon.stub(audioChannel, 'isFadingOut', function() {
|
||||
return true;
|
||||
});
|
||||
subject._activeAudioChannels.set(audioChannel.instanceID, audioChannel);
|
||||
subject._fadeInFadedOutAudioChannels();
|
||||
assert.deepEqual(audioChannel._policy, { isNeededToFadeOut: false });
|
||||
});
|
||||
|
||||
suite('Resume audio channels', function() {
|
||||
var audioChannel;
|
||||
|
||||
setup(function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return true;
|
||||
});
|
||||
this.sinon.stub(audioChannel, 'isPlaying', function() {
|
||||
return true;
|
||||
});
|
||||
subject._interruptedAudioChannels.push(audioChannel);
|
||||
});
|
||||
|
||||
test('Resume the audio channels belong to the foreground app', function() {
|
||||
var app = {
|
||||
audioChannels: [audioChannel]
|
||||
};
|
||||
this.sinon.spy(subject, '_manageAudioChannels');
|
||||
subject._resumeAudioChannels(app);
|
||||
assert.ok(subject._manageAudioChannels.withArgs(audioChannel).calledOnce);
|
||||
assert.equal(subject._interruptedAudioChannels.length, 0);
|
||||
});
|
||||
|
||||
test('Resume the interrupted audio channel', function() {
|
||||
subject._resumeAudioChannels();
|
||||
assert.equal(subject._interruptedAudioChannels.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Delete audio channel from _interruptedAudioChannels', function() {
|
||||
var audioChannel;
|
||||
|
||||
setup(function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
subject._interruptedAudioChannels.push(audioChannel);
|
||||
});
|
||||
|
||||
test('Delete the audio channel', function() {
|
||||
subject._deleteAudioChannelFromInterruptedAudioChannels(audioChannel);
|
||||
assert.equal(subject._interruptedAudioChannels.length, 0);
|
||||
});
|
||||
|
||||
test('Do not delete the audio channel', function() {
|
||||
subject._deleteAudioChannelFromInterruptedAudioChannels(
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'normal' }
|
||||
)
|
||||
);
|
||||
subject._deleteAudioChannelFromInterruptedAudioChannels(
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: 'app2ID' }, { name: 'normal' }
|
||||
)
|
||||
);
|
||||
assert.deepEqual(subject._interruptedAudioChannels.pop(), audioChannel);
|
||||
});
|
||||
});
|
||||
|
||||
suite('App is in foreground or background', function() {
|
||||
var audioChannel;
|
||||
|
||||
test('Keybaord app is in foreground', function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'app1ID', isInputMethod: true }, { name: 'normal' }
|
||||
);
|
||||
this.sinon.stub(audioChannel, 'isActive', function() {
|
||||
return true;
|
||||
});
|
||||
assert.equal(subject._isAudioChannelInBackground(audioChannel), false);
|
||||
});
|
||||
|
||||
suite('Other apps except Keyboard app', function() {
|
||||
setup(function() {
|
||||
audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'app1ID' }, { name: 'content' }
|
||||
);
|
||||
});
|
||||
|
||||
test('In foreground', function() {
|
||||
subject._topMostWindow = { instanceID: 'app1ID' };
|
||||
assert.equal(subject._isAudioChannelInBackground(audioChannel), false);
|
||||
});
|
||||
|
||||
test('In background', function() {
|
||||
subject._topMostWindow = { instanceID: 'app2ID' };
|
||||
assert.equal(subject._isAudioChannelInBackground(audioChannel), true);
|
||||
});
|
||||
|
||||
test('Top most window is not changed', function() {
|
||||
assert.equal(subject._isAudioChannelInBackground(audioChannel), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('_getTopPriorityAudioChannel', function() {
|
||||
test('No top priority audio channel', function() {
|
||||
assert.equal(subject._getTopPriorityAudioChannel(), 'none');
|
||||
});
|
||||
|
||||
test('Only one audio channel is active', function() {
|
||||
var audioChannel = new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
);
|
||||
subject._activeAudioChannels.set(audioChannel.instanceID, audioChannel);
|
||||
assert.equal(subject._getTopPriorityAudioChannel(), 'content');
|
||||
});
|
||||
|
||||
test('Multiple audio channels are active', function() {
|
||||
var audioChannels = [
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'content' }
|
||||
),
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'ringer' }
|
||||
),
|
||||
new MockAudioChannelController(
|
||||
{ instanceID: 'appID' }, { name: 'notification' }
|
||||
)
|
||||
];
|
||||
audioChannels.forEach(function(audioChannel) {
|
||||
subject._activeAudioChannels.set(
|
||||
audioChannel.instanceID, audioChannel
|
||||
);
|
||||
});
|
||||
assert.equal(subject._getTopPriorityAudioChannel(), 'notification');
|
||||
});
|
||||
});
|
||||
});
|
||||
194
gaia/apps/system/test/unit/base_icon_test.js
Executable file
194
gaia/apps/system/test/unit/base_icon_test.js
Executable file
|
|
@ -0,0 +1,194 @@
|
|||
/* global BaseIcon, Service, MockL10n, MocksHelper */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
suite('system/BaseIcon', function() {
|
||||
var subject, manager, realL10n, container;
|
||||
|
||||
var mocksForBaseIcon = new MocksHelper([
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
mocksForBaseIcon.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
container = document.createElement('div');
|
||||
this.sinon.stub(Service, 'request', function() {
|
||||
return {
|
||||
then: function(callback) {
|
||||
callback(container);
|
||||
}
|
||||
};
|
||||
});
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
subject = new BaseIcon(manager);
|
||||
subject.shouldDisplay = function() {};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
suite('Service registration', function() {
|
||||
test('Should register to service while starting', function() {
|
||||
this.sinon.stub(Service, 'register');
|
||||
this.sinon.stub(Service, 'registerState');
|
||||
subject.start();
|
||||
assert.isTrue(Service.register.calledWith('show', subject));
|
||||
assert.isTrue(Service.register.calledWith('hide', subject));
|
||||
assert.isTrue(Service.register.calledWith('update', subject));
|
||||
assert.isTrue(Service.register.calledWith('stop', subject));
|
||||
assert.isTrue(Service.registerState.calledWith('isVisible', subject));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Render', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject, 'update');
|
||||
});
|
||||
|
||||
test('Should get the icon if it is already rendered', function(done) {
|
||||
subject.onrender = function() {
|
||||
assert.isDefined(subject.element);
|
||||
assert.isTrue(subject.element.classList.contains('active'));
|
||||
assert.isFalse(subject.isVisible());
|
||||
assert.isTrue(subject.update.called);
|
||||
done();
|
||||
};
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
subject.start();
|
||||
});
|
||||
|
||||
test('Should insert the element only once', function() {
|
||||
subject.render();
|
||||
var selector = '.BaseUI.active';
|
||||
assert.isTrue(container.querySelectorAll(selector).length === 1);
|
||||
subject.render();
|
||||
assert.isTrue(container.querySelectorAll(selector).length === 1);
|
||||
});
|
||||
|
||||
test('Should get the icon if it is lazily loaded', function(done) {
|
||||
subject.onrender = function() {
|
||||
assert.isDefined(subject.element);
|
||||
assert.isTrue(subject.element.classList.contains('active'));
|
||||
assert.isFalse(subject.isVisible());
|
||||
assert.isTrue(subject.update.called);
|
||||
done();
|
||||
};
|
||||
subject.start();
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
window.dispatchEvent(new CustomEvent('statusbariconrendered'));
|
||||
});
|
||||
|
||||
test('Should not update after rendering if UPDATE_ON_START is false',
|
||||
function(done) {
|
||||
subject.UPDATE_ON_START = false;
|
||||
subject.onrender = function() {
|
||||
assert.isDefined(subject.element);
|
||||
assert.isTrue(subject.element.classList.contains('active'));
|
||||
assert.isFalse(subject.isVisible());
|
||||
assert.isFalse(subject.update.called);
|
||||
done();
|
||||
};
|
||||
subject.start();
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
window.dispatchEvent(new CustomEvent('statusbariconrendered'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('UPDATE_ON_START', function() {
|
||||
setup(function() {
|
||||
subject.element = document.createElement('div');
|
||||
subject.element.hidden = true;
|
||||
this.sinon.stub(subject, 'update');
|
||||
});
|
||||
|
||||
test('Should update right away', function() {
|
||||
subject.UPDATE_ON_START = true;
|
||||
subject.start();
|
||||
assert.isTrue(subject.update.called);
|
||||
});
|
||||
|
||||
test('Should not update right away if not specified', function() {
|
||||
subject.UPDATE_ON_START = false;
|
||||
subject.start();
|
||||
assert.isFalse(subject.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('UpdateLabel', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
subject.element.hidden = true;
|
||||
this.sinon.spy(MockL10n, 'setAttributes');
|
||||
});
|
||||
|
||||
test('Should set l10n id', function() {
|
||||
subject.show();
|
||||
subject.updateLabel('test');
|
||||
assert.equal(MockL10n.getAttributes(subject.element).id,
|
||||
'statusbarIconOn-test');
|
||||
});
|
||||
|
||||
test('Should set l10n id when active', function() {
|
||||
subject.show();
|
||||
subject.updateLabel('test', true);
|
||||
assert.equal(MockL10n.getAttributes(subject.element).id,
|
||||
'statusbarIconOnActive-test');
|
||||
});
|
||||
});
|
||||
|
||||
suite('Update', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
subject.element.hidden = true;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
});
|
||||
|
||||
test('Should show icon if shouldDisplay is true', function() {
|
||||
this.sinon.stub(subject, 'shouldDisplay').returns(true);
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Should hide icon if shouldDisplay is false', function() {
|
||||
this.sinon.stub(subject, 'shouldDisplay').returns(false);
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
|
||||
suite('Show/Hide', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
subject.element.hidden = true;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
});
|
||||
|
||||
test('Should dispatch shown when show is called', function() {
|
||||
subject.hide();
|
||||
subject.show();
|
||||
assert.isTrue(subject.publish.calledWith('shown'));
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Should dispatch hidden when hide is called', function() {
|
||||
subject.show();
|
||||
subject.hide();
|
||||
assert.isTrue(subject.publish.calledWith('hidden'));
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
});
|
||||
747
gaia/apps/system/test/unit/base_module_test.js
Executable file
747
gaia/apps/system/test/unit/base_module_test.js
Executable file
|
|
@ -0,0 +1,747 @@
|
|||
/* 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
65
gaia/apps/system/test/unit/battery_icon_test.js
Executable file
65
gaia/apps/system/test/unit/battery_icon_test.js
Executable file
|
|
@ -0,0 +1,65 @@
|
|||
/* global BatteryIcon, MockNavigatorBattery, MockL10n */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/battery_icon.js');
|
||||
requireApp('system/test/unit/mock_navigator_battery.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
suite('system/BatteryIcon', function() {
|
||||
var subject, realMozL10n;
|
||||
|
||||
setup(function() {
|
||||
realMozL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
MockNavigatorBattery.level = 0.95;
|
||||
MockNavigatorBattery.charging = false;
|
||||
subject = new BatteryIcon({
|
||||
_battery: MockNavigatorBattery
|
||||
});
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realMozL10n;
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('should not publish changed when there is no change', function() {
|
||||
subject.update();
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.update();
|
||||
assert.isFalse(subject.publish.calledWith('changed'));
|
||||
});
|
||||
|
||||
test('should not publish iconchange when computed level does not change',
|
||||
function() {
|
||||
subject.update();
|
||||
MockNavigatorBattery.level = 0.95;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.update();
|
||||
|
||||
assert.isFalse(subject.publish.calledWith('changed'));
|
||||
});
|
||||
|
||||
test('should publish iconchange when battery changes', function() {
|
||||
subject.update();
|
||||
MockNavigatorBattery.level = 0.5;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.update();
|
||||
|
||||
assert.isTrue(subject.publish.calledWith('changed'));
|
||||
});
|
||||
|
||||
test('should publish iconchange when charging state changes', function() {
|
||||
subject.update();
|
||||
MockNavigatorBattery.charging = true;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.update();
|
||||
|
||||
assert.isTrue(subject.publish.calledWith('changed'));
|
||||
});
|
||||
});
|
||||
230
gaia/apps/system/test/unit/battery_overlay_test.js
Executable file
230
gaia/apps/system/test/unit/battery_overlay_test.js
Executable file
|
|
@ -0,0 +1,230 @@
|
|||
'use strict';
|
||||
/* global BaseModule */
|
||||
/* global MocksHelper */
|
||||
/* global MockL10n */
|
||||
/* global MockNavigatorBattery */
|
||||
/* global MockNavigatorSettings */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_navigator_battery.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/test/unit/mock_sleep_menu.js');
|
||||
requireApp('system/test/unit/mock_screen_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_gesture_detector.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/battery_icon.js');
|
||||
requireApp('system/js/power_save.js');
|
||||
requireApp('system/js/battery_overlay.js');
|
||||
|
||||
var mocksForBatteryOverlay = new MocksHelper([
|
||||
'SettingsListener',
|
||||
'sleepMenu',
|
||||
'GestureDetector',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('battery manager >', function() {
|
||||
var realBattery;
|
||||
var screenNode, notifNode, overlayNode;
|
||||
var tinyTimeout = 10;
|
||||
|
||||
var realMozSettings;
|
||||
var realL10n;
|
||||
var subject;
|
||||
|
||||
mocksForBatteryOverlay.attachTestHelpers();
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
// for PowerSave
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
subject._battery = realBattery;
|
||||
realBattery = null;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('BatteryOverlay');
|
||||
realBattery = subject._battery;
|
||||
subject._battery = MockNavigatorBattery;
|
||||
// must be big enough, otherwise the BatteryOverlay timeout occurs
|
||||
// before the different suites execute.
|
||||
subject.TOASTER_TIMEOUT = tinyTimeout;
|
||||
var batteryNotificationMarkup =
|
||||
'<div id="system-overlay" data-z-index-level="system-overlay">' +
|
||||
'<div id="battery">' +
|
||||
'<span class="icon-battery"></span>' +
|
||||
'<div class="battery-notification"> ' +
|
||||
'<span data-l10n-id="battery-almost-empty3">' +
|
||||
'Battery almost empty.' +
|
||||
'</span>' +
|
||||
'<span data-l10n-id="plug-in-your-charger">' +
|
||||
'Plug in your charger.' +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
screenNode = document.createElement('div');
|
||||
screenNode.id = 'screen';
|
||||
screenNode.innerHTML = batteryNotificationMarkup;
|
||||
document.body.appendChild(screenNode);
|
||||
|
||||
overlayNode = document.getElementById('system-overlay');
|
||||
notifNode = document.getElementById('battery');
|
||||
|
||||
MockNavigatorBattery.level = 1;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
screenNode.parentNode.removeChild(screenNode);
|
||||
});
|
||||
|
||||
function sendScreenChange(val) {
|
||||
var detail = { screenEnabled: val};
|
||||
var evt = new CustomEvent('screenchange', { detail: detail });
|
||||
window.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function sendLevelChange(level) {
|
||||
MockNavigatorBattery.level = level;
|
||||
|
||||
var evt = new CustomEvent('levelchange');
|
||||
MockNavigatorBattery.mTriggerEvent(evt);
|
||||
}
|
||||
|
||||
function sendChargingChange(val) {
|
||||
MockNavigatorBattery.charging = val;
|
||||
|
||||
var evt = new CustomEvent('chargingchange');
|
||||
MockNavigatorBattery.mTriggerEvent(evt);
|
||||
}
|
||||
|
||||
suite('"level is near empty" notification >', function() {
|
||||
function assertDisplayed() {
|
||||
assert.ok(overlayNode.classList.contains('battery'));
|
||||
}
|
||||
|
||||
function assertNotDisplayed() {
|
||||
assert.isFalse(overlayNode.classList.contains('battery'));
|
||||
}
|
||||
|
||||
teardown(function(done) {
|
||||
// wait for the notification timeout
|
||||
setTimeout(done, tinyTimeout * 2);
|
||||
});
|
||||
|
||||
suite('init >', function() {
|
||||
setup(function() {
|
||||
MockNavigatorBattery.level = 0.02;
|
||||
subject.start();
|
||||
});
|
||||
|
||||
test('display notification', function() {
|
||||
assertDisplayed();
|
||||
});
|
||||
|
||||
test('should send batteryshutdown when battery is below threshold',
|
||||
function() {
|
||||
this.sinon.stub(window, 'dispatchEvent');
|
||||
sendLevelChange(0.00);
|
||||
sinon.assert.calledWithMatch(window.dispatchEvent,
|
||||
{ type: 'batteryshutdown' });
|
||||
});
|
||||
});
|
||||
|
||||
suite('battery goes empty >', function() {
|
||||
setup(function() {
|
||||
sendLevelChange(0.05);
|
||||
subject.start();
|
||||
});
|
||||
|
||||
test('display notification', function() {
|
||||
assertDisplayed();
|
||||
});
|
||||
|
||||
test('do not display twice', function(done) {
|
||||
setTimeout(function() {
|
||||
sendLevelChange(0.02);
|
||||
|
||||
assertNotDisplayed();
|
||||
done();
|
||||
}, tinyTimeout * 2);
|
||||
});
|
||||
|
||||
suite('charging >', function() {
|
||||
setup(function() {
|
||||
sendChargingChange(true);
|
||||
});
|
||||
|
||||
test('hide notification', function() {
|
||||
assertNotDisplayed();
|
||||
});
|
||||
|
||||
test('not charging > show notification', function() {
|
||||
sendChargingChange(false);
|
||||
assertDisplayed();
|
||||
});
|
||||
|
||||
suite('goes up >', function() {
|
||||
setup(function() {
|
||||
sendLevelChange(0.2);
|
||||
});
|
||||
|
||||
test('hide notification', function() {
|
||||
assertNotDisplayed();
|
||||
});
|
||||
|
||||
suite('not charging >', function() {
|
||||
setup(function() {
|
||||
sendChargingChange(false);
|
||||
});
|
||||
|
||||
test('should not display', function() {
|
||||
assertNotDisplayed();
|
||||
});
|
||||
|
||||
test('goes empty again > display notification', function() {
|
||||
sendLevelChange(0.02);
|
||||
|
||||
assertDisplayed();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('screen goes off > battery goes empty >', function() {
|
||||
setup(function() {
|
||||
subject.start();
|
||||
sendScreenChange(false);
|
||||
sendLevelChange(0.05);
|
||||
});
|
||||
|
||||
test('no notification', function() {
|
||||
assertNotDisplayed();
|
||||
});
|
||||
|
||||
test('screen goes on > display notification', function() {
|
||||
sendScreenChange(true);
|
||||
|
||||
assertDisplayed();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
57
gaia/apps/system/test/unit/bluetooth_core_v2_test.js
Executable file
57
gaia/apps/system/test/unit/bluetooth_core_v2_test.js
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
/* global MockMozBluetooth, BaseModule, MocksHelper, MockLazyLoader */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_bluetooth_v2.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/bluetooth_v2.js');
|
||||
|
||||
var mocksForBluetoothCore = new MocksHelper([
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
function switchReadOnlyProperty(originObject, propName, targetObj) {
|
||||
Object.defineProperty(originObject, propName, {
|
||||
configurable: true,
|
||||
get: function() { return targetObj; }
|
||||
});
|
||||
}
|
||||
|
||||
suite('system/BluetoothCore', function() {
|
||||
var realMozBluetooth;
|
||||
mocksForBluetoothCore.attachTestHelpers();
|
||||
|
||||
setup(function(done) {
|
||||
MockLazyLoader.mLoadRightAway = true;
|
||||
this.sinon.spy(MockLazyLoader, 'load');
|
||||
|
||||
realMozBluetooth = navigator.mozBluetooth;
|
||||
switchReadOnlyProperty(navigator, 'mozBluetooth', MockMozBluetooth);
|
||||
|
||||
requireApp('system/js/bluetooth_core.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
switchReadOnlyProperty(navigator, 'mozBluetooth', realMozBluetooth);
|
||||
});
|
||||
|
||||
suite('BluetoothCore API', function() {
|
||||
var subject;
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('BluetoothCore');
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('read', function() {
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(
|
||||
['js/bluetooth_v2.js']
|
||||
));
|
||||
});
|
||||
});
|
||||
});
|
||||
36
gaia/apps/system/test/unit/bluetooth_headphone_icon_test.js
Executable file
36
gaia/apps/system/test/unit/bluetooth_headphone_icon_test.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
/* global BluetoothHeadphoneIcon, MockBluetooth */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/bluetooth_headphone_icon.js');
|
||||
requireApp('system/test/unit/mock_bluetooth.js');
|
||||
|
||||
suite('system/BluetoothHeadphoneIcon', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
subject = new BluetoothHeadphoneIcon(MockBluetooth);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Bluetooth headset is connected', function() {
|
||||
MockBluetooth.mExpectedProfile = 'a2dp';
|
||||
assert.isTrue(subject.shouldDisplay());
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Bluetooth headset is disconnected', function() {
|
||||
MockBluetooth.mExpectedProfile = '';
|
||||
assert.isFalse(subject.shouldDisplay());
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
54
gaia/apps/system/test/unit/bluetooth_icon_test.js
Executable file
54
gaia/apps/system/test/unit/bluetooth_icon_test.js
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
/* global BluetoothIcon, MockBluetooth, MockL10n */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/bluetooth_icon.js');
|
||||
requireApp('system/test/unit/mock_bluetooth.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
suite('system/BluetoothIcon', function() {
|
||||
var subject, realL10n;
|
||||
|
||||
setup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
subject = new BluetoothIcon(MockBluetooth);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Bluetooth is enabled', function() {
|
||||
MockBluetooth._settingsEnabled = true;
|
||||
MockBluetooth.connected = false;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
assert.equal(subject.element.dataset.active, 'false');
|
||||
assert.equal(MockL10n.getAttributes(subject.element).id,
|
||||
'statusbarIconOn-bluetooth');
|
||||
});
|
||||
|
||||
test('Bluetooth is enabled and connected', function() {
|
||||
MockBluetooth._settingsEnabled = true;
|
||||
MockBluetooth.connected = true;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
assert.equal(subject.element.dataset.active, 'true');
|
||||
assert.equal(MockL10n.getAttributes(subject.element).id,
|
||||
'statusbarIconOnActive-bluetooth');
|
||||
});
|
||||
|
||||
test('Bluetooth is disabled', function() {
|
||||
MockBluetooth._settingsEnabled = false;
|
||||
MockBluetooth.connected = false;
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
assert.equal(subject.element.dataset.active, 'false');
|
||||
});
|
||||
});
|
||||
36
gaia/apps/system/test/unit/bluetooth_transfer_icon_test.js
Executable file
36
gaia/apps/system/test/unit/bluetooth_transfer_icon_test.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
/* global BluetoothTransferIcon, MockBluetooth */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/bluetooth_transfer_icon.js');
|
||||
requireApp('system/test/unit/mock_bluetooth.js');
|
||||
|
||||
suite('system/BluetoothTransferIcon', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
subject = new BluetoothTransferIcon(MockBluetooth);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Bluetooth transfer is ongoing', function() {
|
||||
MockBluetooth.mExpectedProfile = 'opp';
|
||||
assert.isTrue(subject.shouldDisplay());
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Bluetooth transfer is done', function() {
|
||||
MockBluetooth.mExpectedProfile = '';
|
||||
assert.isFalse(subject.shouldDisplay());
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
901
gaia/apps/system/test/unit/bluetooth_transfer_test.js
Executable file
901
gaia/apps/system/test/unit/bluetooth_transfer_test.js
Executable file
|
|
@ -0,0 +1,901 @@
|
|||
/* global MocksHelper, MockNavigatormozSetMessageHandler,
|
||||
MockNavigatorGetDeviceStorage, MockL10n, MockBTAdapter, MockDOMRequest,
|
||||
BluetoothTransfer, MockNotificationHelper, MockNotification, MockUtilityTray,
|
||||
NotificationHelper, MockCustomDialog, MimeMapper, mockMozActivityInstance,
|
||||
Service, MockService, MockPromise */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_set_message_handler.js');
|
||||
require('/shared/test/unit/mocks/mock_event_target.js');
|
||||
require('/shared/test/unit/mocks/mock_dom_request.js');
|
||||
require('/shared/test/unit/mocks/mock_promise.js');
|
||||
require('/test/unit/mock_navigator_get_device_storage.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_bluetooth_v2.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_notification_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_notification.js');
|
||||
require('/shared/js/mime_mapper.js');
|
||||
require('/test/unit/mock_utility_tray.js');
|
||||
require('/test/unit/mock_nfc_handover_manager.js');
|
||||
require('/test/unit/mock_activity.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
require('/shared/test/unit/mocks/mock_custom_dialog.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
var mocksForBluetoothTransfer = new MocksHelper([
|
||||
'NotificationHelper',
|
||||
'MozActivity',
|
||||
'UtilityTray',
|
||||
'Service',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/bluetooth_transfer', function() {
|
||||
mocksForBluetoothTransfer.attachTestHelpers();
|
||||
|
||||
var realSetMessageHandler;
|
||||
var realNavigatorGetDeviceStorage;
|
||||
var realL10n;
|
||||
var realNotification;
|
||||
var real_sendingFilesQueue;
|
||||
|
||||
var fake_sendingFilesQueue;
|
||||
var fake_promiseAll;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realSetMessageHandler = navigator.mozSetMessageHandler;
|
||||
navigator.mozSetMessageHandler = MockNavigatormozSetMessageHandler;
|
||||
|
||||
realNavigatorGetDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockNavigatorGetDeviceStorage;
|
||||
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
realNotification = window.Notification;
|
||||
window.Notification = MockNotification;
|
||||
|
||||
MockNavigatormozSetMessageHandler.mSetup();
|
||||
|
||||
requireApp('system/js/bluetooth_transfer.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockNavigatormozSetMessageHandler.mTeardown();
|
||||
navigator.mozSetMessageHandler = realSetMessageHandler;
|
||||
navigator.getDeviceStorage = realNavigatorGetDeviceStorage;
|
||||
navigator.mozL10n = realL10n;
|
||||
window.Notification = realNotification;
|
||||
});
|
||||
|
||||
suite('Initialize', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(MockService, 'request', function(action) {
|
||||
if (action === 'showModalDialog') {
|
||||
MockCustomDialog.show(arguments[1], arguments[2],
|
||||
arguments[3], arguments[4]);
|
||||
} else if (action === 'hideCustomDialog') {
|
||||
MockCustomDialog.hide();
|
||||
}
|
||||
});
|
||||
this.sinon.spy(window, 'addEventListener');
|
||||
this.sinon.spy(window.navigator, 'mozSetMessageHandler');
|
||||
BluetoothTransfer.start();
|
||||
});
|
||||
|
||||
test('listener called', function() {
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('iac-bluetoothTransfercomms'));
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('bluetooth-opp-transfer-start'));
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('bluetooth-opp-transfer-complete'));
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('bluetooth-sendfile-via-handover'));
|
||||
});
|
||||
|
||||
test('MessageHandler called',
|
||||
function() {
|
||||
assert.ok(window.navigator.mozSetMessageHandler.calledWith(
|
||||
'bluetooth-opp-receiving-file-confirmation'));
|
||||
assert.ok(window.navigator.mozSetMessageHandler.calledWith(
|
||||
'bluetooth-opp-update-progress'));
|
||||
});
|
||||
|
||||
test('Service Request called', function() {
|
||||
assert.isTrue(MockService.request.calledOnce);
|
||||
assert.isTrue(MockService.request.calledWith(
|
||||
'handleSystemMessageNotification', 'BluetoothTransfer',
|
||||
BluetoothTransfer));
|
||||
});
|
||||
});
|
||||
|
||||
suite('UI', function() {
|
||||
suite('getDeviceName', function() {
|
||||
var address = 'AA:BB:CC:00:11:22';
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(MockBTAdapter, 'getConnectedDevices',
|
||||
function() {
|
||||
return new MockDOMRequest();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockBTAdapter.getConnectedDevices.reset();
|
||||
});
|
||||
|
||||
suite('cannot get adapter ', function() {
|
||||
test('should return unknown device name ', function(done) {
|
||||
this.sinon.stub(Service, 'query').returns(null);
|
||||
BluetoothTransfer.getDeviceName(address).then(function(deviceName) {
|
||||
assert.isFalse(MockBTAdapter.getConnectedDevices.called);
|
||||
assert.equal(deviceName, 'unknown-device');
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('request getConnectedDevices() onerror ', function() {
|
||||
test('should return unknown device name ', function(done) {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
BluetoothTransfer.getDeviceName(address).then(function(deviceName) {
|
||||
assert.isTrue(MockBTAdapter.getConnectedDevices.called);
|
||||
assert.equal(deviceName, 'unknown-device');
|
||||
}).then(done, done);
|
||||
|
||||
var connectedDevicesReq =
|
||||
MockBTAdapter.getConnectedDevices.getCall(0).returnValue;
|
||||
connectedDevicesReq.fireError(null);
|
||||
});
|
||||
});
|
||||
|
||||
suite('request getConnectedDevices() onsuccess ' +
|
||||
'without any devices ', function() {
|
||||
var mockConnectedDevices = null;
|
||||
test('should return unknown device name ', function(done) {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
BluetoothTransfer.getDeviceName(address).then(function(deviceName) {
|
||||
assert.isTrue(MockBTAdapter.getConnectedDevices.called);
|
||||
assert.equal(deviceName, 'unknown-device');
|
||||
}).then(done, done);
|
||||
|
||||
var connectedDevicesReq =
|
||||
MockBTAdapter.getConnectedDevices.getCall(0).returnValue;
|
||||
connectedDevicesReq.readyState = 'pending';
|
||||
connectedDevicesReq.fireSuccess(mockConnectedDevices);
|
||||
});
|
||||
});
|
||||
|
||||
suite('request getConnectedDevices() onsuccess ' +
|
||||
'with responding device ', function() {
|
||||
var mockConnectedDevices =
|
||||
[{name: 'device-No1',
|
||||
address: '00:11:22:AA:BB:CC'},
|
||||
{name: 'device-No2',
|
||||
address: 'AA:BB:CC:00:11:22'}];
|
||||
|
||||
test('should return responding device name ', function(done) {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
BluetoothTransfer.getDeviceName(address).then(function(deviceName) {
|
||||
assert.isTrue(MockBTAdapter.getConnectedDevices.called);
|
||||
assert.equal(deviceName, 'device-No2');
|
||||
}).then(done, done);
|
||||
|
||||
var connectedDevicesReq =
|
||||
MockBTAdapter.getConnectedDevices.getCall(0).returnValue;
|
||||
connectedDevicesReq.readyState = 'pending';
|
||||
connectedDevicesReq.fireSuccess(mockConnectedDevices);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('humanizeSize', function() {
|
||||
test('should handle zero size ', function() {
|
||||
var expectedSize = 'fileSize{"size":"0.00","unit":"byteUnit-B"}';
|
||||
assert.equal(expectedSize, BluetoothTransfer.humanizeSize(0));
|
||||
});
|
||||
|
||||
test('should handle bytes size ', function() {
|
||||
var expectedSize = 'fileSize{"size":"42.00","unit":"byteUnit-B"}';
|
||||
assert.equal(expectedSize, BluetoothTransfer.humanizeSize(42));
|
||||
});
|
||||
|
||||
test('should handle kilobytes size ', function() {
|
||||
var expectedSize = 'fileSize{"size":"1.00","unit":"byteUnit-KB"}';
|
||||
assert.equal(expectedSize, BluetoothTransfer.humanizeSize(1024));
|
||||
});
|
||||
|
||||
test('should handle megabytes size ', function() {
|
||||
var expectedSize = 'fileSize{"size":"4.67","unit":"byteUnit-MB"}';
|
||||
assert.equal(expectedSize, BluetoothTransfer.humanizeSize(4901024));
|
||||
});
|
||||
|
||||
test('should handle gigabytes size ', function() {
|
||||
var expectedSize = 'fileSize{"size":"3.73","unit":"byteUnit-GB"}';
|
||||
assert.equal(expectedSize, BluetoothTransfer.humanizeSize(4000901024));
|
||||
});
|
||||
});
|
||||
|
||||
suite('operate sending files queue ', function() {
|
||||
suiteSetup(function() {
|
||||
real_sendingFilesQueue = BluetoothTransfer._sendingFilesQueue;
|
||||
fake_sendingFilesQueue = [{
|
||||
numberOfFiles: 1,
|
||||
numSuccessful: 0,
|
||||
numUnsuccessful: 0
|
||||
}];
|
||||
BluetoothTransfer._sendingFilesQueue = fake_sendingFilesQueue;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
BluetoothTransfer._sendingFilesQueue = real_sendingFilesQueue;
|
||||
});
|
||||
|
||||
test('push sending files request in queue, then create notification ',
|
||||
function() {
|
||||
var sendingFilesSchedule = {
|
||||
numberOfFiles: 2,
|
||||
numSuccessful: 0,
|
||||
numUnsuccessful: 0
|
||||
};
|
||||
var evt = {
|
||||
detail: sendingFilesSchedule
|
||||
};
|
||||
var title = 'transferHasStartedTitle';
|
||||
BluetoothTransfer._onFilesSending(evt);
|
||||
assert.equal(2, BluetoothTransfer._sendingFilesQueue.length);
|
||||
assert.equal(MockNotificationHelper.mTitleL10n, title);
|
||||
});
|
||||
|
||||
test('received onTransferComplete callback for received task, ' +
|
||||
'should be ignored.. ', function() {
|
||||
var transferInfo = {
|
||||
received: true,
|
||||
success: true
|
||||
};
|
||||
BluetoothTransfer.summarizeSentFilesReport(transferInfo);
|
||||
assert.equal(2, BluetoothTransfer._sendingFilesQueue.length);
|
||||
assert.equal(MockNotificationHelper.mTitleL10n, null);
|
||||
});
|
||||
|
||||
test('received onTransferComplete callback for the first sent task, ' +
|
||||
'should remove the tast from queue.. ', function() {
|
||||
var transferInfo = {
|
||||
received: false,
|
||||
success: true
|
||||
};
|
||||
BluetoothTransfer.summarizeSentFilesReport(transferInfo);
|
||||
assert.equal(1, BluetoothTransfer._sendingFilesQueue.length);
|
||||
assert.equal(MockNotificationHelper.mTitleL10n, null);
|
||||
});
|
||||
|
||||
test('received onTransferComplete callback for the second sent task' +
|
||||
' --> first file, should record success/fail report in queue.. ',
|
||||
function() {
|
||||
var transferInfo = {
|
||||
received: false,
|
||||
success: false
|
||||
};
|
||||
BluetoothTransfer.summarizeSentFilesReport(transferInfo);
|
||||
assert.equal(1, BluetoothTransfer._sendingFilesQueue.length);
|
||||
assert.equal(1,
|
||||
BluetoothTransfer._sendingFilesQueue[0].numUnsuccessful);
|
||||
|
||||
assert.equal(MockNotificationHelper.mTitleL10n, null);
|
||||
});
|
||||
|
||||
test('received onTransferComplete callback for the second sent task' +
|
||||
' --> the second file, should remove the tast from queue. Then, ' +
|
||||
'create a report in notification.. ', function() {
|
||||
var transferInfo = {
|
||||
received: false,
|
||||
success: true
|
||||
};
|
||||
var title = 'transferReportTitle';
|
||||
var body = {
|
||||
id: 'transferReport-description',
|
||||
args: {'numSuccessful' : 1, 'numUnsuccessful' : 1}
|
||||
};
|
||||
|
||||
BluetoothTransfer.summarizeSentFilesReport(transferInfo);
|
||||
assert.equal(0, BluetoothTransfer._sendingFilesQueue.length);
|
||||
assert.equal(MockNotificationHelper.mTitleL10n, title);
|
||||
assert.equal(MockNotificationHelper.mOptions.bodyL10n.id, body.id);
|
||||
assert.deepEqual(
|
||||
MockNotificationHelper.mOptions.bodyL10n.args, body.args);
|
||||
});
|
||||
});
|
||||
|
||||
suite('confirmation, decline, accept, and storage check', function() {
|
||||
test('receivingFileConfirmation', function() {
|
||||
this.sinon.stub(BluetoothTransfer, 'getDeviceName', function() {
|
||||
return Promise.resolve('nameName');
|
||||
});
|
||||
|
||||
this.sinon.stub(MockUtilityTray, 'hide');
|
||||
this.sinon.stub(BluetoothTransfer, 'showReceivePrompt');
|
||||
var evt = {
|
||||
address: 'AA:BB:CC:00:11:22',
|
||||
fileLength: 1048000
|
||||
};
|
||||
|
||||
BluetoothTransfer.onReceivingFileConfirmation(evt);
|
||||
assert.isTrue(BluetoothTransfer.getDeviceName.calledWith(evt.address));
|
||||
BluetoothTransfer.getDeviceName().then(function() {
|
||||
assert.deepEqual(
|
||||
MockNotificationHelper.mTitleL10n,
|
||||
{id: 'transfer-confirmation-title', args: {deviceName: 'nameName'}}
|
||||
);
|
||||
assert.equal(
|
||||
MockNotificationHelper.mOptions.bodyL10n,
|
||||
'transfer-confirmation-desc'
|
||||
);
|
||||
assert.equal(
|
||||
MockNotificationHelper.mOptions.icon,
|
||||
'style/bluetooth_transfer/images/icon_bluetooth.png'
|
||||
);
|
||||
assert.equal(
|
||||
MockNotificationHelper.mOptions.mozbehavior,
|
||||
{noclear: true}
|
||||
);
|
||||
|
||||
NotificationHelper.mEmit('click');
|
||||
assert.isTrue(MockUtilityTray.hide.called);
|
||||
assert.isTrue(BluetoothTransfer.showReceivePrompt.called);
|
||||
MockNotificationHelper.mTeardown();
|
||||
});
|
||||
});
|
||||
|
||||
test('declineReceive', function() {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
this.sinon.spy(MockBTAdapter, 'confirmReceivingFile');
|
||||
|
||||
BluetoothTransfer.declineReceive('AA:BB:CC:00:22:33');
|
||||
|
||||
assert.isTrue(
|
||||
MockBTAdapter.confirmReceivingFile
|
||||
.calledWith('AA:BB:CC:00:22:33', false)
|
||||
);
|
||||
|
||||
MockBTAdapter.confirmReceivingFile.reset();
|
||||
|
||||
Service.query.restore();
|
||||
this.sinon.stub(Service, 'query').returns(null);
|
||||
|
||||
BluetoothTransfer.declineReceive('AA:BB:CC:00:22:33');
|
||||
assert.isFalse(MockBTAdapter.confirmReceivingFile.called);
|
||||
});
|
||||
|
||||
test('acceptReceive', function() {
|
||||
var evt = {
|
||||
address: 'AA:BB:CC:00:11:24',
|
||||
fileLength: 1048500
|
||||
};
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
this.sinon.stub(BluetoothTransfer, 'checkStorageSpace');
|
||||
this.sinon.stub(BluetoothTransfer, 'showStorageUnavaliablePrompt');
|
||||
this.sinon.spy(MockBTAdapter, 'confirmReceivingFile');
|
||||
|
||||
BluetoothTransfer.acceptReceive(evt);
|
||||
assert.isTrue(BluetoothTransfer.checkStorageSpace
|
||||
.calledWith(evt.fileLength));
|
||||
BluetoothTransfer.checkStorageSpace.getCall(0).args[1](true, 'somemsg');
|
||||
assert.isTrue(
|
||||
MockBTAdapter.confirmReceivingFile.calledWith(evt.address, true)
|
||||
);
|
||||
|
||||
MockBTAdapter.confirmReceivingFile.reset();
|
||||
BluetoothTransfer.checkStorageSpace.getCall(0)
|
||||
.args[1](false, 'somemsg2');
|
||||
assert.isTrue(
|
||||
MockBTAdapter.confirmReceivingFile.calledWith(evt.address, false)
|
||||
);
|
||||
assert.isTrue(BluetoothTransfer.showStorageUnavaliablePrompt
|
||||
.calledWith('somemsg2'));
|
||||
|
||||
MockBTAdapter.confirmReceivingFile.reset();
|
||||
|
||||
Service.query.restore();
|
||||
this.sinon.stub(Service, 'query').returns(null);
|
||||
|
||||
BluetoothTransfer.checkStorageSpace.getCall(0)
|
||||
.args[1](false, 'somemsg3');
|
||||
assert.isFalse(MockBTAdapter.confirmReceivingFile.called);
|
||||
});
|
||||
|
||||
test('showStorageUnavaliablePrompt', function() {
|
||||
this.sinon.stub(MockService, 'request');
|
||||
BluetoothTransfer.showStorageUnavaliablePrompt('message');
|
||||
|
||||
assert.isTrue(MockService.request.calledWith(
|
||||
'showCustomDialog',
|
||||
'cannotReceiveFile',
|
||||
'message'
|
||||
));
|
||||
MockService.request.getCall(0).args[3].callback();
|
||||
assert.isTrue(MockService.request.calledWith('hideCustomDialog'));
|
||||
});
|
||||
|
||||
test('checkStorageSpace', function() {
|
||||
var spyCb = this.sinon.spy();
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
this.sinon.spy(mockDeviceStorage, 'available');
|
||||
var spyFreeSpace = this.sinon.spy(mockDeviceStorage, 'freeSpace');
|
||||
|
||||
BluetoothTransfer.checkStorageSpace(10240, spyCb);
|
||||
|
||||
assert.isTrue(mockDeviceStorage.available.called);
|
||||
var availreq = mockDeviceStorage.available.getCall(0).returnValue;
|
||||
|
||||
availreq.fireError(null);
|
||||
assert.isTrue(spyCb.calledWithMatch(
|
||||
false,
|
||||
'cannotGetStorageState'
|
||||
));
|
||||
assert.isFalse(spyFreeSpace.called);
|
||||
spyFreeSpace.reset();
|
||||
spyCb.reset();
|
||||
|
||||
availreq.readyState = 'pending';
|
||||
availreq.fireSuccess('unavailable');
|
||||
sinon.assert.calledWithMatch(
|
||||
spyCb,
|
||||
false,
|
||||
'sdcard-not-exist2'
|
||||
);
|
||||
assert.isFalse(spyFreeSpace.called);
|
||||
spyFreeSpace.reset();
|
||||
spyCb.reset();
|
||||
|
||||
availreq.readyState = 'pending';
|
||||
availreq.fireSuccess('shared');
|
||||
sinon.assert.calledWithMatch(spyCb, false, 'sdcard-in-use');
|
||||
assert.isFalse(spyFreeSpace.called);
|
||||
spyFreeSpace.reset();
|
||||
spyCb.reset();
|
||||
|
||||
availreq.readyState = 'pending';
|
||||
availreq.fireSuccess('some-default-case');
|
||||
sinon.assert.calledWithMatch(spyCb, false, 'unknown-error');
|
||||
assert.isFalse(spyFreeSpace.called);
|
||||
spyFreeSpace.reset();
|
||||
spyCb.reset();
|
||||
|
||||
availreq.readyState = 'pending';
|
||||
availreq.fireSuccess('available');
|
||||
var freereq = spyFreeSpace.getCall(0).returnValue;
|
||||
freereq.fireError();
|
||||
assert.isTrue(spyCb.calledWithMatch(
|
||||
false,
|
||||
'cannotGetStorageState'
|
||||
));
|
||||
spyCb.reset();
|
||||
|
||||
freereq.readyState = 'pending';
|
||||
freereq.fireSuccess(20480);
|
||||
assert.isTrue(spyCb.calledWith(true, ''));
|
||||
spyCb.reset();
|
||||
|
||||
freereq.readyState = 'pending';
|
||||
freereq.fireSuccess(512);
|
||||
assert.isTrue(spyCb.calledWithMatch(
|
||||
false,
|
||||
'sdcard-no-space2'
|
||||
));
|
||||
spyCb.reset();
|
||||
|
||||
mockDeviceStorage.available.reset();
|
||||
BluetoothTransfer.checkStorageSpace(10240, null);
|
||||
assert.isFalse(mockDeviceStorage.available.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('openReceivedFile', function() {
|
||||
setup(function() {
|
||||
fake_promiseAll = new MockPromise();
|
||||
this.sinon.stub(Promise, 'all').returns(fake_promiseAll);
|
||||
});
|
||||
|
||||
test('until getreq.onsuccess', function() {
|
||||
var evt = {
|
||||
fileName: 'someFile.txt',
|
||||
contentType: 'text/plain'
|
||||
};
|
||||
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var spyGetDeviceStorage = this.sinon.spy(navigator, 'getDeviceStorage');
|
||||
var spyGet = this.sinon.spy(mockDeviceStorage, 'get');
|
||||
|
||||
BluetoothTransfer.openReceivedFile(evt);
|
||||
assert.isTrue(spyGetDeviceStorage.calledWith('sdcard'));
|
||||
assert.isTrue(spyGet.calledWith('Download/Bluetooth/' + evt.fileName));
|
||||
});
|
||||
|
||||
test('into getreq.onsuccess', function() {
|
||||
var evt = {
|
||||
fileName: 'someFile.txt',
|
||||
contentType: 'text/plain'
|
||||
};
|
||||
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var spyGet = this.sinon.spy(mockDeviceStorage, 'get');
|
||||
BluetoothTransfer.openReceivedFile(evt);
|
||||
|
||||
this.sinon.stub(MimeMapper, 'isSupportedType').returns(false);
|
||||
this.sinon.stub(MimeMapper, 'guessTypeFromExtension')
|
||||
.returns('text/plain');
|
||||
|
||||
var req = spyGet.getCall(0).returnValue;
|
||||
req.fireSuccess({
|
||||
name: evt.fileName,
|
||||
type: evt.contentType
|
||||
});
|
||||
fake_promiseAll.mFulfillToValue();
|
||||
|
||||
assert.equal(mockMozActivityInstance.name, 'open');
|
||||
assert.deepEqual(
|
||||
mockMozActivityInstance.data,
|
||||
{
|
||||
type: req.result.type,
|
||||
blob: req.result,
|
||||
filename: req.result.name
|
||||
}
|
||||
);
|
||||
|
||||
assert.isFunction(mockMozActivityInstance.onsuccess);
|
||||
assert.isFunction(mockMozActivityInstance.onerror);
|
||||
|
||||
var stubMockUtilityTrayHide = this.sinon.stub(MockUtilityTray, 'hide');
|
||||
var stubShowUnknownMediaPrompt =
|
||||
this.sinon.stub(BluetoothTransfer, 'showUnknownMediaPrompt');
|
||||
|
||||
mockMozActivityInstance.error = {
|
||||
name: 'NO_PROVIDER'
|
||||
};
|
||||
|
||||
mockMozActivityInstance.onerror(null);
|
||||
|
||||
assert.isTrue(stubMockUtilityTrayHide.called);
|
||||
assert.isTrue(stubShowUnknownMediaPrompt.calledWith(req.result.name));
|
||||
|
||||
stubMockUtilityTrayHide.reset();
|
||||
stubShowUnknownMediaPrompt.reset();
|
||||
|
||||
mockMozActivityInstance.error = {
|
||||
name: 'USER_ABORT'
|
||||
};
|
||||
|
||||
mockMozActivityInstance.onerror(null);
|
||||
|
||||
assert.isFalse(stubMockUtilityTrayHide.called);
|
||||
assert.isFalse(stubShowUnknownMediaPrompt.calledWith(req.result.name));
|
||||
});
|
||||
|
||||
test('getreq.onsuccess with vcard', function() {
|
||||
var evt = {
|
||||
fileName: 'someCard.vcf',
|
||||
contentType: 'text/vcard'
|
||||
};
|
||||
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var spyGet = this.sinon.spy(mockDeviceStorage, 'get');
|
||||
|
||||
BluetoothTransfer.openReceivedFile(evt);
|
||||
|
||||
this.sinon.stub(MimeMapper, 'isSupportedType').returns(true);
|
||||
|
||||
var req = spyGet.getCall(0).returnValue;
|
||||
|
||||
req.fireSuccess({
|
||||
name: evt.fileName,
|
||||
type: evt.contentType
|
||||
});
|
||||
fake_promiseAll.mFulfillToValue();
|
||||
|
||||
assert.equal(mockMozActivityInstance.name, 'import');
|
||||
assert.deepEqual(
|
||||
mockMozActivityInstance.data,
|
||||
{
|
||||
type: req.result.type,
|
||||
blob: req.result,
|
||||
filename: req.result.name
|
||||
}
|
||||
);
|
||||
|
||||
assert.isFunction(mockMozActivityInstance.onsuccess);
|
||||
assert.isFunction(mockMozActivityInstance.onerror);
|
||||
});
|
||||
|
||||
test('showUnknownMediaPrompt', function() {
|
||||
this.sinon.stub(MockService, 'request');
|
||||
BluetoothTransfer.showUnknownMediaPrompt('theFile.ext');
|
||||
|
||||
assert.isTrue(MockService.request.calledWith(
|
||||
'showCustomDialog',
|
||||
'cannotOpenFile',
|
||||
{
|
||||
id: 'unknownMediaTypeToOpenFile',
|
||||
args: {
|
||||
fileName: 'theFile.ext'
|
||||
}
|
||||
}
|
||||
));
|
||||
MockService.request.getCall(0).args[3].callback();
|
||||
assert.isTrue(MockService.request.calledWith('hideCustomDialog'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('sendFile', function() {
|
||||
test('sendFileViaHandover', function() {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
var spySendFile =
|
||||
this.sinon.spy(MockBTAdapter, 'sendFile');
|
||||
var stubOnFilesSending =
|
||||
this.sinon.stub(BluetoothTransfer, '_onFilesSending');
|
||||
var stubSetTimeout = this.sinon.stub(window, 'setTimeout');
|
||||
BluetoothTransfer.sendFileViaHandover({
|
||||
detail: {
|
||||
mac: 'AA:BB:CC:00:11:55',
|
||||
blob: 'blahblahblah\0xa0\0xa0blahblahblah'
|
||||
}
|
||||
});
|
||||
|
||||
assert.isTrue(stubOnFilesSending.called);
|
||||
assert.equal(typeof stubOnFilesSending.getCall(0).args[0], 'object');
|
||||
|
||||
assert.isTrue(stubSetTimeout.called);
|
||||
assert.isTrue(stubSetTimeout.getCall(0).args[1] > 0);
|
||||
stubSetTimeout.getCall(0).args[0]();
|
||||
|
||||
assert.isTrue(
|
||||
spySendFile
|
||||
.calledWith('AA:BB:CC:00:11:55', 'blahblahblah\0xa0\0xa0blahblahblah')
|
||||
);
|
||||
|
||||
Service.query.restore();
|
||||
this.sinon.stub(Service, 'query').returns(null);
|
||||
BluetoothTransfer.sendFileViaHandover({
|
||||
detail: {
|
||||
mac: 'AA:BB:CC:00:11:66',
|
||||
blob: 'blahblahblah\0xa0\0xa0blahblahblahblah'
|
||||
}
|
||||
});
|
||||
|
||||
stubOnFilesSending.reset();
|
||||
assert.isFalse(stubOnFilesSending.called);
|
||||
});
|
||||
|
||||
test('onUpdateProgress', function() {
|
||||
// mode = start
|
||||
var stubInitProgress =
|
||||
this.sinon.stub(BluetoothTransfer, 'initProgress');
|
||||
var evt = {
|
||||
detail: {
|
||||
transferInfo: 'info123'
|
||||
}
|
||||
};
|
||||
|
||||
BluetoothTransfer._onUpdateProgress('start', evt);
|
||||
assert.isTrue(stubInitProgress.calledWith('info123'));
|
||||
|
||||
// mode = progress
|
||||
var stubUpdateProgress =
|
||||
this.sinon.stub(BluetoothTransfer, 'updateProgress');
|
||||
evt = {
|
||||
address: 'AA:BB:DD:11:22:44',
|
||||
processedLength: '1024',
|
||||
fileLength: '2048'
|
||||
};
|
||||
|
||||
BluetoothTransfer._onUpdateProgress('progress', evt);
|
||||
assert.isTrue(
|
||||
Math.abs(stubUpdateProgress.getCall(0).args[0]) -
|
||||
(evt.processedLength / evt.fileLength) <
|
||||
0.00001
|
||||
);
|
||||
assert.equal(stubUpdateProgress.getCall(0).args[1], evt);
|
||||
|
||||
evt.fileLength = 0;
|
||||
BluetoothTransfer._onUpdateProgress('progress', evt);
|
||||
assert.isTrue(stubUpdateProgress.calledWith(0, evt));
|
||||
|
||||
evt.fileLength = 1024;
|
||||
evt.processedLength = 1000;
|
||||
BluetoothTransfer._onUpdateProgress('progress', evt);
|
||||
assert.isTrue(stubUpdateProgress.calledWith(0, evt));
|
||||
|
||||
stubUpdateProgress.reset();
|
||||
});
|
||||
|
||||
test('onCancelTransferTask', function() {
|
||||
var stubMockUtilityTrayHide = this.sinon.stub(MockUtilityTray, 'hide');
|
||||
var stubShowCancelTransferPrompt =
|
||||
this.sinon.stub(BluetoothTransfer, 'showCancelTransferPrompt');
|
||||
|
||||
BluetoothTransfer.onCancelTransferTask({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
id: 1234
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assert.isTrue(stubMockUtilityTrayHide.called);
|
||||
assert.isTrue(stubShowCancelTransferPrompt.calledWith(1234));
|
||||
});
|
||||
|
||||
test('showCancelTransferPrompt', function() {
|
||||
this.sinon.stub(MockService, 'request');
|
||||
var stubContinueTransfer =
|
||||
this.sinon.stub(BluetoothTransfer, 'continueTransfer');
|
||||
var stubCancelTransfer =
|
||||
this.sinon.stub(BluetoothTransfer, 'cancelTransfer');
|
||||
|
||||
BluetoothTransfer.showCancelTransferPrompt('DD:FE:00:11:22:33');
|
||||
|
||||
assert.isTrue(MockService.request.calledWith('showCustomDialog',
|
||||
'cancelFileTransfer', 'cancelFileTransfer'));
|
||||
assert.equal(
|
||||
MockService.request.getCall(0).args[3].title,
|
||||
'no'
|
||||
);
|
||||
assert.equal(
|
||||
MockService.request.getCall(0).args[4].title,
|
||||
'yes'
|
||||
);
|
||||
|
||||
MockService.request.getCall(0).args[3].callback();
|
||||
assert.isTrue(stubContinueTransfer.called);
|
||||
|
||||
MockService.request.getCall(0).args[4].callback();
|
||||
assert.isTrue(stubCancelTransfer.calledWith('DD:FE:00:11:22:33'));
|
||||
});
|
||||
|
||||
test('cancelTransfer', function() {
|
||||
this.sinon.stub(Service, 'query').returns(MockBTAdapter);
|
||||
var spyStopSendingFile =
|
||||
this.sinon.spy(MockBTAdapter, 'stopSendingFile');
|
||||
MockCustomDialog.mTeardown();
|
||||
BluetoothTransfer.cancelTransfer('CC:DD:00:AA:22:44');
|
||||
assert.isTrue(spyStopSendingFile.calledWith('CC:DD:00:AA:22:44'));
|
||||
|
||||
Service.query.restore();
|
||||
this.sinon.stub(Service, 'query').returns(null);
|
||||
|
||||
spyStopSendingFile.reset();
|
||||
|
||||
BluetoothTransfer.cancelTransfer('CC:DD:00:AA:22:44');
|
||||
assert.isFalse(spyStopSendingFile.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('isSendFileQueueEmpty', function() {
|
||||
test('True if queue is empty', function() {
|
||||
assert.isTrue(BluetoothTransfer.isSendFileQueueEmpty());
|
||||
});
|
||||
|
||||
test('False is queue is not empty', function() {
|
||||
BluetoothTransfer._sendingFilesQueue.push(1);
|
||||
assert.isFalse(BluetoothTransfer.isSendFileQueueEmpty());
|
||||
BluetoothTransfer._sendingFilesQueue.splice(0);
|
||||
});
|
||||
});
|
||||
|
||||
suite('NfcHandoverManager interactions', function() {
|
||||
var stubRemoveProgress;
|
||||
var stubSummarizeSentFilesReport;
|
||||
|
||||
var transferEvt;
|
||||
|
||||
setup(function() {
|
||||
// In this suite, we care about NfcHandoverManager.transferComplete()
|
||||
// only.
|
||||
stubRemoveProgress = this.sinon.stub(BluetoothTransfer,
|
||||
'removeProgress');
|
||||
stubSummarizeSentFilesReport = this.sinon.stub(BluetoothTransfer,
|
||||
'summarizeSentFilesReport');
|
||||
|
||||
transferEvt = {
|
||||
detail: {
|
||||
transferInfo: {
|
||||
success: true,
|
||||
received: false
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubRemoveProgress.restore();
|
||||
stubSummarizeSentFilesReport.restore();
|
||||
});
|
||||
|
||||
test('transferComplete() called for NFC originated transfer',
|
||||
function() {
|
||||
var stubEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
BluetoothTransfer._onTransferComplete(transferEvt);
|
||||
|
||||
assert.equal(stubEvent.firstCall.args[0].type,
|
||||
'nfc-transfer-completed');
|
||||
assert.deepEqual(stubEvent.firstCall.args[0].detail, {
|
||||
viaHandover: false,
|
||||
success: true,
|
||||
received: false
|
||||
});
|
||||
});
|
||||
|
||||
test('transferComplete() called for non-NFC originated transfer',
|
||||
function() {
|
||||
var stubEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
BluetoothTransfer._sendingFilesQueue.push({
|
||||
viaHandover: true
|
||||
});
|
||||
BluetoothTransfer._onTransferComplete(transferEvt);
|
||||
|
||||
assert.deepEqual(stubEvent.firstCall.args[0].detail, {
|
||||
viaHandover: true,
|
||||
success: true,
|
||||
received: false
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('handleSystemMessageNotification behavior', function() {
|
||||
test('calls openReceivedFile', function() {
|
||||
var message = {
|
||||
body: 'someFile.txt',
|
||||
data: {
|
||||
systemMessageTarget: 'BluetoothTransfer',
|
||||
transferInfo: {
|
||||
'fileName': 'someFile.txt',
|
||||
'contentType': ''
|
||||
},
|
||||
}
|
||||
};
|
||||
this.sinon.spy(BluetoothTransfer, 'openReceivedFile');
|
||||
this.sinon.spy(BluetoothTransfer, 'closeSystemMessageNotification');
|
||||
BluetoothTransfer.handleSystemMessageNotification(message);
|
||||
|
||||
assert.isTrue(BluetoothTransfer.openReceivedFile.calledOnce);
|
||||
assert.isTrue(
|
||||
BluetoothTransfer.closeSystemMessageNotification.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('closeSystemMessageNotification behavior', function() {
|
||||
var notifCloseSpy, notificationGetStub;
|
||||
var notification = {
|
||||
body: 'fake',
|
||||
data: {
|
||||
systemMessageTarget: 'BluetoothTransfer'
|
||||
},
|
||||
close: function() {}
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
notifCloseSpy = this.sinon.spy(notification, 'close');
|
||||
notificationGetStub = function notificationGet() {
|
||||
return {
|
||||
then: function(cb) {
|
||||
cb && cb([ notification ]);
|
||||
}
|
||||
};
|
||||
};
|
||||
this.sinon.stub(window.Notification, 'get', notificationGetStub);
|
||||
});
|
||||
|
||||
test('closes notification by body', function() {
|
||||
var tag = notification.tag;
|
||||
notification.tag = undefined;
|
||||
|
||||
BluetoothTransfer.closeSystemMessageNotification(notification);
|
||||
assert.isTrue(window.Notification.get.calledOnce);
|
||||
assert.isTrue(window.Notification.get.calledWith(
|
||||
{ tag: notification.tag}));
|
||||
assert.isTrue(notifCloseSpy.calledOnce);
|
||||
|
||||
notification.tag = tag;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
507
gaia/apps/system/test/unit/bluetooth_v2_test.js
Executable file
507
gaia/apps/system/test/unit/bluetooth_v2_test.js
Executable file
|
|
@ -0,0 +1,507 @@
|
|||
/* global Bluetooth, MockSettingsListener, Service, MockL10n,
|
||||
MockNavigatorSettings, MockNavigatormozSetMessageHandler,
|
||||
MockMozBluetooth, MockBTAdapter, MocksHelper, MockLazyLoader */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_set_message_handler.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_bluetooth_v2.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/bluetooth_icon.js');
|
||||
requireApp('system/js/bluetooth_transfer_icon.js');
|
||||
requireApp('system/js/bluetooth_headphone_icon.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
function switchReadOnlyProperty(originObject, propName, targetObj) {
|
||||
Object.defineProperty(originObject, propName, {
|
||||
configurable: true,
|
||||
get: function() { return targetObj; }
|
||||
});
|
||||
}
|
||||
|
||||
var mocksForBluetooth = new MocksHelper([
|
||||
'SettingsListener',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/bluetooth_v2', function() {
|
||||
var realSetMessageHandler;
|
||||
var realSettings;
|
||||
var realSettingsListener;
|
||||
var realMozBluetooth;
|
||||
var realL10n;
|
||||
mocksForBluetooth.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
MockLazyLoader.mLoadRightAway = true;
|
||||
sinon.spy(MockLazyLoader, 'load');
|
||||
|
||||
realSetMessageHandler = navigator.mozSetMessageHandler;
|
||||
navigator.mozSetMessageHandler = MockNavigatormozSetMessageHandler;
|
||||
MockNavigatormozSetMessageHandler.mSetup();
|
||||
|
||||
realSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
realSettingsListener = window.SettingsListener;
|
||||
window.SettingsListener = MockSettingsListener;
|
||||
|
||||
realMozBluetooth = navigator.mozBluetooth;
|
||||
switchReadOnlyProperty(navigator, 'mozBluetooth', MockMozBluetooth);
|
||||
|
||||
realL10n = window.navigator.mozL10n;
|
||||
window.navigator.mozL10n = MockL10n;
|
||||
|
||||
requireApp('system/js/bluetooth_v2.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockNavigatormozSetMessageHandler.mTeardown();
|
||||
navigator.mozSetMessageHandler = realSetMessageHandler;
|
||||
window.SettingsListener = realSettingsListener;
|
||||
switchReadOnlyProperty(navigator, 'mozBluetooth', realMozBluetooth);
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
// instanciate bluetooth module
|
||||
window.Bluetooth = new window.Bluetooth2();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.Bluetooth.stop();
|
||||
});
|
||||
|
||||
suite('setProfileConnected', function() {
|
||||
var profiles = ['hfp', 'opp', 'a2dp', 'sco'];
|
||||
setup(function() {
|
||||
this.sinon.spy(window, 'dispatchEvent');
|
||||
Bluetooth.icon = { update: function() {} };
|
||||
this.sinon.stub(Bluetooth.icon, 'update');
|
||||
});
|
||||
|
||||
test('nothing is called when wasConnected', function() {
|
||||
profiles.forEach(function(profile){
|
||||
Bluetooth['_' + profile + 'Connected'] = true;
|
||||
Bluetooth._setProfileConnected(profile, true);
|
||||
assert.isFalse(window.dispatchEvent.called);
|
||||
assert.isFalse(Bluetooth.icon.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
test('event is dispatched, Bluetooth icon is updated when disconnected',
|
||||
function() {
|
||||
profiles.forEach(function(profile){
|
||||
Bluetooth['_' + profile + 'Connected'] = true;
|
||||
Bluetooth._setProfileConnected(profile, false);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
assert.isTrue(Bluetooth.icon.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
test('event is dispatched, Bluetooth icon is updated when first connect',
|
||||
function() {
|
||||
profiles.forEach(function(profile){
|
||||
Bluetooth['_' + profile + 'Connected'] = false;
|
||||
Bluetooth._setProfileConnected(profile, true);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
assert.isTrue(Bluetooth.icon.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
test('event is dispatched with right detail object', function(done) {
|
||||
Bluetooth._oppConnected = false;
|
||||
var handler = function(evt) {
|
||||
assert.equal(evt.detail.name, 'opp');
|
||||
assert.isTrue(evt.detail.connected);
|
||||
done();
|
||||
};
|
||||
var bindHandler = handler.bind(this);
|
||||
window.addEventListener('bluetoothprofileconnectionchange',
|
||||
bindHandler);
|
||||
Bluetooth._setProfileConnected('opp', true);
|
||||
window.removeEventListener('bluetoothprofileconnectionchange',
|
||||
bindHandler);
|
||||
});
|
||||
|
||||
test('transferIcon is not updated with non-OPP profile',
|
||||
function() {
|
||||
Bluetooth.transferIcon = { update: function() {} };
|
||||
this.sinon.stub(Bluetooth.transferIcon, 'update');
|
||||
Bluetooth._setProfileConnected('hfp', false);
|
||||
assert.isFalse(Bluetooth.transferIcon.update.called);
|
||||
Bluetooth._setProfileConnected('a2dp', false);
|
||||
assert.isFalse(Bluetooth.transferIcon.update.called);
|
||||
Bluetooth._setProfileConnected('sco', false);
|
||||
});
|
||||
|
||||
test('transferIcon is updated with OPP profile', function() {
|
||||
Bluetooth.transferIcon = { update: function() {} };
|
||||
this.sinon.stub(Bluetooth.transferIcon, 'update');
|
||||
Bluetooth._setProfileConnected('opp', false);
|
||||
assert.isTrue(Bluetooth.transferIcon.update.called);
|
||||
Bluetooth._setProfileConnected('opp', true);
|
||||
assert.isTrue(Bluetooth.transferIcon.update.calledTwice);
|
||||
});
|
||||
});
|
||||
|
||||
suite('isProfileConnected', function() {
|
||||
var profiles = ['hfp', 'opp', 'a2dp', 'sco'];
|
||||
|
||||
test('return true when profile is connected', function() {
|
||||
profiles.forEach(function(profile) {
|
||||
Bluetooth['_' + profile + 'Connected'] = false;
|
||||
});
|
||||
profiles.forEach(function(profile) {
|
||||
assert.isFalse(Bluetooth._isProfileConnected(profile));
|
||||
});
|
||||
});
|
||||
|
||||
test('return true when profile is connected', function() {
|
||||
profiles.forEach(function(profile) {
|
||||
Bluetooth['_' + profile + 'Connected'] = true;
|
||||
});
|
||||
profiles.forEach(function(profile) {
|
||||
assert.ok(Bluetooth._isProfileConnected(profile));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Initialize', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(navigator.mozBluetooth, 'addEventListener');
|
||||
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
||||
this.sinon.stub(Bluetooth, '_initDefaultAdapter');
|
||||
this.sinon.spy(window, 'addEventListener');
|
||||
this.sinon.spy(window, 'dispatchEvent');
|
||||
this.sinon.spy(Service, 'register');
|
||||
this.sinon.spy(Service, 'registerState');
|
||||
window.BluetoothTransfer = { start: function() {} };
|
||||
Bluetooth.start();
|
||||
});
|
||||
|
||||
test('initDefaultAdapter is called', function() {
|
||||
assert.ok(Bluetooth._initDefaultAdapter.called);
|
||||
});
|
||||
|
||||
test('listener called', function() {
|
||||
assert.ok(navigator.mozBluetooth.addEventListener.
|
||||
calledWith('attributechanged'));
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('request-enable-bluetooth'));
|
||||
assert.ok(window.addEventListener
|
||||
.calledWith('request-disable-bluetooth'));
|
||||
});
|
||||
|
||||
test('MessageHandler bluetooth-opp-transfer-start is called',
|
||||
function() {
|
||||
MockNavigatormozSetMessageHandler.mTrigger(
|
||||
'bluetooth-opp-transfer-start', {
|
||||
source: {
|
||||
data: {}
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(Bluetooth._setProfileConnected.called);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
});
|
||||
|
||||
test('MessageHandler bluetooth-opp-transfer-complete is called',
|
||||
function() {
|
||||
MockNavigatormozSetMessageHandler.mTrigger(
|
||||
'bluetooth-opp-transfer-complete', {
|
||||
source: {
|
||||
data: {}
|
||||
}
|
||||
});
|
||||
|
||||
assert.ok(Bluetooth._setProfileConnected.called);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
});
|
||||
|
||||
test('register request', function() {
|
||||
assert.ok(Service.register.calledWith('adapter'));
|
||||
assert.ok(Service.register.calledWith('pair'));
|
||||
assert.ok(Service.register.calledWith('getPairedDevices'));
|
||||
});
|
||||
|
||||
test('register state', function() {
|
||||
assert.ok(Service.registerState.calledWith('isEnabled'));
|
||||
assert.ok(Service.registerState.calledWith('getAdapter'));
|
||||
assert.ok(Service.registerState.calledWith('isOPPProfileConnected'));
|
||||
assert.ok(Service.registerState.calledWith('isA2DPProfileConnected'));
|
||||
assert.ok(Service.registerState.calledWith('isSCOProfileConnected'));
|
||||
});
|
||||
|
||||
test('Should lazy load icons', function() {
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(
|
||||
['js/bluetooth_transfer.js',
|
||||
'js/bluetooth_icon.js',
|
||||
'js/bluetooth_transfer_icon.js',
|
||||
'js/bluetooth_headphone_icon.js']
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
suite('initDefaultAdapter', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(Bluetooth, '_dispatchEnableState');
|
||||
Bluetooth._bluetooth = MockMozBluetooth;
|
||||
});
|
||||
|
||||
test('defaultAdapter is available', function() {
|
||||
Bluetooth._bluetooth.defaultAdapter = MockBTAdapter;
|
||||
Bluetooth._initDefaultAdapter();
|
||||
|
||||
assert.equal(Bluetooth._adapter, navigator.mozBluetooth.defaultAdapter);
|
||||
assert.ok(Bluetooth._dispatchEnableState.called);
|
||||
});
|
||||
|
||||
test('defaultAdapter is not available', function() {
|
||||
Bluetooth._bluetooth.defaultAdapter = null;
|
||||
Bluetooth._initDefaultAdapter();
|
||||
|
||||
assert.equal(Bluetooth._adapter, null);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Adapter Available Handler', function() {
|
||||
setup(function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
this.sinon.stub(Bluetooth._adapter, 'addEventListener');
|
||||
Bluetooth._adapterAvailableHandler();
|
||||
});
|
||||
|
||||
test('return true when profile is connected', function() {
|
||||
assert.ok(MockBTAdapter.addEventListener.
|
||||
calledWith('attributechanged'));
|
||||
assert.ok(MockBTAdapter.addEventListener
|
||||
.calledWith('hfpstatuschanged'));
|
||||
assert.ok(MockBTAdapter.addEventListener
|
||||
.calledWith('a2dpstatuschanged'));
|
||||
assert.ok(MockBTAdapter.addEventListener
|
||||
.calledWith('scostatuschanged'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Adapter Unavailable Handler', function() {
|
||||
setup(function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
this.sinon.stub(Bluetooth._adapter, 'removeEventListener');
|
||||
Bluetooth._adapterUnavailableHandler();
|
||||
});
|
||||
|
||||
test('removeEventListener is called', function() {
|
||||
assert.ok(Bluetooth._adapter.removeEventListener
|
||||
.calledWith('hfpstatuschanged'));
|
||||
assert.ok(Bluetooth._adapter.removeEventListener
|
||||
.calledWith('a2dpstatuschanged'));
|
||||
assert.ok(Bluetooth._adapter.removeEventListener
|
||||
.calledWith('scostatuschanged'));
|
||||
assert.ok(Bluetooth._adapter.removeEventListener
|
||||
.calledWith('attributechanged'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('handle Bluetooth states', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(Bluetooth, '_requestEnableHandler');
|
||||
this.sinon.spy(Bluetooth, '_requestDisableHandler');
|
||||
this.sinon.spy(Bluetooth, '_dispatchEnableState');
|
||||
this.sinon.stub(Bluetooth, '_initDefaultAdapter');
|
||||
|
||||
this.sinon.stub(MockBTAdapter, 'enable', function() {
|
||||
return { then: function(resolve) { resolve(); } };
|
||||
});
|
||||
this.sinon.stub(MockBTAdapter, 'disable', function() {
|
||||
return { then: function(resolve) { resolve(); } };
|
||||
});
|
||||
});
|
||||
|
||||
test('request-enable-bluetooth is called', function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
Bluetooth.start();
|
||||
window.dispatchEvent(new CustomEvent('request-enable-bluetooth'));
|
||||
|
||||
assert.ok(Bluetooth._requestEnableHandler.called);
|
||||
assert.ok(MockBTAdapter.enable.called);
|
||||
});
|
||||
|
||||
test('request-enable-bluetooth is called when adapter is not available',
|
||||
function() {
|
||||
Bluetooth._adapter = null;
|
||||
Bluetooth.start();
|
||||
window.dispatchEvent(new CustomEvent('request-enable-bluetooth'));
|
||||
|
||||
assert.ok(Bluetooth._dispatchEnableState.called);
|
||||
});
|
||||
|
||||
test('request-disable-bluetooth is called', function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
Bluetooth.start();
|
||||
window.dispatchEvent(new CustomEvent('request-disable-bluetooth'));
|
||||
|
||||
assert.ok(Bluetooth._requestDisableHandler.called);
|
||||
assert.ok(MockBTAdapter.disable.called);
|
||||
});
|
||||
|
||||
test('request-disable-bluetooth is called when adapter is not available',
|
||||
function() {
|
||||
Bluetooth._adapter = null;
|
||||
Bluetooth.start();
|
||||
|
||||
window.dispatchEvent(new CustomEvent('request-disable-bluetooth'));
|
||||
assert.ok(Bluetooth._dispatchEnableState.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('bluetoothAdapterHandler', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(MockNavigatorSettings, 'createLock');
|
||||
this.sinon.stub(window, 'dispatchEvent');
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
Bluetooth.icon = { update: function() {} };
|
||||
this.sinon.stub(Bluetooth.icon, 'update');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Bluetooth._adapter = null;
|
||||
Bluetooth.icon = null;
|
||||
});
|
||||
|
||||
test('bluetooth state is enabled', function() {
|
||||
Bluetooth._adapter.state = 'enabled';
|
||||
Bluetooth._btAdapterHandler({attrs: ['state']});
|
||||
|
||||
assert.isTrue(Bluetooth._isEnabled);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
assert.ok(Bluetooth.icon.update.called);
|
||||
});
|
||||
|
||||
test('bluetooth state is disabled', function() {
|
||||
Bluetooth._adapter.state = 'disabled';
|
||||
Bluetooth._btAdapterHandler({attrs: ['state']});
|
||||
|
||||
assert.isFalse(Bluetooth._isEnabled);
|
||||
assert.ok(window.dispatchEvent.called);
|
||||
assert.ok(Bluetooth.icon.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('btManagerHandler', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(Bluetooth, '_adapterUnavailableHandler');
|
||||
Bluetooth._bluetooth = window.navigator.mozBluetooth;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Bluetooth._adapter = null;
|
||||
MockBTAdapter.state = '';
|
||||
});
|
||||
|
||||
test('default adapter and state are updated when defaultAdapter' +
|
||||
'is changed', function() {
|
||||
var evt = {
|
||||
attrs: ['defaultAdapter']
|
||||
};
|
||||
MockMozBluetooth.defaultAdapter = MockBTAdapter;
|
||||
MockBTAdapter.state = 'enabled';
|
||||
Bluetooth._btManagerHandler(evt);
|
||||
|
||||
assert.equal(Bluetooth._adapter, MockBTAdapter);
|
||||
assert.ok(Bluetooth._isEnabled, true);
|
||||
});
|
||||
|
||||
test('functions are not called when defaultAdapter is null',
|
||||
function() {
|
||||
var evt = {
|
||||
attrs: ['defaultAdapter']
|
||||
};
|
||||
MockMozBluetooth.defaultAdapter = null;
|
||||
Bluetooth._btManagerHandler(evt);
|
||||
|
||||
assert.equal(Bluetooth._adapter, null);
|
||||
assert.ok(Bluetooth._adapterUnavailableHandler.called);
|
||||
});
|
||||
|
||||
test('functions are not called when no matched attribute',
|
||||
function() {
|
||||
var evt = {
|
||||
attrs: []
|
||||
};
|
||||
MockMozBluetooth.defaultAdapter = null;
|
||||
Bluetooth._btManagerHandler(evt);
|
||||
|
||||
assert.equal(Bluetooth._adapter, null);
|
||||
assert.ok(!Bluetooth._adapterUnavailableHandler.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('oppTransferStartHandler', function() {
|
||||
test('event is dispatched with right detail object', function(done) {
|
||||
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
||||
var transferInfo = this.sinon.stub();
|
||||
var handler = function(evt) {
|
||||
assert.equal(evt.detail.transferInfo, transferInfo);
|
||||
done();
|
||||
};
|
||||
var bindHandler = handler.bind(this);
|
||||
window.addEventListener('bluetooth-opp-transfer-start',
|
||||
bindHandler);
|
||||
Bluetooth._oppTransferStartHandler(transferInfo);
|
||||
assert.ok(Bluetooth._setProfileConnected.called);
|
||||
window.removeEventListener('bluetooth-opp-transfer-start',
|
||||
bindHandler);
|
||||
});
|
||||
});
|
||||
|
||||
suite('oppTransferCompleteHandler', function() {
|
||||
test('event is dispatched with right detail object', function(done) {
|
||||
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
||||
var transferInfo = this.sinon.stub();
|
||||
var handler = function(evt) {
|
||||
assert.equal(evt.detail.transferInfo, transferInfo);
|
||||
done();
|
||||
};
|
||||
var bindHandler = handler.bind(this);
|
||||
window.addEventListener('bluetooth-opp-transfer-complete',
|
||||
bindHandler);
|
||||
Bluetooth._oppTransferCompleteHandler(transferInfo);
|
||||
assert.ok(Bluetooth._setProfileConnected.called);
|
||||
window.removeEventListener('bluetooth-opp-transfer-complete',
|
||||
bindHandler);
|
||||
});
|
||||
});
|
||||
|
||||
suite('service requests', function() {
|
||||
test('request the adapter', function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
Service.request('Bluetooth:adapter').then(function(value) {
|
||||
assert.equal(value, Bluetooth._adapter);
|
||||
});
|
||||
});
|
||||
|
||||
test('request pair', function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
var mac = '01:23:45:67:89:AB';
|
||||
this.sinon.spy(MockBTAdapter, 'pair');
|
||||
Service.request('Bluetooth:pair', mac).then(function() {
|
||||
assert.ok(MockBTAdapter.pair.calledWith(mac));
|
||||
});
|
||||
});
|
||||
|
||||
test('request getPairedDevices', function() {
|
||||
Bluetooth._adapter = MockBTAdapter;
|
||||
this.sinon.spy(MockBTAdapter, 'getPairedDevices');
|
||||
Service.request('Bluetooth:getPairedDevices')
|
||||
.then(function() {
|
||||
assert.ok(MockBTAdapter.getPairedDevices.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
459
gaia/apps/system/test/unit/browser_context_menu_test.js
Executable file
459
gaia/apps/system/test/unit/browser_context_menu_test.js
Executable file
|
|
@ -0,0 +1,459 @@
|
|||
/* global MocksHelper, MockL10n, AppWindow, BaseModule, MockNavigatorSettings,
|
||||
MockMozActivity, MozActivity, MockAppWindowHelper, MockService */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_icons_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_activity.js');
|
||||
requireApp('system/test/unit/mock_orientation_manager.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_context_menu_view.js');
|
||||
requireApp('system/test/unit/mock_pin_page_system_dialog.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_activity.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
require('/js/browser_config_helper.js');
|
||||
require('/js/service.js');
|
||||
require('/js/base_module.js');
|
||||
|
||||
const PINNING_PREF = 'dev.gaia.pinning_the_web';
|
||||
|
||||
var mocksForAppModalDialog = new MocksHelper([
|
||||
'AppWindow', 'MozActivity', 'LazyLoader', 'IconsHelper', 'ContextMenuView',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/BrowserContextMenu', function() {
|
||||
var stubById, realL10n, stubQuerySelector, realMozActivity,
|
||||
realMozSettings;
|
||||
|
||||
mocksForAppModalDialog.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozL10n = MockL10n;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
MockNavigatorSettings.mSetup();
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
MockService.mockQueryWith('isFtuRunning', false);
|
||||
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
var e = document.createElement('div');
|
||||
stubQuerySelector = this.sinon.stub(e, 'querySelector');
|
||||
stubQuerySelector.returns(document.createElement('div'));
|
||||
stubById.returns(e);
|
||||
|
||||
window.BookmarksDatabase = {
|
||||
get: function() {
|
||||
return new Promise(function(resolve) { resolve(false); });
|
||||
}
|
||||
};
|
||||
|
||||
this.sinon.stub(BaseModule, 'lazyLoad', function() {
|
||||
return {
|
||||
'then': function(callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
requireApp('system/js/browser_context_menu.js', done);
|
||||
realMozActivity = window.MozActivity;
|
||||
window.MozActivity = MockMozActivity;
|
||||
MozActivity.mSetup();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockNavigatorSettings.mTeardown();
|
||||
stubById.restore();
|
||||
stubQuerySelector.restore();
|
||||
MozActivity.mTeardown();
|
||||
window.MozActivity = realMozActivity;
|
||||
delete window.BookmarksDatabase;
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
var fakeBrowserConfig = {
|
||||
url: 'http://mozilla.org/index.html',
|
||||
manifest: {},
|
||||
origin: 'http://mozilla.org'
|
||||
};
|
||||
|
||||
var fakePrivateConfig = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake',
|
||||
isPrivate: true
|
||||
};
|
||||
|
||||
var fakeContextMenuEvent = {
|
||||
type: 'mozbrowsercontextmenu',
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
contextmenu: {
|
||||
items: [{
|
||||
label: 'test0',
|
||||
icon: 'test'
|
||||
}],
|
||||
customized: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var SYSTEM_TARGET_TYPES = [
|
||||
'a',
|
||||
'A',
|
||||
'IMG',
|
||||
'VIDEO',
|
||||
'AUDIO'
|
||||
];
|
||||
|
||||
var fakeSystemContextMenuEvents = [];
|
||||
|
||||
SYSTEM_TARGET_TYPES.forEach(function(type) {
|
||||
fakeSystemContextMenuEvents.push({
|
||||
type: 'mozbrowsercontextmenu',
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
contextmenu: {
|
||||
items: [],
|
||||
customized: false
|
||||
},
|
||||
systemTargets: [{
|
||||
nodeName: type,
|
||||
data: {
|
||||
uri: 'http://fake.com'
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var fakeEmptyContextMenuEvent = {
|
||||
type: 'mozbrowsercontextmenu',
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
detail: {}
|
||||
};
|
||||
|
||||
var fakeNoItemsContextMenuEvent = {
|
||||
type: 'mozbrowsercontextmenu',
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
detail: {
|
||||
contextmenu: {
|
||||
items: [],
|
||||
customized: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test('start', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
assert.isDefined(md1);
|
||||
assert.isDefined(md1.contextMenuView);
|
||||
});
|
||||
|
||||
test('stop', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
this.sinon.spy(md1.contextMenuView, 'destroy');
|
||||
md1.stop();
|
||||
assert.isTrue(md1.contextMenuView.destroy.calledOnce);
|
||||
assert.isNull(md1.containerElement);
|
||||
assert.isNull(md1.app);
|
||||
});
|
||||
|
||||
test('launch menu', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
this.sinon.stub(md1.contextMenuView, 'show');
|
||||
|
||||
var stubStopPropagation =
|
||||
this.sinon.stub(fakeContextMenuEvent, 'stopPropagation');
|
||||
var stubPreventDefault =
|
||||
this.sinon.stub(fakeContextMenuEvent, 'preventDefault');
|
||||
|
||||
md1.handleEvent(fakeContextMenuEvent);
|
||||
|
||||
// Checking that we stop propagation *before* getting
|
||||
// the pinning setting
|
||||
assert.isTrue(stubStopPropagation.called);
|
||||
assert.isTrue(stubPreventDefault.called);
|
||||
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.isTrue(md1.contextMenuView.show.called);
|
||||
});
|
||||
|
||||
suite('manually launch menu', function() {
|
||||
var md1;
|
||||
|
||||
setup(function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
md1.showDefaultMenu();
|
||||
});
|
||||
|
||||
test('Context Menu is shown', function() {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.isTrue(md1.isShown());
|
||||
});
|
||||
|
||||
test('Context Menu is not shown', function() {
|
||||
md1.hide();
|
||||
assert.isFalse(md1.isShown());
|
||||
});
|
||||
});
|
||||
|
||||
test('Context Menu is not shown during FTU', function() {
|
||||
var app1 = new AppWindow(fakeBrowserConfig);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
this.sinon.stub(md1, 'show');
|
||||
MockService.mockQueryWith('isFtuRunning', true);
|
||||
|
||||
md1.handleEvent(fakeSystemContextMenuEvents[0]);
|
||||
assert.isFalse(md1.show.called);
|
||||
});
|
||||
|
||||
test('Check that a context menu containing items is prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.handleEvent(fakeContextMenuEvent);
|
||||
assert.isTrue(fakeContextMenuEvent.defaultPrevented);
|
||||
});
|
||||
|
||||
test('Check that an empty context menu is not prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.handleEvent(fakeEmptyContextMenuEvent);
|
||||
assert.isTrue(!fakeEmptyContextMenuEvent.defaultPrevented);
|
||||
});
|
||||
|
||||
test('Check that a context menu without items is not prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.handleEvent(fakeNoItemsContextMenuEvent);
|
||||
assert.isTrue(!fakeNoItemsContextMenuEvent.defaultPrevented);
|
||||
});
|
||||
|
||||
test('System menu with invalid items is not prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
app1.isBrowser = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
var fakeEvent = {
|
||||
type: 'mozbrowsercontextmenu',
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
stopPropagation: function() {},
|
||||
detail: {
|
||||
contextmenu: {
|
||||
items: [],
|
||||
customized: false
|
||||
},
|
||||
systemTargets: [{
|
||||
nodeName: 'INPUT',
|
||||
data: {
|
||||
uri: 'http://fake.com'
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
md1.handleEvent(fakeEvent);
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.isFalse(fakeEvent.defaultPrevented);
|
||||
});
|
||||
|
||||
|
||||
test('Check that a system menu without items is prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
app1.isBrowser = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
for (var i = 0; i < fakeSystemContextMenuEvents.length; i++) {
|
||||
var event = fakeSystemContextMenuEvents[i];
|
||||
md1.handleEvent(event);
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
assert.isTrue(event.defaultPrevented);
|
||||
}
|
||||
});
|
||||
|
||||
suite('Pinning the web', function() {
|
||||
var app1, md1;
|
||||
|
||||
setup(function() {
|
||||
app1 = new AppWindow(fakeBrowserConfig);
|
||||
md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
});
|
||||
|
||||
test('Shows pinning when clicking on the context button', function(done) {
|
||||
this.sinon.stub(md1.contextMenuView, 'show', function(items) {
|
||||
assert.isTrue(items[3].id === 'pin-to-home-screen');
|
||||
done();
|
||||
});
|
||||
var settingObj = {};
|
||||
settingObj[PINNING_PREF] = true;
|
||||
MockNavigatorSettings.mSet(settingObj);
|
||||
md1.showDefaultMenu();
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
});
|
||||
|
||||
test('Does not show pinning when longpressing link', function(done) {
|
||||
this.sinon.stub(md1.contextMenuView, 'show', function(items) {
|
||||
assert.isFalse(items[2].id === 'add-to-homescreen');
|
||||
assert.isFalse(items[2].id === 'pin-to-homescreen');
|
||||
done();
|
||||
});
|
||||
var settingObj = {};
|
||||
settingObj[PINNING_PREF] = true;
|
||||
MockNavigatorSettings.mSet(settingObj);
|
||||
md1.handleEvent(fakeSystemContextMenuEvents[0]);
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
});
|
||||
});
|
||||
|
||||
test('Check that an app with system menu is not prevented', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
app1.isCertified = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
for (var i = 0; i < fakeSystemContextMenuEvents.length; i++) {
|
||||
var event = fakeSystemContextMenuEvents[i];
|
||||
event.defaultPrevented = false;
|
||||
md1.handleEvent(event);
|
||||
assert.isFalse(event.defaultPrevented);
|
||||
}
|
||||
});
|
||||
|
||||
test('newWindow() - private browser', function() {
|
||||
var app1 = new AppWindow(fakePrivateConfig);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.newWindow('http://search.gaiamobile.org/manifest.webapp', true);
|
||||
|
||||
var app = MockAppWindowHelper.mLatest;
|
||||
assert.equal(app.isPrivate, true);
|
||||
});
|
||||
|
||||
test('bookmark/share buttons hidden in private browser', function(done) {
|
||||
var app1 = new AppWindow(fakePrivateConfig);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
var app2 = new AppWindow(fakeBrowserConfig);
|
||||
var md2 = BaseModule.instantiate('BrowserContextMenu', app2);
|
||||
md2.start();
|
||||
|
||||
var md1ShowStub = this.sinon.stub(md1.contextMenuView, 'show');
|
||||
var md2ShowStub = this.sinon.stub(md2.contextMenuView, 'show');
|
||||
Promise.all([
|
||||
md1.showDefaultMenu(),
|
||||
md2.showDefaultMenu()
|
||||
]).then(() => {
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
var md1Items = md1ShowStub.getCall(0).args[0];
|
||||
var md2Items = md2ShowStub.getCall(0).args[0];
|
||||
// We should not show the bookmark or share buttons.
|
||||
assert.equal(md2Items.length - md1Items.length, 2);
|
||||
done();
|
||||
});
|
||||
MockNavigatorSettings.mReplyToRequests();
|
||||
});
|
||||
|
||||
|
||||
test('openUrl()', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.openUrl('http://example.com');
|
||||
assert.equal(MozActivity.calls.length, 1);
|
||||
assert.equal(MozActivity.calls[0].name, 'view');
|
||||
assert.equal(MozActivity.calls[0].data.type, 'url');
|
||||
assert.equal(MozActivity.calls[0].data.url, 'http://example.com');
|
||||
assert.ok(!MozActivity.calls[0].data.isPrivate);
|
||||
});
|
||||
|
||||
test('openUrl() - private browser', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
md1.openUrl('http://example.com', true);
|
||||
assert.equal(MozActivity.calls.length, 1);
|
||||
assert.equal(MozActivity.calls[0].name, 'view');
|
||||
assert.equal(MozActivity.calls[0].data.type, 'url');
|
||||
assert.equal(MozActivity.calls[0].data.isPrivate, true);
|
||||
assert.equal(MozActivity.calls[0].data.url, 'http://example.com');
|
||||
});
|
||||
|
||||
test('focus context menu', function() {
|
||||
var app1 = new AppWindow(fakeAppConfig1);
|
||||
var md1 = BaseModule.instantiate('BrowserContextMenu', app1);
|
||||
md1.start();
|
||||
|
||||
var focusStub = this.sinon.stub(md1.contextMenuView, 'focus');
|
||||
|
||||
md1.focus();
|
||||
|
||||
assert.isTrue(focusStub.called);
|
||||
|
||||
});
|
||||
});
|
||||
99
gaia/apps/system/test/unit/browser_frame_test.js
Executable file
99
gaia/apps/system/test/unit/browser_frame_test.js
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
/* globals BrowserFrame */
|
||||
|
||||
'use strict';
|
||||
|
||||
/* Unit test of browser_frame.js */
|
||||
requireApp('system/js/browser_frame.js');
|
||||
|
||||
suite('browser class > ', function() {
|
||||
test('Simple browser frame instance creation..', function() {
|
||||
var browserFrame = new BrowserFrame({ url: 'unit-test.gaia' });
|
||||
assert.equal(browserFrame.element.getAttribute('mozbrowser'), 'true');
|
||||
});
|
||||
|
||||
suite('mozapptype', function() {
|
||||
test('mozapptype: clock', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'clock.gaiamobile.org'
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozapptype'), 'critical');
|
||||
});
|
||||
|
||||
test('mozapptype: callscreen', function() {
|
||||
var port = '';
|
||||
if (window.location.port !== '') {
|
||||
port = ':' + window.location.port;
|
||||
}
|
||||
var b = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'callscreen.gaiamobile.org'
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozapptype'), 'critical');
|
||||
});
|
||||
|
||||
test('mozapptype: inputmethod', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'keyboard.gaiamobile.org',
|
||||
isInputMethod: true
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozapptype'), 'inputmethod');
|
||||
});
|
||||
|
||||
test('mozapptype: other app', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'other.gaiamobile.org'
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozapptype'), null);
|
||||
});
|
||||
});
|
||||
|
||||
test('set parent app manifestURL', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: 'fake',
|
||||
parentApp: 'fake.parent.app/manifest.webapp'
|
||||
});
|
||||
|
||||
assert.equal(b.element.getAttribute('parentapp'),
|
||||
'fake.parent.app/manifest.webapp');
|
||||
});
|
||||
|
||||
test('expect system message', function() {
|
||||
var b = new BrowserFrame({
|
||||
isSystemMessage: true,
|
||||
url: window.location.protocol + '//' + 'other.gaiamobile.org',
|
||||
manifestURL: window.location.protocol +
|
||||
'//' + 'other.gaiamobile.org/manifest.webapp'
|
||||
});
|
||||
assert.equal(b.element.getAttribute('expecting-system-message'),
|
||||
'expecting-system-message');
|
||||
|
||||
var b2 = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'other.gaiamobile.org',
|
||||
manifestURL: window.location.protocol +
|
||||
'//' + 'other.gaiamobile.org/manifest.webapp'
|
||||
});
|
||||
assert.isNull(b2.element.getAttribute('expecting-system-message'));
|
||||
|
||||
var b3 = new BrowserFrame({
|
||||
isSystemMessage: true,
|
||||
url: window.location.protocol + '//' + 'other.gaiamobile.org'
|
||||
});
|
||||
assert.isNull(b3.element.getAttribute('expecting-system-message'));
|
||||
});
|
||||
|
||||
test('inputmethod app attributes', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: window.location.protocol + '//' + 'keyboard.gaiamobile.org',
|
||||
isInputMethod: true
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozpasspointerevents'), 'true');
|
||||
assert.equal(b.element.getAttribute('ignoreuserfocus'), 'true');
|
||||
});
|
||||
|
||||
test('private browsing attribute', function() {
|
||||
var b = new BrowserFrame({
|
||||
url: 'http://mozilla.org',
|
||||
isPrivate: true
|
||||
});
|
||||
assert.equal(b.element.getAttribute('mozprivatebrowsing'), 'true');
|
||||
});
|
||||
});
|
||||
413
gaia/apps/system/test/unit/browser_key_event_manager_test.js
Executable file
413
gaia/apps/system/test/unit/browser_key_event_manager_test.js
Executable file
|
|
@ -0,0 +1,413 @@
|
|||
'use strict';
|
||||
|
||||
/* global BrowserKeyEventManager */
|
||||
|
||||
requireApp('system/js/browser_key_event_manager.js');
|
||||
|
||||
suite('system/BrowserKeyEventManager', function() {
|
||||
var browserKeyEventManager;
|
||||
|
||||
var createHardwareKeyEvent = function (type, key, embeddedCancelled) {
|
||||
return {
|
||||
type: type,
|
||||
key: key,
|
||||
location: 0,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
altKey: false,
|
||||
metaKey: false,
|
||||
repeat: false,
|
||||
embeddedCancelled: embeddedCancelled,
|
||||
preventDefault: function() {},
|
||||
getModifierState: function() {}
|
||||
};
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
browserKeyEventManager = new BrowserKeyEventManager();
|
||||
});
|
||||
suiteTeardown(function() {
|
||||
browserKeyEventManager = undefined;
|
||||
});
|
||||
|
||||
test('tranlate (mozbrowserbeforekeydown, Power) into sleep-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'sleep-button-press');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('translate (keydown, Power) into sleep-button-press', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keydown', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'sleep-button-press');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeydown, Power)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserbeforekeyup, Power) into sleep-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeyup', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'sleep-button-release');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('translate (keyup, Power) into sleep-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keyup', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'sleep-button-release');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeyup, Power)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'Power', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('tranlate (mozbrowserbeforekeydown, Home) into home-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'home-button-press');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('translate (keydown, Home) into home-button-press', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keydown', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'home-button-press');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeydown, Home)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserbeforekeyup, Home) into home-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeyup', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'home-button-release');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('translate (keyup, Home) into home-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keyup', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'home-button-release');
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeyup, Home)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'Home', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeydown, VolumeUp)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (keydown, VolumeUp) into volume-up-button-press', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keydown', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-up-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserafterkeydown, VolumeUp) into ' +
|
||||
'volume-up-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-up-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for embeddedCancelled ' +
|
||||
'(mozbrowserafterkeydown, VolumeUp)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'VolumeUp', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeyup, VolumeUp)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeyup', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (keyup, VolumeUp) into volume-up-button-release', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keyup', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-up-button-release');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserafterkeyup, VolumeUp) into ' +
|
||||
'volume-up-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'VolumeUp', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-up-button-release');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for embeddedCancelled ' +
|
||||
'(mozbrowserafterkeyup, VolumeUp)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'VolumeUp', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeydown, VolumeDown)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('defaultPrevented called for VolumeDown in key combinations',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt, true);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isTrue(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (keydown, VolumeDown) into volume-down-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keydown', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-down-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserafterkeydown, VolumeDown) into ' +
|
||||
'volume-down-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(createHardwareKeyEvent(
|
||||
'mozbrowserafterkeydown', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-down-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for embeddedCancelled ' +
|
||||
'(mozbrowserafterkeydown, VolumeDown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'VolumeDown', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('ignore embeddedCancelled for VolumeDown in key combination',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'VolumeDown', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt, true);
|
||||
assert.equal(actualTranslatedType, 'volume-down-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeyup, VolumeDown)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeyup', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (keyup, VolumeDown) into volume-down-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keyup', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-down-button-release');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserafterkeyup, VolumeDown) into ' +
|
||||
'volume-down-button-release',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'VolumeDown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'volume-down-button-release');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for embeddedCancelled ' +
|
||||
'(mozbrowserafterkeyup, VolumeDown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'VolumeDown', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeydown, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeydown', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (keydown, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keydown', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeydown, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserbeforekeyup, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserbeforekeyup', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.calledOnce);
|
||||
});
|
||||
|
||||
test('no translation for (keyup, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('keyup', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for (mozbrowserafterkeyup, Unknown)', function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeyup', 'Unknown', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('translate (mozbrowserafterkeydown, Camera) into camera-button-press',
|
||||
function() {
|
||||
var evt = this.sinon.stub(createHardwareKeyEvent(
|
||||
'mozbrowserafterkeydown', 'Camera', false));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType =
|
||||
browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.equal(actualTranslatedType, 'camera-button-press');
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
|
||||
test('no translation for embeddedCancelled (mozbrowserafterkeydown, Camera)',
|
||||
function() {
|
||||
var evt = this.sinon.stub(
|
||||
createHardwareKeyEvent('mozbrowserafterkeydown', 'Camera', true));
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
var actualTranslatedType = browserKeyEventManager.getButtonEventType(evt);
|
||||
assert.isUndefined(actualTranslatedType);
|
||||
assert.isFalse(evt.preventDefault.called);
|
||||
});
|
||||
});
|
||||
97
gaia/apps/system/test/unit/browser_mixin_test.js
Executable file
97
gaia/apps/system/test/unit/browser_mixin_test.js
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
'use strict';
|
||||
/* global MockAppWindow */
|
||||
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
|
||||
suite('BrowserMixin', function() {
|
||||
var subject, realAppWindow;
|
||||
|
||||
function extend(mixin) {
|
||||
for (var prop in mixin) {
|
||||
if (mixin.hasOwnProperty(prop)) {
|
||||
MockAppWindow.prototype[prop] = mixin[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup(function(done) {
|
||||
realAppWindow = window.AppWindow;
|
||||
window.AppWindow = MockAppWindow;
|
||||
this.sinon.stub(MockAppWindow, 'addMixin', extend);
|
||||
requireApp('system/js/browser_mixin.js', function() {
|
||||
subject = new MockAppWindow();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.AppWindow = realAppWindow;
|
||||
});
|
||||
|
||||
suite('on import >', function() {
|
||||
test('adds the mixin to the app window', function() {
|
||||
assert.isTrue(MockAppWindow.addMixin.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('focus >', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(subject, 'getTopMostWindow');
|
||||
});
|
||||
|
||||
test('uses the topMostWindow', function() {
|
||||
subject.focus();
|
||||
assert.isTrue(subject.getTopMostWindow.called);
|
||||
});
|
||||
|
||||
test('focus the context menu if shown', function() {
|
||||
subject.contextmenu = {
|
||||
isShown: this.sinon.stub().returns(true),
|
||||
focus: this.sinon.stub()
|
||||
};
|
||||
subject.focus();
|
||||
assert.isTrue(subject.contextmenu.focus.called);
|
||||
});
|
||||
|
||||
test('focus the browser element if no contextmenu', function() {
|
||||
this.sinon.spy(subject.browser.element, 'focus');
|
||||
subject.focus();
|
||||
assert.isTrue(subject.browser.element.focus.called);
|
||||
});
|
||||
|
||||
test('does not focus the browser element if activeElement', function() {
|
||||
var element = subject.browser.element;
|
||||
this.sinon.stub(subject, 'getActiveElement').returns(element);
|
||||
this.sinon.spy(element, 'focus');
|
||||
subject.focus();
|
||||
assert.isFalse(element.focus.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('blur >', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(subject, 'getTopMostWindow');
|
||||
});
|
||||
|
||||
test('uses the topMostWindow', function() {
|
||||
subject.blur();
|
||||
assert.isTrue(subject.getTopMostWindow.called);
|
||||
});
|
||||
|
||||
test('blur the browser element if activeElement', function() {
|
||||
var element = subject.browser.element;
|
||||
this.sinon.stub(subject, 'getActiveElement').returns(element);
|
||||
this.sinon.spy(element, 'blur');
|
||||
subject.blur();
|
||||
assert.isTrue(element.blur.called);
|
||||
});
|
||||
|
||||
test('does not blur the browser element if !activeElement', function() {
|
||||
var element = subject.browser.element;
|
||||
this.sinon.stub(subject, 'getActiveElement').returns({});
|
||||
this.sinon.spy(element, 'blur');
|
||||
subject.blur();
|
||||
assert.isFalse(element.blur.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
91
gaia/apps/system/test/unit/browser_settings_test.js
Executable file
91
gaia/apps/system/test/unit/browser_settings_test.js
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
'use strict';
|
||||
/* global BrowserSettings, MockNavigatormozApps, MockNavigatorSettings,
|
||||
MockService, MocksHelper, MockLazyLoader, IconsHelper */
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_apps.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_icons_helper.js');
|
||||
|
||||
|
||||
var mocksForBrowserSettings = new MocksHelper([
|
||||
'Service',
|
||||
'LazyLoader',
|
||||
'IconsHelper'
|
||||
]).init();
|
||||
|
||||
suite('system/BrowserSettings', function() {
|
||||
mocksForBrowserSettings.attachTestHelpers();
|
||||
var realNavigatorSettings;
|
||||
var realNavigatormozApps;
|
||||
var browserSettings;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realNavigatormozApps = navigator.mozApps;
|
||||
navigator.mozApps = MockNavigatormozApps;
|
||||
|
||||
realNavigatorSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
requireApp('system/js/browser_settings.js', function() {
|
||||
browserSettings = new BrowserSettings();
|
||||
browserSettings.start();
|
||||
done();
|
||||
});
|
||||
|
||||
MockLazyLoader.mLoadRightAway = true;
|
||||
sinon.spy(MockLazyLoader, 'load');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozApps = realNavigatormozApps;
|
||||
realNavigatormozApps = null;
|
||||
|
||||
navigator.mozSettings = realNavigatorSettings;
|
||||
realNavigatorSettings = null;
|
||||
});
|
||||
|
||||
suite('check for settings-based procedure handlers', function() {
|
||||
test('setting clear.browser.history should clear places database',
|
||||
function() {
|
||||
this.sinon.spy(MockService, 'request');
|
||||
navigator.mozSettings.createLock().set({'clear.browser.history': true});
|
||||
assert.isTrue(MockService.request.calledWith('Places:clearHistory'),
|
||||
'Places database clear should be requested');
|
||||
}
|
||||
);
|
||||
|
||||
test('setting clear.browser.private-data should call clearBrowserData',
|
||||
function() {
|
||||
navigator.mozSettings.createLock().set({
|
||||
'clear.browser.private-data': true
|
||||
});
|
||||
|
||||
var called = false;
|
||||
// Resolve DOMRequest to a fake app object
|
||||
MockNavigatormozApps.mLastRequest.result = {
|
||||
clearBrowserData: function() {
|
||||
called = true;
|
||||
}
|
||||
};
|
||||
MockNavigatormozApps.mLastRequest.onsuccess();
|
||||
|
||||
assert.isTrue(called,
|
||||
'Browser data clear should be requested');
|
||||
}
|
||||
);
|
||||
|
||||
test('setting clear.browser.private-data should clear icons dataStore',
|
||||
function() {
|
||||
var iconsHelperStub = this.sinon.stub(IconsHelper, 'clear');
|
||||
navigator.mozSettings.createLock().set({
|
||||
'clear.browser.private-data': true
|
||||
});
|
||||
|
||||
assert.isTrue(iconsHelperStub.called,
|
||||
'IconsHelper.clear() should be called');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
119
gaia/apps/system/test/unit/browser_test.js
Executable file
119
gaia/apps/system/test/unit/browser_test.js
Executable file
|
|
@ -0,0 +1,119 @@
|
|||
/*global MocksHelper, MockNavigatormozSetMessageHandler, Browser,
|
||||
MockApplications, MockAppWindow, MockAppWindowHelper,
|
||||
ActivityHandler, MockNavigatorSettings, setImmediate */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/js/browser_config_helper.js');
|
||||
require('/shared/js/url_helper.js');
|
||||
require('/shared/js/settings_listener.js');
|
||||
require('/js/import.js');
|
||||
require('/js/activity_handler.js');
|
||||
require('/js/browser.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_set_message_handler.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
require('/test/unit/mock_app_window.js');
|
||||
require('/test/unit/mock_applications.js');
|
||||
|
||||
var mocksForBrowser = new MocksHelper([
|
||||
'AppWindow', 'Applications', 'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/Browser', function() {
|
||||
mocksForBrowser.attachTestHelpers();
|
||||
|
||||
var realMozSettings;
|
||||
var realMozSetMessageHandler;
|
||||
var subject;
|
||||
var clock;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
realMozSetMessageHandler = navigator.mozSetMessageHandler;
|
||||
navigator.mozSetMessageHandler = MockNavigatormozSetMessageHandler;
|
||||
MockNavigatormozSetMessageHandler.mSetup();
|
||||
window.applications = MockApplications;
|
||||
var handler = new ActivityHandler();
|
||||
handler.start();
|
||||
subject = new Browser();
|
||||
subject.start();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSetMessageHandler = realMozSetMessageHandler;
|
||||
MockNavigatormozSetMessageHandler.mTeardown();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockNavigatorSettings.mSetup();
|
||||
this.sinon.spy(MockAppWindow.prototype, 'requestOpen');
|
||||
clock = this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockNavigatorSettings.mTeardown();
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('should open a new app window with the correct config', function() {
|
||||
MockNavigatormozSetMessageHandler.mTrigger('activity', {
|
||||
source: {
|
||||
name: 'view',
|
||||
data: {
|
||||
name: 'view',
|
||||
type: 'url',
|
||||
url: 'http://arandomurl.com'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(MockAppWindowHelper.mInstances.length, 1);
|
||||
var app = MockAppWindowHelper.mLatest;
|
||||
assert.equal(app.oop, true);
|
||||
assert.equal(app.url, 'http://arandomurl.com/');
|
||||
assert.equal(app.origin, 'http://arandomurl.com/');
|
||||
});
|
||||
|
||||
test('when private browsing is requested', function() {
|
||||
MockNavigatormozSetMessageHandler.mTrigger('activity', {
|
||||
source: {
|
||||
name: 'view',
|
||||
data: {
|
||||
name: 'view',
|
||||
type: 'url',
|
||||
url: 'http://arandomurl.com',
|
||||
isPrivate: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(MockAppWindowHelper.mInstances.length, 1);
|
||||
var app = MockAppWindowHelper.mLatest;
|
||||
assert.equal(app.isPrivate, true);
|
||||
});
|
||||
|
||||
test('when private browsing is the default setting', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('browser.private.default',
|
||||
{settingValue: true});
|
||||
|
||||
setImmediate(function () {
|
||||
MockNavigatormozSetMessageHandler.mTrigger('activity', {
|
||||
source: {
|
||||
name: 'view',
|
||||
data: {
|
||||
name: 'view',
|
||||
type: 'url',
|
||||
url: 'http://arandomurl.com'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(MockAppWindowHelper.mInstances.length, 1);
|
||||
var app = MockAppWindowHelper.mLatest;
|
||||
assert.equal(app.isPrivate, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
89
gaia/apps/system/test/unit/call_forwarding_icon_test.js
Executable file
89
gaia/apps/system/test/unit/call_forwarding_icon_test.js
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
/* global CallForwardingsIcon, MocksHelper, MockCallForwarding, Service,
|
||||
MockSIMSlot, MockNavigatorMozMobileConnection, MockSIMSlotManager */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/call_forwarding_icon.js');
|
||||
requireApp('system/test/unit/mock_call_forwarding.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_simslot.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_simslot_manager.js');
|
||||
requireApp(
|
||||
'system/shared/test/unit/mocks/mock_navigator_moz_mobile_connection.js');
|
||||
|
||||
var mocksForCallForwardingsIcon = new MocksHelper([
|
||||
'SIMSlotManager',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/CallForwardingsIcon', function() {
|
||||
var subject;
|
||||
|
||||
mocksForCallForwardingsIcon.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(document, 'getElementById').returns(
|
||||
document.createElement('div'));
|
||||
this.sinon.stub(Service, 'request', function() {
|
||||
var container = document.createElement('div');
|
||||
return {
|
||||
then: function(callback) {
|
||||
callback(container);
|
||||
}
|
||||
};
|
||||
});
|
||||
MockSIMSlotManager.mInstances = [
|
||||
new MockSIMSlot(MockNavigatorMozMobileConnection, 0),
|
||||
new MockSIMSlot(MockNavigatorMozMobileConnection, 1)
|
||||
];
|
||||
subject = new CallForwardingsIcon(MockCallForwarding);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
subject.onrender();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Enable call forwarding on 1st SIM slot', function() {
|
||||
this.sinon.stub(MockCallForwarding, 'enabled', function(index) {
|
||||
return index === 0 ? true : false;
|
||||
});
|
||||
subject.update();
|
||||
assert.isTrue(subject.icons[0].isVisible());
|
||||
assert.isFalse(subject.icons[1].isVisible());
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Enable call forwarding on 2nd SIM slot', function() {
|
||||
this.sinon.stub(MockCallForwarding, 'enabled', function(index) {
|
||||
return index === 0 ? false : true;
|
||||
});
|
||||
subject.update();
|
||||
assert.isFalse(subject.icons[0].isVisible());
|
||||
assert.isTrue(subject.icons[1].isVisible());
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Enable call forwarding on both SIM slots', function() {
|
||||
this.sinon.stub(MockCallForwarding, 'enabled', function() {
|
||||
return true;
|
||||
});
|
||||
subject.update();
|
||||
assert.isTrue(subject.icons[0].isVisible());
|
||||
assert.isTrue(subject.icons[1].isVisible());
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Disable call forwarding on both SIM slots', function() {
|
||||
this.sinon.stub(MockCallForwarding, 'enabled', function() {
|
||||
return false;
|
||||
});
|
||||
subject.update();
|
||||
assert.isFalse(subject.icons[0].isVisible());
|
||||
assert.isFalse(subject.icons[1].isVisible());
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
389
gaia/apps/system/test/unit/call_forwarding_test.js
Executable file
389
gaia/apps/system/test/unit/call_forwarding_test.js
Executable file
|
|
@ -0,0 +1,389 @@
|
|||
/* global MockNavigatorSettings, CallForwardingsIcon, MocksHelper,
|
||||
MockSIMSlotManager, MockSettingsHelper, MockasyncStorage,
|
||||
MockMobileconnection, MockSIMSlot, BaseModule, MockLazyLoader */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_simslot.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_simslot_manager.js');
|
||||
requireApp('system/test/unit/mock_asyncStorage.js');
|
||||
requireApp(
|
||||
'system/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_helper.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/call_forwarding_icon.js');
|
||||
requireApp('system/js/base_icon_collection.js');
|
||||
requireApp('system/js/call_forwarding.js');
|
||||
|
||||
var mocksForCallForwarding = new MocksHelper([
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/callForwarding >', function() {
|
||||
var realSIMSlotManager;
|
||||
var realMozSettings;
|
||||
var realSettingsHelper;
|
||||
var realAsyncStorage;
|
||||
mocksForCallForwarding.attachTestHelpers();
|
||||
|
||||
// Must be in sync with nsIDOMMozMobileCFInfo interface.
|
||||
var cfReason = {
|
||||
CALL_FORWARD_REASON_UNCONDITIONAL: 0,
|
||||
CALL_FORWARD_REASON_MOBILE_BUSY: 1,
|
||||
CALL_FORWARD_REASON_NO_REPLY: 2,
|
||||
CALL_FORWARD_REASON_NOT_REACHABLE: 3,
|
||||
CALL_FORWARD_REASON_ALL_CALL_FORWARDING: 4,
|
||||
CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING: 5
|
||||
};
|
||||
|
||||
var cfAction = {
|
||||
CALL_FORWARD_ACTION_DISABLE: 0,
|
||||
CALL_FORWARD_ACTION_ENABLE: 1,
|
||||
CALL_FORWARD_ACTION_QUERY_STATUS: 2,
|
||||
CALL_FORWARD_ACTION_REGISTRATION: 3,
|
||||
CALL_FORWARD_ACTION_ERASURE: 4
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = window.navigator.mozSettings;
|
||||
window.navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
realSIMSlotManager = window.SIMSlotManager;
|
||||
window.SIMSlotManager = MockSIMSlotManager;
|
||||
|
||||
realSettingsHelper = window.SettingsHelper;
|
||||
window.SettingsHelper = MockSettingsHelper;
|
||||
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.navigator.mozSettings = realMozSettings;
|
||||
window.SIMSlotManager = realSIMSlotManager;
|
||||
window.SettingsHelper = realSettingsHelper;
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockLazyLoader.mLoadRightAway = true;
|
||||
this.sinon.spy(MockLazyLoader, 'load');
|
||||
this.mockMobileConnection = MockMobileconnection();
|
||||
this.slots = [new MockSIMSlot(this.mockMobileConnection, 0)];
|
||||
this.iccid = 'iccid1';
|
||||
this.slots[0].simCard = {
|
||||
cardState: 'ready',
|
||||
iccInfo: {
|
||||
iccid: this.iccid
|
||||
}
|
||||
};
|
||||
MockSIMSlotManager.mInstances = this.slots;
|
||||
|
||||
this.callForwarding = BaseModule.instantiate('CallForwarding');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockSettingsHelper.mTeardown();
|
||||
MockNavigatorSettings.mTeardown();
|
||||
MockasyncStorage.mTeardown();
|
||||
});
|
||||
|
||||
suite('settings changed', function() {
|
||||
var settingsCore;
|
||||
setup(function() {
|
||||
settingsCore = BaseModule.instantiate('SettingsCore');
|
||||
settingsCore.start();
|
||||
this.callForwarding.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.callForwarding.stop();
|
||||
settingsCore.stop();
|
||||
});
|
||||
|
||||
test('Should lazy load icon', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('ril.cf.enabled',
|
||||
{ settingValue: [true] });
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(
|
||||
['js/call_forwarding_icon.js']));
|
||||
});
|
||||
|
||||
test('Should update icon', function() {
|
||||
this.callForwarding.icon = new CallForwardingsIcon(this.callForwarding);
|
||||
this.sinon.stub(this.callForwarding.icon, 'update');
|
||||
MockNavigatorSettings.mTriggerObservers('ril.cf.enabled',
|
||||
{ settingValue: [false] });
|
||||
assert.isTrue(this.callForwarding.icon.update.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('start()', function() {
|
||||
test('_slots should be the same as what SIMSlotManager returns',
|
||||
function() {
|
||||
this.callForwarding.start();
|
||||
for (var i = 0; i < this.slots.length; i++) {
|
||||
assert.equal(this.callForwarding._slots[i], this.slots[i]);
|
||||
}
|
||||
});
|
||||
|
||||
test('should add event handlers', function() {
|
||||
sinon.stub(this.callForwarding, '_addEventHandlers');
|
||||
this.callForwarding.start();
|
||||
sinon.assert.called(this.callForwarding._addEventHandlers);
|
||||
});
|
||||
|
||||
test('should call to _initCallForwardingState', function() {
|
||||
sinon.stub(this.callForwarding, '_initCallForwardingState');
|
||||
this.callForwarding.start();
|
||||
sinon.assert.calledWith(this.callForwarding._initCallForwardingState,
|
||||
this.slots[0]);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_addEventHandlers()', function() {
|
||||
['simslot-cardstatechange',
|
||||
'simslot-iccinfochange'].forEach(function(eventName) {
|
||||
test('should call to _initCallForwardingState when receiving ' +
|
||||
eventName, function(done) {
|
||||
sinon.stub(this.callForwarding, '_initCallForwardingState');
|
||||
this.callForwarding.start();
|
||||
|
||||
var eventObj = new CustomEvent(eventName, { detail: this.slots[0] });
|
||||
window.dispatchEvent(eventObj);
|
||||
setTimeout((function() {
|
||||
sinon.assert.calledWith(
|
||||
this.callForwarding._initCallForwardingState,
|
||||
this.slots[0]);
|
||||
done();
|
||||
}).bind(this));
|
||||
});
|
||||
});
|
||||
|
||||
test('should call to _onCallForwardingStateChanged when ' +
|
||||
'ril.cf.carrier.enabled changed', function() {
|
||||
sinon.stub(this.callForwarding, '_onCallForwardingStateChanged');
|
||||
this.callForwarding.start();
|
||||
|
||||
var value = { settingValue: { index: 0, enabled: true }};
|
||||
MockNavigatorSettings
|
||||
.mTriggerObservers('ril.cf.carrier.enabled', value);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
this.callForwarding._onCallForwardingStateChanged,
|
||||
value.settingValue.index, value.settingValue.enabled);
|
||||
});
|
||||
|
||||
test('should call to _updateCallForwardingIconState when receiving ' +
|
||||
'cfstatechange', function() {
|
||||
sinon.stub(this.callForwarding, '_updateCallForwardingIconState');
|
||||
this.callForwarding.start();
|
||||
|
||||
var event = {};
|
||||
this.slots[0].conn.triggerEventListeners('cfstatechange', event);
|
||||
|
||||
sinon.assert.called(
|
||||
this.callForwarding._updateCallForwardingIconState,
|
||||
this.slots[0], event);
|
||||
});
|
||||
|
||||
suite('_initCallForwardingState()', function() {
|
||||
setup(function() {
|
||||
this.callForwarding.start();
|
||||
this.sinon.spy(window.asyncStorage, 'getItem');
|
||||
|
||||
// _callForwardingIconInitializedStates will be true after calling
|
||||
// callForwarding.start(), set to false so we can test different cases.
|
||||
this.callForwarding._callForwardingIconInitializedStates[0] = false;
|
||||
|
||||
// MockSettingsHelper.instances['ril.cf.enabled'].value[0] is false
|
||||
// by default, set to true and see if it changes to correct value.
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0] = true;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
// Move back 'ril.cf.enabled' default settings value
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0] = false;
|
||||
});
|
||||
|
||||
test('should early return if the slot has been initialized', function() {
|
||||
this.callForwarding._callForwardingIconInitializedStates[0] = true;
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
sinon.assert.notCalled(window.asyncStorage.getItem);
|
||||
});
|
||||
|
||||
test('should early return and set call forwarding to false ' +
|
||||
'if the sim card is not available', function(done) {
|
||||
this.slots[0].simCard = null;
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
sinon.assert.notCalled(window.asyncStorage.getItem);
|
||||
setTimeout(function() {
|
||||
assert.isFalse(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should early return and set call forwarding to false ' +
|
||||
'if the card state is not ready', function(done) {
|
||||
this.slots[0].simCard.cardState = 'unknown';
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
sinon.assert.notCalled(window.asyncStorage.getItem);
|
||||
setTimeout(function() {
|
||||
assert.isFalse(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should early return and set call forwarding to false ' +
|
||||
'if the iccid is not available', function(done) {
|
||||
this.slots[0].simCard.iccInfo = {
|
||||
iccid: null
|
||||
};
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
sinon.assert.notCalled(window.asyncStorage.getItem);
|
||||
setTimeout(function() {
|
||||
assert.isFalse(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('when with valid iccid', function() {
|
||||
test('should mark the slot as initialized', function() {
|
||||
this.callForwarding.start();
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
assert.ok(
|
||||
this.callForwarding._callForwardingIconInitializedStates[0]);
|
||||
});
|
||||
|
||||
test('should set the icon state to false when no cached information',
|
||||
function(done) {
|
||||
this.callForwarding.start();
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
setTimeout(function() {
|
||||
assert.isFalse(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should initialize the icon state with cached information',
|
||||
function(done) {
|
||||
MockasyncStorage.mItems['ril.cf.enabled.' + this.iccid] = true;
|
||||
this.callForwarding.start();
|
||||
this.callForwarding._initCallForwardingState(this.slots[0]);
|
||||
setTimeout(function() {
|
||||
assert.isTrue(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[cfReason.CALL_FORWARD_REASON_UNCONDITIONAL,
|
||||
cfReason.CALL_FORWARD_REASON_ALL_CALL_FORWARDING].forEach(
|
||||
function(reason) {
|
||||
suite('_updateCallForwardingIconState()', function() {
|
||||
setup(function() {
|
||||
this.event = {
|
||||
reason: reason,
|
||||
action: cfAction.CALL_FORWARD_ACTION_ENABLE
|
||||
};
|
||||
|
||||
this.callForwarding.start();
|
||||
this.callForwarding.icon =
|
||||
new CallForwardingsIcon(this.callForwarding);
|
||||
});
|
||||
|
||||
test('should early return if the event is not available', function() {
|
||||
sinon.spy(this.callForwarding._callForwardingHelper, 'get');
|
||||
this.callForwarding._updateCallForwardingIconState(this.slots[0]);
|
||||
sinon.assert.notCalled(
|
||||
this.callForwarding._callForwardingHelper.get);
|
||||
});
|
||||
|
||||
test('should early return if it is not unconditional call forwarding',
|
||||
function() {
|
||||
this.event.reason = 'otherReason';
|
||||
sinon.spy(this.callForwarding._callForwardingHelper, 'get');
|
||||
this.callForwarding._updateCallForwardingIconState(this.slots[0],
|
||||
this.event);
|
||||
sinon.assert.notCalled(
|
||||
this.callForwarding._callForwardingHelper.get);
|
||||
});
|
||||
|
||||
test('should set the icon state to false when erase the setting ' +
|
||||
'successfully', function(done) {
|
||||
this.event.action = cfAction.CALL_FORWARD_ACTION_ERASURE;
|
||||
this.callForwarding._updateCallForwardingIconState(this.slots[0],
|
||||
this.event);
|
||||
setTimeout(function() {
|
||||
assert.isFalse(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('should set the icon state to true when with correct call ' +
|
||||
'forwarding settings', function() {
|
||||
test('CALL_FORWARD_ACTION_REGISTRATION', function(done) {
|
||||
this.event.action = cfAction.CALL_FORWARD_ACTION_REGISTRATION;
|
||||
this.callForwarding._updateCallForwardingIconState(
|
||||
this.slots[0], this.event);
|
||||
setTimeout(function() {
|
||||
assert.isTrue(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('CALL_FORWARD_ACTION_ENABLE', function(done) {
|
||||
this.event.action = cfAction.CALL_FORWARD_ACTION_ENABLE;
|
||||
this.callForwarding._updateCallForwardingIconState(
|
||||
this.slots[0], this.event);
|
||||
setTimeout(function() {
|
||||
assert.isTrue(
|
||||
MockSettingsHelper.instances['ril.cf.enabled'].value[0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('should cache the call forwarding information', function() {
|
||||
test('when success', function() {
|
||||
this.callForwarding._updateCallForwardingIconState(this.slots[0],
|
||||
this.event);
|
||||
assert.isTrue(
|
||||
MockasyncStorage.mItems['ril.cf.enabled.' + this.iccid]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('_onCallForwardingStateChanged()', function() {
|
||||
setup(function() {
|
||||
this.callForwarding.start();
|
||||
});
|
||||
|
||||
test('should set icon state correctly', function(done) {
|
||||
var enabled = true;
|
||||
this.callForwarding._onCallForwardingStateChanged(0, enabled);
|
||||
setTimeout(function() {
|
||||
assert.ok(MockSettingsHelper.instances['ril.cf.enabled'].value[0] ===
|
||||
enabled);
|
||||
done();
|
||||
});
|
||||
assert.ok(MockasyncStorage.mItems['ril.cf.enabled.' + this.iccid] ===
|
||||
enabled);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
209
gaia/apps/system/test/unit/callscreen_window_test.js
Executable file
209
gaia/apps/system/test/unit/callscreen_window_test.js
Executable file
|
|
@ -0,0 +1,209 @@
|
|||
/* globals CallscreenWindow, MocksHelper, MockApplications, MockLayoutManager,
|
||||
Service, MockL10n */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_orientation_manager.js');
|
||||
requireApp('system/test/unit/mock_layout_manager.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_manifest_helper.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/test/unit/mock_screen_layout.js');
|
||||
requireApp('system/test/unit/mock_app_chrome.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForCallscreenWindow = new MocksHelper([
|
||||
'OrientationManager', 'Applications', 'SettingsListener',
|
||||
'ManifestHelper', 'LayoutManager', 'ScreenLayout', 'Service',
|
||||
'AppChrome'
|
||||
]).init();
|
||||
|
||||
suite('system/CallscreenWindow', function() {
|
||||
mocksForCallscreenWindow.attachTestHelpers();
|
||||
var stubById;
|
||||
var realApplications;
|
||||
var realLayoutManager;
|
||||
var realL10n;
|
||||
var CSORIGIN = window.location.origin.replace('system', 'callscreen') + '/';
|
||||
var fakeAppConfig = {
|
||||
iframe: document.createElement('iframe'),
|
||||
frame: document.createElement('div'),
|
||||
origin: 'http://fake',
|
||||
url: 'http://fakeurl/index.html',
|
||||
manifestURL: 'app://fakeatt.gaiamobile.org/manifest.webapp',
|
||||
name: 'fake',
|
||||
manifest: {
|
||||
orientation: 'default',
|
||||
icons: {
|
||||
'128': 'fake.icon'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fakeAppConfig.browser = { element: fakeAppConfig.iframe };
|
||||
|
||||
setup(function(done) {
|
||||
MockApplications.mRegisterMockApp(fakeAppConfig);
|
||||
realApplications = window.applications;
|
||||
window.applications = MockApplications;
|
||||
realLayoutManager = window.layoutManager;
|
||||
window.layoutManager = new MockLayoutManager();
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
this.sinon.useFakeTimers();
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
this.sinon.stub(HTMLElement.prototype, 'querySelector',
|
||||
function() {
|
||||
return document.createElement('div');
|
||||
});
|
||||
requireApp('system/js/browser_config_helper.js');
|
||||
requireApp('system/js/browser_frame.js');
|
||||
requireApp('system/js/app_window.js');
|
||||
requireApp('system/js/browser_mixin.js');
|
||||
requireApp('system/js/attention_window.js');
|
||||
requireApp('system/js/callscreen_window.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
window.applications = realApplications;
|
||||
window.layoutManager = realLayoutManager;
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
test('Should be an attention window', function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
assert.isTrue(callscreen.isAttentionWindow);
|
||||
});
|
||||
|
||||
test('Hide right away if we are not active while window.close()', function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
this.sinon.stub(callscreen, 'isActive').returns(false);
|
||||
callscreen.element.dispatchEvent(new CustomEvent('mozbrowserclose'));
|
||||
|
||||
assert.isTrue(callscreen.isHidden());
|
||||
});
|
||||
|
||||
test('Close while window.close() then hide', function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
this.sinon.spy(callscreen, 'requestClose');
|
||||
var stubPublish = this.sinon.stub(callscreen, 'publish');
|
||||
this.sinon.stub(callscreen, 'isActive').returns(true);
|
||||
var stubBlur = this.sinon.stub(callscreen.browser.element, 'blur');
|
||||
var stubReloadWindow = this.sinon.stub(callscreen, 'reloadWindow');
|
||||
callscreen.element.dispatchEvent(new CustomEvent('mozbrowserclose'));
|
||||
sinon.assert.calledOnce(callscreen.requestClose);
|
||||
assert.isTrue(stubPublish.calledWith('terminated'));
|
||||
assert.isFalse(stubReloadWindow.called);
|
||||
callscreen.element.dispatchEvent(new CustomEvent('_closed'));
|
||||
assert.isTrue(callscreen.isHidden());
|
||||
assert.isTrue(stubReloadWindow.called);
|
||||
if (document.activeElement === callscreen.browser.element) {
|
||||
assert.isTrue(stubBlur.called);
|
||||
}
|
||||
});
|
||||
|
||||
test('When window.close() and requestOpen are racing', function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
var stubPublish = this.sinon.stub(callscreen, 'publish');
|
||||
this.sinon.spy(callscreen, 'requestClose');
|
||||
this.sinon.stub(callscreen, 'isActive').returns(false);
|
||||
var stubBlur = this.sinon.stub(callscreen.browser.element, 'blur');
|
||||
var stubReloadWindow = this.sinon.stub(callscreen, 'reloadWindow');
|
||||
|
||||
callscreen.requestOpen();
|
||||
callscreen.element.dispatchEvent(new CustomEvent('mozbrowserclose'));
|
||||
|
||||
sinon.assert.calledOnce(callscreen.requestClose);
|
||||
assert.isTrue(stubPublish.calledWith('terminated'));
|
||||
assert.isFalse(stubReloadWindow.called);
|
||||
callscreen.element.dispatchEvent(new CustomEvent('_closed'));
|
||||
assert.isTrue(callscreen.isHidden());
|
||||
assert.isTrue(stubReloadWindow.called);
|
||||
if (document.activeElement === callscreen.browser.element) {
|
||||
assert.isTrue(stubBlur.called);
|
||||
}
|
||||
});
|
||||
|
||||
test('Hide and reload right away while window.close() when we are not active',
|
||||
function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
this.sinon.stub(callscreen, 'isActive').returns(false);
|
||||
var stubBlur = this.sinon.stub(callscreen.browser.element, 'blur');
|
||||
var stubReloadWindow = this.sinon.stub(callscreen, 'reloadWindow');
|
||||
callscreen.element.dispatchEvent(new CustomEvent('mozbrowserclose'));
|
||||
assert.isTrue(callscreen.isHidden());
|
||||
assert.isTrue(stubReloadWindow.called);
|
||||
if (document.activeElement === callscreen.browser.element) {
|
||||
assert.isTrue(stubBlur.called);
|
||||
}
|
||||
});
|
||||
|
||||
suite('> Call screen ensure', function() {
|
||||
suite('> When the lockscreen is unlocked', function() {
|
||||
test('it should open the call screen and force a hashchange',
|
||||
function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
this.sinon.stub(callscreen, 'show');
|
||||
callscreen.ensure();
|
||||
assert.equal(CSORIGIN + 'index.html#×tamp=0',
|
||||
callscreen.browser.element.src);
|
||||
assert.isTrue(callscreen.show.calledOnce,
|
||||
'AttentionWindow#show called.');
|
||||
});
|
||||
});
|
||||
|
||||
suite('> When the lockscreen is locked', function() {
|
||||
setup(function() {
|
||||
Service.mockQueryWith('locked', true);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Service.mockQueryWith('locked', false);
|
||||
});
|
||||
|
||||
test('it should open the call screen on #locked', function() {
|
||||
var callscreen = new CallscreenWindow();
|
||||
this.sinon.stub(callscreen, 'show');
|
||||
callscreen.ensure();
|
||||
assert.equal(CSORIGIN + 'index.html#locked×tamp=0',
|
||||
callscreen.browser.element.src);
|
||||
assert.isTrue(callscreen.show.calledOnce,
|
||||
'AttentionWindow#show called.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('reloading the window', function() {
|
||||
var subject;
|
||||
setup(function() {
|
||||
subject = new CallscreenWindow();
|
||||
subject.browser.element = {
|
||||
src: 'app://callscreen.gaiamobile.org/index.html#stuff',
|
||||
setAttribute: function() {},
|
||||
classList: {
|
||||
contains: function() { return true; }
|
||||
}
|
||||
};
|
||||
this.sinon.spy(subject, 'setVisible');
|
||||
|
||||
subject.reloadWindow();
|
||||
});
|
||||
|
||||
test('should empty the src at first', function() {
|
||||
assert.equal(subject.browser.element.src, '');
|
||||
});
|
||||
|
||||
test('should set the visibility to false', function() {
|
||||
sinon.assert.calledOnce(subject.setVisible);
|
||||
sinon.assert.calledWith(subject.setVisible, false);
|
||||
});
|
||||
|
||||
test('should reset the src after a tick', function() {
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(subject.browser.element.src,
|
||||
'app://callscreen.gaiamobile.org/index.html');
|
||||
});
|
||||
});
|
||||
});
|
||||
78
gaia/apps/system/test/unit/camera_trigger_test.js
Executable file
78
gaia/apps/system/test/unit/camera_trigger_test.js
Executable file
|
|
@ -0,0 +1,78 @@
|
|||
/* global MocksHelper, BaseModule, Service */
|
||||
'use strict';
|
||||
|
||||
require('/js/service.js');
|
||||
require('/js/base_module.js');
|
||||
require('/js/camera_trigger.js');
|
||||
require('/test/unit/mock_activity.js');
|
||||
|
||||
var mocksForCameraTrigger = new MocksHelper([
|
||||
'MozActivity'
|
||||
]).init();
|
||||
|
||||
suite('system/CameraTrigger', function() {
|
||||
var subject;
|
||||
mocksForCameraTrigger.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
subject = BaseModule.instantiate('CameraTrigger');
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
suite('Launch Camera', function() {
|
||||
var activitySpy;
|
||||
var expectedActivity = {
|
||||
name: 'record',
|
||||
data: {
|
||||
type: 'photos'
|
||||
}
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
activitySpy = this.sinon.spy(window, 'MozActivity');
|
||||
});
|
||||
|
||||
suite('Allows MozActivity', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(Service, 'query', function(name) {
|
||||
return (name !== 'locked' && name !== 'isFtuRunning');
|
||||
});
|
||||
});
|
||||
|
||||
test('holdcamera triggers MozActivity', function() {
|
||||
window.dispatchEvent(new CustomEvent('holdcamera', {}));
|
||||
sinon.assert.calledWith(activitySpy, expectedActivity);
|
||||
});
|
||||
});
|
||||
|
||||
suite('LockScreen is locked', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(Service, 'query', function(name) {
|
||||
return (name === 'locked');
|
||||
});
|
||||
});
|
||||
|
||||
test('holdcamera inhibited by lockscreen', function() {
|
||||
window.dispatchEvent(new CustomEvent('holdcamera', {}));
|
||||
sinon.assert.notCalled(activitySpy);
|
||||
});
|
||||
});
|
||||
|
||||
suite('FTU is running', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(Service, 'query', function(name) {
|
||||
return (name === 'isFtuRunning');
|
||||
});
|
||||
});
|
||||
test('holdcamera inhibited when FTU running', function() {
|
||||
window.dispatchEvent(new CustomEvent('holdcamera', {}));
|
||||
sinon.assert.notCalled(activitySpy);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
188
gaia/apps/system/test/unit/captive_portal_test.js
Executable file
188
gaia/apps/system/test/unit/captive_portal_test.js
Executable file
|
|
@ -0,0 +1,188 @@
|
|||
// Captive Portal Test
|
||||
|
||||
/* global CaptivePortal,
|
||||
MockService,
|
||||
MocksHelper,
|
||||
MockChromeEvent,
|
||||
MockL10n,
|
||||
MockMozActivity,
|
||||
MockNavigatorSettings,
|
||||
MockWifiManager,
|
||||
Notification,
|
||||
MockNotificationHelper,
|
||||
Promise
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_chrome_event.js');
|
||||
requireApp('system/test/unit/mock_app.js');
|
||||
requireApp('system/test/unit/mocks_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_notification_helper.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/test/unit/mock_wifi_manager.js');
|
||||
requireApp('system/test/unit/mock_activity.js');
|
||||
requireApp('system/test/unit/mock_app_window_manager.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
|
||||
requireApp('system/js/browser_frame.js');
|
||||
requireApp('system/js/entry_sheet.js');
|
||||
requireApp('system/js/captive_portal.js');
|
||||
|
||||
var mocksForCaptivePortal = new MocksHelper([
|
||||
'SettingsListener',
|
||||
'AppWindowManager',
|
||||
'Service',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('captive portal > ', function() {
|
||||
var realWifiManager;
|
||||
var realL10n;
|
||||
var realSettings;
|
||||
var realActivity;
|
||||
var realNotificationHelper;
|
||||
var event;
|
||||
var successEvent;
|
||||
var abortEvent;
|
||||
var fakeScreenNode;
|
||||
var expectedBody, expectedTag;
|
||||
var notificationGetStub;
|
||||
var previousCaptiveNotification, previousSpy;
|
||||
|
||||
mocksForCaptivePortal.attachTestHelpers();
|
||||
suiteSetup(function() {
|
||||
realWifiManager = navigator.mozWifiManager;
|
||||
navigator.mozWifiManager = MockWifiManager;
|
||||
realSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
realNotificationHelper = window.NotificationHelper;
|
||||
window.NotificationHelper = MockNotificationHelper;
|
||||
try {
|
||||
realActivity = window.MozActivity;
|
||||
} catch (e) {
|
||||
console.log('Access MozActivity failed, passed realActivity assignment');
|
||||
}
|
||||
window.MozActivity = MockMozActivity;
|
||||
|
||||
fakeScreenNode = document.createElement('div');
|
||||
fakeScreenNode.id = 'screen';
|
||||
document.body.appendChild(fakeScreenNode);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozWifiManager = realWifiManager;
|
||||
try {
|
||||
window.MozActivity = realActivity;
|
||||
} catch (e) {
|
||||
console.log('Access MozActivity failed, passed MozActivity assignment');
|
||||
}
|
||||
navigator.mozL10n = realL10n;
|
||||
navigator.mozSettings = realSettings;
|
||||
window.NotificationHelper = realNotificationHelper;
|
||||
document.body.appendChild(fakeScreenNode);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
event = new MockChromeEvent({
|
||||
type: 'captive-portal-login',
|
||||
url: 'http://developer.mozilla.org',
|
||||
id: 0
|
||||
});
|
||||
|
||||
successEvent = new MockChromeEvent({
|
||||
type: 'captive-portal-login-success',
|
||||
url: 'http://developer.mozilla.org',
|
||||
id: 0
|
||||
});
|
||||
|
||||
abortEvent = new MockChromeEvent({
|
||||
type: 'captive-portal-login-abort',
|
||||
url: 'http://developer.mozilla.org',
|
||||
id: 0
|
||||
});
|
||||
|
||||
var expectedSSID = window.navigator.mozWifiManager.connection.network.ssid;
|
||||
expectedTag = 'captivePortal:' + expectedSSID;
|
||||
expectedBody = {
|
||||
id: 'captive-wifi-available',
|
||||
args: {
|
||||
networkName: expectedSSID
|
||||
}
|
||||
};
|
||||
|
||||
previousCaptiveNotification = new Notification('', {
|
||||
body: 'previousCaptiveNotification',
|
||||
tag: expectedTag
|
||||
});
|
||||
|
||||
notificationGetStub = function notificationGet() {
|
||||
return Promise.resolve([previousCaptiveNotification]);
|
||||
};
|
||||
this.sinon.stub(window.Notification, 'get', notificationGetStub);
|
||||
previousSpy = this.sinon.spy(previousCaptiveNotification, 'close');
|
||||
|
||||
CaptivePortal.init().then(function() {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('system/captive portal notification cleanup', function() {
|
||||
sinon.assert.called(previousSpy);
|
||||
});
|
||||
|
||||
test('system/captive portal login', function() {
|
||||
var sendSpy = this.sinon.spy(window.NotificationHelper, 'send');
|
||||
CaptivePortal.handleEvent(event);
|
||||
sinon.assert.called(sendSpy);
|
||||
var notification = sendSpy.firstCall.args[1];
|
||||
assert.deepEqual(notification.bodyL10n, expectedBody);
|
||||
assert.equal(notification.tag, expectedTag);
|
||||
assert.equal(notification.mozbehavior.showOnlyOnce, true);
|
||||
});
|
||||
|
||||
test('system/captive portal open activity url', function() {
|
||||
var expectedActivity = {
|
||||
name: 'view',
|
||||
data: { type: 'url', url: event.detail.url }
|
||||
};
|
||||
var activitySpy = this.sinon.spy(window, 'MozActivity');
|
||||
CaptivePortal.handleEvent(event);
|
||||
CaptivePortal.captiveNotification_onClick();
|
||||
sinon.assert.calledWith(activitySpy, expectedActivity);
|
||||
});
|
||||
|
||||
test('system/captive portal login success', function() {
|
||||
CaptivePortal.handleEvent(event);
|
||||
CaptivePortal.handleEvent(successEvent);
|
||||
sinon.assert.called(CaptivePortal.notification.close);
|
||||
});
|
||||
|
||||
test('system/captive portal login again', function() {
|
||||
var sendSpy = this.sinon.spy(window.NotificationHelper, 'send');
|
||||
CaptivePortal.handleEvent(event);
|
||||
sinon.assert.called(sendSpy);
|
||||
var notification = sendSpy.firstCall.args[1];
|
||||
assert.deepEqual(notification.bodyL10n, expectedBody);
|
||||
assert.equal(notification.tag, expectedTag);
|
||||
assert.equal(notification.mozbehavior.showOnlyOnce, true);
|
||||
});
|
||||
|
||||
test('system/captive portal login abort', function() {
|
||||
CaptivePortal.handleEvent(event);
|
||||
CaptivePortal.handleEvent(abortEvent);
|
||||
sinon.assert.called(CaptivePortal.notification.close);
|
||||
});
|
||||
|
||||
test('system/captive portal while FTU running..', function() {
|
||||
MockService.mockQueryWith('isFtuRunning', true);
|
||||
|
||||
CaptivePortal.handleEvent(event);
|
||||
assert.equal(CaptivePortal.hasOwnProperty('entrySheet'), true);
|
||||
});
|
||||
});
|
||||
281
gaia/apps/system/test/unit/card_test.js
Executable file
281
gaia/apps/system/test/unit/card_test.js
Executable file
|
|
@ -0,0 +1,281 @@
|
|||
/* global AppWindow, Card, MocksHelper, MockPromise, Icon,
|
||||
TaskManagerUtils, SwipeToKillMotion */
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/sanitizer.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
require('/shared/test/unit/mocks/mock_promise.js');
|
||||
require('/shared/js/homescreens/icon.js');
|
||||
|
||||
var mocksForCard = new MocksHelper([
|
||||
'AppWindow'
|
||||
]).init();
|
||||
|
||||
suite('system/Card', function() {
|
||||
|
||||
function makeApp(config) {
|
||||
var appWindow = new AppWindow({
|
||||
launchTime: 4,
|
||||
title: config.title,
|
||||
name: config.name || 'dummyapp',
|
||||
manifest: {
|
||||
orientation: config.orientation || 'portrait-primary'
|
||||
},
|
||||
isPrivate: config.isPrivate,
|
||||
rotatingDegree: config.rotatingDegree || 0,
|
||||
getScreenshot: function(callback) {
|
||||
callback();
|
||||
},
|
||||
origin: config.origin || 'app://' +
|
||||
(config.name || 'dummyapp') + '.gaiamobile.org',
|
||||
url: config.url,
|
||||
blur: function() {}
|
||||
});
|
||||
appWindow.browser.element.src = appWindow.origin + '/index.html';
|
||||
if (config.isBrowser) {
|
||||
appWindow.isBrowser = () => config.isBrowser;
|
||||
}
|
||||
return appWindow;
|
||||
}
|
||||
|
||||
mocksForCard.attachTestHelpers();
|
||||
var mockManager;
|
||||
var cardsList;
|
||||
var iconDataURI = 'data:image/png;base64,abc+';
|
||||
var getIconPromise;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
cardsList = document.createElement('ul');
|
||||
cardsList.id = 'cards-list';
|
||||
document.body.appendChild(cardsList);
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/task_manager_utils.js');
|
||||
requireApp('system/js/card.js', done);
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
getIconPromise = new MockPromise();
|
||||
this.sinon.stub(AppWindow.prototype, 'getSiteIconUrl')
|
||||
.returns(getIconPromise);
|
||||
mockManager = {
|
||||
SWIPE_UP_THRESHOLD: 480/4,
|
||||
cardsList: cardsList
|
||||
};
|
||||
|
||||
this.sinon.stub(Icon.prototype, 'renderBlob', function() {
|
||||
this.elem.style.backgroundImage = 'url(' + this.uri + ')';
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
cardsList.innerHTML = '';
|
||||
if (getIconPromise.then.called) {
|
||||
getIconPromise.mFulfillToValue({originalUrl: iconDataURI, blob: {}});
|
||||
}
|
||||
});
|
||||
|
||||
suite('render > ', function() {
|
||||
|
||||
test('does nothing when stayInvisible is set', function() {
|
||||
var card = new Card(makeApp({
|
||||
name: 'anyapp',
|
||||
title: 'sometitle'
|
||||
}), { stayInvisible: true });
|
||||
|
||||
assert.equal(card.element.style.display, 'none');
|
||||
assert.equal(card.title, undefined);
|
||||
});
|
||||
|
||||
test('adds browser class for browser windows', function(){
|
||||
var card = new Card(makeApp({
|
||||
name: 'browserapp',
|
||||
isBrowser: true,
|
||||
title: 'Page title'
|
||||
}));
|
||||
|
||||
assert.ok(card.element.classList.contains('browser'),
|
||||
'has browser class');
|
||||
assert.equal(
|
||||
card.element.querySelector('.title').textContent,
|
||||
card.app.title);
|
||||
assert.ok(!card.element.classList.contains('.private'));
|
||||
});
|
||||
|
||||
test('adds private class for private windows', function(){
|
||||
var card = new Card(makeApp({
|
||||
name: 'privatewindow',
|
||||
isBrowser: true,
|
||||
isPrivate: true
|
||||
}));
|
||||
|
||||
assert.ok(card.element.classList.contains('private'));
|
||||
});
|
||||
|
||||
test('unkillable card', function(){
|
||||
var app = makeApp({
|
||||
name: 'privatewindow',
|
||||
isBrowser: true,
|
||||
isPrivate: true
|
||||
});
|
||||
app.attentionWindow = true; // makes the card unkillable
|
||||
var card = new Card(app);
|
||||
|
||||
assert.equal(
|
||||
card.element.querySelector('.close-button').style.visibility,
|
||||
'hidden');
|
||||
});
|
||||
|
||||
test('app security for browser windows', function() {
|
||||
var app = makeApp({
|
||||
name: 'browserwindow',
|
||||
isBrowser: true
|
||||
});
|
||||
app.getSSLState = () => 'broken';
|
||||
var card = new Card(app);
|
||||
|
||||
assert.equal(card.element.dataset.ssl, 'broken');
|
||||
});
|
||||
|
||||
test('browser windows display URL in their subTitle', function() {
|
||||
var app = makeApp({
|
||||
name: 'browserwindow',
|
||||
isBrowser: true
|
||||
});
|
||||
app.config.url = 'https://someorigin.org/foo';
|
||||
var card = new Card(app);
|
||||
this.sinon.stub(TaskManagerUtils, 'getDisplayUrlForApp')
|
||||
.returns('someorigin.org/foo');
|
||||
|
||||
assert.ok(card.element.classList.contains('show-subtitle'));
|
||||
assert.equal(
|
||||
card.element.querySelector('.subtitle-url').textContent,
|
||||
'someorigin.org/foo');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('loadIcon > ', function() {
|
||||
|
||||
test('calls loadAppIcon', function(){
|
||||
this.sinon.stub(TaskManagerUtils, 'loadAppIcon')
|
||||
.returns(Promise.resolve());
|
||||
|
||||
var card = new Card(makeApp({ name: 'app' }));
|
||||
card.loadIcon();
|
||||
|
||||
assert.ok(TaskManagerUtils.loadAppIcon.called);
|
||||
assert.equal(TaskManagerUtils.loadAppIcon.firstCall.args[0], card.app);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('system/SwipeToKillMotion', function() {
|
||||
var motion, el, setTranslateY;
|
||||
var currentY;
|
||||
|
||||
setup(function() {
|
||||
el = document.createElement('div');
|
||||
setTranslateY = this.sinon.stub();
|
||||
currentY = 0;
|
||||
motion = new SwipeToKillMotion(el, {
|
||||
setTranslateY(newY) {
|
||||
currentY = newY;
|
||||
setTranslateY(currentY);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
|
||||
});
|
||||
|
||||
function touch(subtype, x, y) {
|
||||
var evt = new CustomEvent('touch' + subtype);
|
||||
evt.touches = evt.targetTouches = [];
|
||||
if (arguments.length > 1) {
|
||||
evt.touches.push({
|
||||
clientX: x, clientY: y
|
||||
});
|
||||
}
|
||||
return evt;
|
||||
}
|
||||
|
||||
test('swipe up to kill', function() {
|
||||
var dropStub = this.sinon.stub();
|
||||
var willDragStub = this.sinon.stub();
|
||||
el.addEventListener('card-dropped', dropStub);
|
||||
el.addEventListener('card-will-drag', willDragStub);
|
||||
|
||||
motion.el.dispatchEvent(touch('start', 0, 0));
|
||||
motion.el.dispatchEvent(touch('move', 0, -10));
|
||||
assert.isTrue(motion.activelyDragging);
|
||||
assert.equal(currentY, '-10px');
|
||||
motion.el.dispatchEvent(touch('move', 0, -20));
|
||||
motion.el.dispatchEvent(touch('move', 0, -30));
|
||||
motion.el.dispatchEvent(touch('move', 0, -40));
|
||||
motion.el.dispatchEvent(touch('end'));
|
||||
assert.isFalse(motion.activelyDragging);
|
||||
|
||||
assert.equal(currentY, '-200%');
|
||||
assert.isTrue(dropStub.calledOnce);
|
||||
assert.isTrue(dropStub.firstCall.args[0].detail.willKill);
|
||||
assert.isTrue(willDragStub.calledOnce);
|
||||
});
|
||||
|
||||
test('swipe up but without enough velocity', function() {
|
||||
var dropStub = this.sinon.stub();
|
||||
el.addEventListener('card-dropped', dropStub);
|
||||
|
||||
motion.el.dispatchEvent(touch('start', 0, 0));
|
||||
motion.el.dispatchEvent(touch('move', 0, -10));
|
||||
motion.el.dispatchEvent(touch('move', 0, -20));
|
||||
motion.el.dispatchEvent(touch('move', 0, -20));
|
||||
motion.el.dispatchEvent(touch('move', 0, -10));
|
||||
motion.el.dispatchEvent(touch('end'));
|
||||
|
||||
assert.equal(currentY, '0px');
|
||||
assert.isTrue(dropStub.calledOnce);
|
||||
assert.isFalse(dropStub.firstCall.args[0].detail.willKill);
|
||||
});
|
||||
|
||||
test('touch events are intercepted by the card', function() {
|
||||
var touchEvent = touch('start', 0, 0);
|
||||
this.sinon.spy(touchEvent, 'stopPropagation');
|
||||
motion.el.dispatchEvent(touchEvent);
|
||||
assert.isTrue(touchEvent.stopPropagation.called);
|
||||
});
|
||||
|
||||
test('swipe up, but event canceled', function() {
|
||||
var dropStub = this.sinon.stub();
|
||||
el.addEventListener('card-will-drag', (evt) => {
|
||||
evt.preventDefault();
|
||||
});
|
||||
|
||||
motion.el.dispatchEvent(touch('start', 0, 0));
|
||||
motion.el.dispatchEvent(touch('move', 0, -10));
|
||||
assert.equal(currentY, '0px');
|
||||
motion.el.dispatchEvent(touch('move', 0, -20));
|
||||
motion.el.dispatchEvent(touch('move', 0, -30));
|
||||
motion.el.dispatchEvent(touch('move', 0, -40));
|
||||
motion.el.dispatchEvent(touch('end'));
|
||||
|
||||
assert.equal(currentY, '0px');
|
||||
assert.isFalse(dropStub.calledOnce); // no drop event expected
|
||||
});
|
||||
|
||||
test('click while dragging should be ignored', function() {
|
||||
motion.el.dispatchEvent(touch('start', 0, 0));
|
||||
motion.el.dispatchEvent(touch('move', 0, -10));
|
||||
motion.el.dispatchEvent(touch('move', 0, -20));
|
||||
motion.el.dispatchEvent(touch('move', 0, -30));
|
||||
|
||||
var click = new CustomEvent('click', { cancelable: true });
|
||||
this.sinon.spy(click, 'stopPropagation');
|
||||
motion.el.dispatchEvent(click);
|
||||
assert.isTrue(click.defaultPrevented);
|
||||
assert.isTrue(click.stopPropagation.called);
|
||||
});
|
||||
|
||||
});
|
||||
88
gaia/apps/system/test/unit/carrier_info_notifier_test.js
Executable file
88
gaia/apps/system/test/unit/carrier_info_notifier_test.js
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
/* global CarrierInfoNotifier */
|
||||
/* global ModalDialog */
|
||||
/* global MockNotificationScreen */
|
||||
/* global MockModalDialog */
|
||||
/* global MockService */
|
||||
|
||||
requireApp('system/js/carrier_info_notifier.js');
|
||||
requireApp('system/test/unit/mock_modal_dialog.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_notification_screen.js');
|
||||
|
||||
if (typeof window.ModalDialog == 'undefined') {
|
||||
window.ModalDialog = null;
|
||||
}
|
||||
|
||||
if (typeof window.NotificationScreen == 'undefined') {
|
||||
window.NotificationScreen = null;
|
||||
}
|
||||
|
||||
suite('carrier info notifier >', function() {
|
||||
var subject;
|
||||
|
||||
var realModalDialog;
|
||||
var realNotificationScreen;
|
||||
var testData = {
|
||||
display: '0',
|
||||
extendedDisplay: {
|
||||
records: [
|
||||
{ content: '1' },
|
||||
{ content: '2' }
|
||||
]
|
||||
}
|
||||
};
|
||||
var expectedDisplay = ['0', '1 2'];
|
||||
|
||||
suiteSetup(function() {
|
||||
subject = CarrierInfoNotifier;
|
||||
|
||||
realModalDialog = window.ModalDialog;
|
||||
window.ModalDialog = MockModalDialog;
|
||||
|
||||
window.Service = window.MockService;
|
||||
MockService.mockQueryWith('locked', false);
|
||||
|
||||
realNotificationScreen = window.NotificationScreen;
|
||||
window.NotificationScreen = MockNotificationScreen;
|
||||
|
||||
});
|
||||
|
||||
test('CDMA record information: Unlocked', function(done) {
|
||||
var ptr = 0;
|
||||
MockService.mockQueryWith('locked', false);
|
||||
ModalDialog.mCallback = function(param) {
|
||||
assert.equal(param.text, expectedDisplay[ptr]);
|
||||
ptr++;
|
||||
if (ptr == expectedDisplay.length) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
subject.showCDMA(testData);
|
||||
});
|
||||
|
||||
test('CDMA record information: locked', function(done) {
|
||||
var ptr = 0;
|
||||
MockService.mockQueryWith('locked', true);
|
||||
MockNotificationScreen.mCallback = function(param) {
|
||||
assert.equal(param.text, expectedDisplay[ptr]);
|
||||
ptr++;
|
||||
if (ptr == expectedDisplay.length) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
subject.showCDMA(testData);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.ModalDialog.mTeardown();
|
||||
window.ModalDialog = realModalDialog;
|
||||
|
||||
window.NotificationScreen.mTeardown();
|
||||
window.NotificationScreen = realNotificationScreen;
|
||||
});
|
||||
});
|
||||
154
gaia/apps/system/test/unit/cell_broadcast_system_test.js
Executable file
154
gaia/apps/system/test/unit/cell_broadcast_system_test.js
Executable file
|
|
@ -0,0 +1,154 @@
|
|||
'use strict';
|
||||
/* global CellBroadcastSystem, MocksHelper, MockNavigatorMozMobileConnections,
|
||||
CarrierInfoNotifier
|
||||
*/
|
||||
|
||||
requireApp('system/js/carrier_info_notifier.js');
|
||||
requireApp('system/js/cell_broadcast_system.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
require('/shared/js/l10n.js');
|
||||
|
||||
var mocksForCBS = new MocksHelper([
|
||||
'NavigatorMozMobileConnections'
|
||||
]).init();
|
||||
|
||||
suite('system/CellBroadcastSystem', function() {
|
||||
|
||||
var subject;
|
||||
var realMozMobileConnections;
|
||||
|
||||
mocksForCBS.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozMobileConnections = navigator.mozMobileConnections;
|
||||
navigator.mozMobileConnections = MockNavigatorMozMobileConnections;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozMobileConnections = realMozMobileConnections;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
subject = new CellBroadcastSystem();
|
||||
});
|
||||
|
||||
suite('settingsChangedHandler', function() {
|
||||
test('dispatches cellbroadcastmsgchanged event', function(done) {
|
||||
window.addEventListener('cellbroadcastmsgchanged', function cb() {
|
||||
window.removeEventListener('cellbroadcastmsgchanged', cb);
|
||||
done();
|
||||
});
|
||||
subject.settingsChangedHandler({
|
||||
settingValue: [true, true]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('show', function() {
|
||||
var realMobileOperator;
|
||||
var fakeMessageID = 0;
|
||||
var fakeMcc = [123, 456];
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(CarrierInfoNotifier, 'show');
|
||||
this.sinon.stub(window, 'dispatchEvent');
|
||||
[0, 1].forEach((id) => {
|
||||
var conn = new window.MockMobileconnection();
|
||||
conn.voice = {
|
||||
network: {
|
||||
mcc: fakeMcc[id]
|
||||
}
|
||||
};
|
||||
|
||||
window.navigator.mozMobileConnections.mAddMobileConnection(conn, id);
|
||||
});
|
||||
|
||||
realMobileOperator = window.MobileOperator;
|
||||
window.MobileOperator = {
|
||||
BRAZIL_MCC:
|
||||
window.navigator.mozMobileConnections[0].voice.network.mcc,
|
||||
BRAZIL_CELLBROADCAST_CHANNEL: fakeMessageID
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.MobileOperator = realMobileOperator;
|
||||
});
|
||||
|
||||
test('if SIM1 is Brazil mcc, will send out event', function() {
|
||||
subject.show({
|
||||
message: {
|
||||
messageId: fakeMessageID,
|
||||
cdmaServiceCategory: null,
|
||||
body: {},
|
||||
serviceId: 0
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.called(window.dispatchEvent);
|
||||
sinon.assert.notCalled(CarrierInfoNotifier.show);
|
||||
});
|
||||
|
||||
test('if SIM 2 is not Brazil mcc, will not send out event', function() {
|
||||
subject.show({
|
||||
message: {
|
||||
messageId: fakeMessageID,
|
||||
cdmaServiceCategory: null,
|
||||
body: {},
|
||||
serviceId: 1
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.notCalled(window.dispatchEvent);
|
||||
sinon.assert.called(CarrierInfoNotifier.show);
|
||||
});
|
||||
|
||||
test('return while message is GSM CMAS', function() {
|
||||
subject.show({
|
||||
message: {
|
||||
messageId: 4370,
|
||||
cdmaServiceCategory: null,
|
||||
body: {}
|
||||
},
|
||||
serviceId: 0,
|
||||
});
|
||||
|
||||
sinon.assert.notCalled(CarrierInfoNotifier.show);
|
||||
});
|
||||
|
||||
test('return while message is CDMA CMAS', function() {
|
||||
subject.show({
|
||||
message: {
|
||||
messageId: 0,
|
||||
cdmaServiceCategory: 4096,
|
||||
body: {}
|
||||
},
|
||||
serviceId: 0,
|
||||
});
|
||||
|
||||
sinon.assert.notCalled(CarrierInfoNotifier.show);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_hasCBSDisabled', function() {
|
||||
suite('with any disabled CBS item', function() {
|
||||
setup(function() {
|
||||
subject._settingsDisabled = [true, false];
|
||||
});
|
||||
|
||||
test('we would get true', function() {
|
||||
assert.isTrue(subject._hasCBSDisabled());
|
||||
});
|
||||
});
|
||||
|
||||
suite('without any disabled CBS item', function() {
|
||||
setup(function() {
|
||||
subject._settingsDisabled = [false, false];
|
||||
});
|
||||
|
||||
test('we would get false', function() {
|
||||
assert.isFalse(subject._hasCBSDisabled());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
510
gaia/apps/system/test/unit/child_window_factory_test.js
Executable file
510
gaia/apps/system/test/unit/child_window_factory_test.js
Executable file
|
|
@ -0,0 +1,510 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockAppWindow, ChildWindowFactory, MockService,
|
||||
MockActivityWindow, MockPopupWindow, MockSettingsListener */
|
||||
/* jshint nonew: false */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/test/unit/mock_popup_window.js');
|
||||
requireApp('system/test/unit/mock_activity_window.js');
|
||||
requireApp('system/test/unit/mock_trusted_window.js');
|
||||
requireApp('system/test/unit/mock_attention_window.js');
|
||||
requireApp('system/test/unit/mock_global_overlay_window.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/test/unit/mock_activity.js');
|
||||
|
||||
var mocksForChildWindowFactory = new MocksHelper([
|
||||
'MozActivity', 'AppWindow', 'ActivityWindow', 'PopupWindow', 'TrustedWindow',
|
||||
'SettingsListener', 'AttentionWindow', 'Service', 'GlobalOverlayWindow'
|
||||
]).init();
|
||||
|
||||
suite('system/ChildWindowFactory', function() {
|
||||
var stubById;
|
||||
mocksForChildWindowFactory.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
this.sinon.useFakeTimers();
|
||||
|
||||
stubById = this.sinon.stub(document, 'getElementById');
|
||||
stubById.returns(document.createElement('div'));
|
||||
requireApp('system/js/child_window_factory.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
});
|
||||
|
||||
var fakeAppConfig1 = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailSameOrigin = {
|
||||
url: 'app://www.fake/child.html',
|
||||
name: 'same',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: ''
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailCrossOrigin = {
|
||||
url: 'http://fake.com/child.html',
|
||||
name: 'other',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: ''
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailBlank = {
|
||||
url: 'http://blank.com/index.html',
|
||||
name: '_blank',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: ''
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailPopup = {
|
||||
url: 'http://fake.com/child2.html',
|
||||
name: '',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: 'dialog'
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailHiddenPopup =
|
||||
Object.assign({}, fakeWindowOpenDetailPopup);
|
||||
fakeWindowOpenDetailHiddenPopup.features = 'alwaysLowered';
|
||||
|
||||
var fakeWindowOpenDetailHaidaSheet = {
|
||||
url: 'http://fake.com/child2.html',
|
||||
name: 'haida',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: 'mozhaidasheet'
|
||||
};
|
||||
|
||||
var fakeWindowOpenDetailEmail = {
|
||||
url: 'mailto:demo@mozilla.com',
|
||||
name: '',
|
||||
features: 'dialog'
|
||||
};
|
||||
|
||||
var fakeActivityDetail = {
|
||||
url: 'http://fake.activity/open.html',
|
||||
origin: 'http://fake.activity',
|
||||
manifestURL: 'http://fake.activity/manifest.webapp',
|
||||
manifest: {}
|
||||
};
|
||||
|
||||
var fakeTrustedDetail = {
|
||||
name: 'trustedname',
|
||||
frame: document.createElement('iframe'),
|
||||
requestId: 'testrequestid',
|
||||
chromeId: 'testchromeid'
|
||||
|
||||
};
|
||||
|
||||
var fakeOpenAppDetail = {
|
||||
url: 'http://fake.com/index.html',
|
||||
name: 'http://fake.com/manifest.webapp',
|
||||
isApp: true
|
||||
};
|
||||
|
||||
var fakeOpenWindowDetailAttention = {
|
||||
'url': 'app://fakeatt.gaiamobile.org/pick.html',
|
||||
'manifestURL': 'app://fakeatt.gaiamobile.org/manifest.webapp',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: 'attention'
|
||||
};
|
||||
|
||||
var fakeOpenWindowGlobalOverlay = {
|
||||
'url': 'app://fakeglobaloverlay.gaiamobile.org/pick.html',
|
||||
'manifestURL': 'app://fakeglobaloverlay.gaiamobile.org/manifest.webapp',
|
||||
frameElement: document.createElement('iframe'),
|
||||
features: 'global-clickthrough-overlay'
|
||||
};
|
||||
|
||||
test('Should only open inner sheet in setting enabled', function() {
|
||||
MockSettingsListener.mCallbacks['in-app-sheet.enabled'](false);
|
||||
var spyAppWindow = this.sinon.spy(window, 'AppWindow');
|
||||
var spyPopupWindow = this.sinon.spy(window, 'PopupWindow');
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailSameOrigin
|
||||
}));
|
||||
assert.isFalse(spyAppWindow.calledWithNew());
|
||||
assert.isTrue(spyPopupWindow.calledWithNew());
|
||||
assert.isFalse(spyPopupWindow.getCall(0).args[0].stayBackground);
|
||||
});
|
||||
|
||||
test('Open attention window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AttentionWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'hasPermission').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeOpenWindowDetailAttention
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0].parentWindow, app1);
|
||||
});
|
||||
|
||||
test('Open global overlay window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'GlobalOverlayWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'hasPermission').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeOpenWindowGlobalOverlay
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0].parentWindow, app1);
|
||||
});
|
||||
|
||||
test('Open same origin sheets', function() {
|
||||
MockSettingsListener.mCallbacks['in-app-sheet.enabled'](true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailSameOrigin
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0].previousWindow, app1);
|
||||
});
|
||||
|
||||
test('Open cross origin sheets', function() {
|
||||
MockSettingsListener.mCallbacks['in-app-sheet.enabled'](true);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailCrossOrigin
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.isUndefined(spy.getCall(0).args[0].previousWindow);
|
||||
});
|
||||
|
||||
test('Open popup', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailPopup
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0].rearWindow, app1);
|
||||
});
|
||||
|
||||
test('background app should not create child window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(false);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailSameOrigin
|
||||
}));
|
||||
assert.isFalse(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('app having a transitioning frontwindow ' +
|
||||
'should not create child window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var popup1 = new MockPopupWindow();
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
app1.frontWindow = popup1;
|
||||
this.sinon.stub(popup1, 'isTransitioning').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailPopup
|
||||
}));
|
||||
assert.isFalse(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('app having an active frontwindow ' +
|
||||
'should not create child window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var popup1 = new MockPopupWindow();
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
app1.frontWindow = popup1;
|
||||
this.sinon.stub(popup1, 'isActive').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailPopup
|
||||
}));
|
||||
assert.isFalse(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('transitioning app should not create child window', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isTransitioning').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailCrossOrigin
|
||||
}));
|
||||
assert.isFalse(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('Use mozhaidasheet to open inner sheet', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailHaidaSheet
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('Open email sheets', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var activitySpy = this.sinon.spy(window, 'MozActivity');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
var expectedActivity = {
|
||||
name: 'view',
|
||||
data: {
|
||||
type: 'url',
|
||||
url: 'mailto:demo@mozilla.com'
|
||||
}
|
||||
};
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailEmail
|
||||
}));
|
||||
assert.isTrue(activitySpy.calledWithNew());
|
||||
sinon.assert.calledWith(activitySpy, expectedActivity);
|
||||
});
|
||||
|
||||
test('Target _blank support', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
this.sinon.stub(app1, 'isTransitioning').returns(false);
|
||||
var stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent');
|
||||
var testEvt = {
|
||||
type: 'mozbrowseropenwindow',
|
||||
target: document.createElement('iframe'),
|
||||
detail: fakeWindowOpenDetailBlank,
|
||||
preventDefault: this.sinon.stub(),
|
||||
stopPropagation: this.sinon.stub()
|
||||
};
|
||||
testEvt.target.setAttribute('mozallowfullscreen', 'true');
|
||||
cwf.handleEvent(testEvt);
|
||||
|
||||
assert.equal(stubDispatchEvent.getCall(0).args[0].type, 'openwindow');
|
||||
assert.deepEqual(stubDispatchEvent.getCall(0).args[0].detail, {
|
||||
url: fakeWindowOpenDetailBlank.url,
|
||||
name: fakeWindowOpenDetailBlank.name,
|
||||
iframe: fakeWindowOpenDetailBlank.frameElement,
|
||||
isPrivate: false
|
||||
});
|
||||
assert.equal(
|
||||
fakeWindowOpenDetailBlank.frameElement.getAttribute('mozallowfullscreen'),
|
||||
'true');
|
||||
});
|
||||
|
||||
test('Create ActivityWindow', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'ActivityWindow');
|
||||
this.sinon.spy(app1, '_setVisibleForScreenReader');
|
||||
this.sinon.spy(app1, 'setNFCFocus');
|
||||
new ChildWindowFactory(app1);
|
||||
app1.element.dispatchEvent(new CustomEvent('_launchactivity', {
|
||||
detail: fakeActivityDetail
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0], fakeActivityDetail);
|
||||
assert.deepEqual(spy.getCall(0).args[1], app1);
|
||||
sinon.assert.calledWith(app1._setVisibleForScreenReader, false);
|
||||
sinon.assert.calledWith(app1.setNFCFocus, false);
|
||||
});
|
||||
|
||||
test('Create TrustedWindow', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'TrustedWindow');
|
||||
new ChildWindowFactory(app1);
|
||||
app1.element.dispatchEvent(new CustomEvent('_launchtrusted', {
|
||||
detail: fakeTrustedDetail
|
||||
}));
|
||||
assert.isTrue(spy.calledWithNew());
|
||||
assert.deepEqual(spy.getCall(0).args[0], fakeTrustedDetail);
|
||||
assert.deepEqual(spy.getCall(0).args[1], app1);
|
||||
});
|
||||
|
||||
test('isApp support', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
new ChildWindowFactory(app1);
|
||||
var spy = this.sinon.spy(app1, 'publish');
|
||||
var event = new CustomEvent('mozbrowseropenwindow', {
|
||||
detail: fakeOpenAppDetail
|
||||
});
|
||||
var eventSpy = this.sinon.spy(event, 'stopPropagation');
|
||||
app1.element.dispatchEvent(event);
|
||||
assert.isTrue(spy.called);
|
||||
assert.deepEqual(spy.getCall(0).args[0], 'openwindow');
|
||||
assert.deepEqual(spy.getCall(0).args[1],
|
||||
{ manifestURL: fakeOpenAppDetail.name,
|
||||
url: fakeOpenAppDetail.url,
|
||||
timestamp: 0 });
|
||||
assert.isTrue(eventSpy.called);
|
||||
});
|
||||
|
||||
test('No new ActivityWindow instance if the top window has same config',
|
||||
function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'ActivityWindow');
|
||||
new ChildWindowFactory(app1);
|
||||
var spy2 = this.sinon.stub(app1, 'getTopMostWindow');
|
||||
spy2.returns(new MockActivityWindow(fakeActivityDetail));
|
||||
app1.element.dispatchEvent(new CustomEvent('_launchactivity', {
|
||||
detail: fakeActivityDetail
|
||||
}));
|
||||
assert.isFalse(spy.calledWithNew());
|
||||
});
|
||||
|
||||
test('opened of activity should hide the back', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'ActivityWindow');
|
||||
app1.cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
this.sinon.stub(app1, 'isVisible').returns(true);
|
||||
app1.element.dispatchEvent(new CustomEvent('_launchactivity',
|
||||
{
|
||||
detail: fakeActivityDetail
|
||||
}));
|
||||
this.sinon.stub(app1, 'setVisible');
|
||||
var activity = spy.getCall(0).returnValue;
|
||||
activity.element.dispatchEvent(new CustomEvent('_opened', {
|
||||
detail: spy.getCall(0).returnValue
|
||||
}));
|
||||
assert.isTrue(app1.setVisible.calledWith(false, true));
|
||||
});
|
||||
|
||||
test('opened popups should hide the opener', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
app1.cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
this.sinon.stub(app1, 'isVisible').returns(true);
|
||||
app1.cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailPopup
|
||||
}));
|
||||
|
||||
this.sinon.stub(app1, 'setVisible');
|
||||
|
||||
spy.getCall(0).returnValue.element
|
||||
.dispatchEvent(new CustomEvent('_opened', {
|
||||
detail: spy.getCall(0).returnValue
|
||||
}));
|
||||
|
||||
assert.isTrue(app1.setVisible.calledWith(false, true));
|
||||
});
|
||||
|
||||
test('closing of popup should resume visibility and orientation', function() {
|
||||
MockSettingsListener.mCallbacks['in-app-sheet.enabled'](false);
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
this.sinon.stub(app1, 'isVisible').returns(true);
|
||||
this.sinon.spy(app1, '_setVisibleForScreenReader');
|
||||
MockService.mockQueryWith('getTopMostWindow', app1);
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailPopup
|
||||
}));
|
||||
var stubSetOrientation = this.sinon.stub(app1, 'setOrientation');
|
||||
this.sinon.stub(app1, 'setVisible');
|
||||
spy.getCall(0).returnValue.element
|
||||
.dispatchEvent(new CustomEvent('_closing', {
|
||||
detail: spy.getCall(0).returnValue
|
||||
}));
|
||||
assert.isTrue(stubSetOrientation.called);
|
||||
assert.isTrue(app1.setVisible.calledWith(true, true));
|
||||
sinon.assert.calledWith(app1._setVisibleForScreenReader, true);
|
||||
});
|
||||
|
||||
suite('Hidden popups', function() {
|
||||
test('app with no permissions cannot open hidden popup', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'AppWindow');
|
||||
this.sinon.stub(app1, 'hasPermission').returns(false);
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
var stubCreatePopupWindow = this.sinon.stub(cwf, 'createPopupWindow');
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailHiddenPopup
|
||||
}));
|
||||
assert.equal(stubCreatePopupWindow.callCount, 0);
|
||||
assert.equal(spy.callCount, 0);
|
||||
});
|
||||
|
||||
test('app with permissions can open hidden popup', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
this.sinon.stub(app1, 'hasPermission').returns(true);
|
||||
var spyPopupWindow = this.sinon.spy(window, 'PopupWindow');
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
var spyCreatePopupWindow = this.sinon.spy(cwf, 'createPopupWindow');
|
||||
cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailHiddenPopup
|
||||
}));
|
||||
|
||||
assert.isTrue(spyCreatePopupWindow.calledOnce);
|
||||
assert.isTrue(spyPopupWindow.getCall(0).args[0].stayBackground);
|
||||
});
|
||||
|
||||
test('opened hidden popup should not hide the opener', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var spy = this.sinon.spy(window, 'PopupWindow');
|
||||
app1.cwf = new ChildWindowFactory(app1);
|
||||
this.sinon.stub(app1, 'isActive').returns(true);
|
||||
this.sinon.stub(app1, 'isVisible').returns(true);
|
||||
this.sinon.stub(app1, 'hasPermission').returns(true);
|
||||
app1.cwf.handleEvent(new CustomEvent('mozbrowseropenwindow',
|
||||
{
|
||||
detail: fakeWindowOpenDetailHiddenPopup
|
||||
}));
|
||||
|
||||
this.sinon.stub(app1, 'setVisible');
|
||||
|
||||
spy.getCall(0).returnValue.element
|
||||
.dispatchEvent(new CustomEvent('_opened', {
|
||||
detail: spy.getCall(0).returnValue
|
||||
}));
|
||||
|
||||
assert.isFalse(app1.setVisible.calledWith(false, true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('FTU is running', function() {
|
||||
setup(function() {
|
||||
MockService.mockQueryWith('isFtuRunning', true);
|
||||
});
|
||||
|
||||
test('> _blank', function() {
|
||||
var app1 = new MockAppWindow(fakeAppConfig1);
|
||||
var cwf = new ChildWindowFactory(app1);
|
||||
var stubCreatePopupWindow = this.sinon.stub(cwf, 'createPopupWindow');
|
||||
var testEvt = (new CustomEvent('mozbrowseropenwindow', {
|
||||
detail: fakeWindowOpenDetailBlank
|
||||
}));
|
||||
cwf.handleEvent(testEvt);
|
||||
assert.isTrue(stubCreatePopupWindow.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
121
gaia/apps/system/test/unit/context_menu_view_test.js
Executable file
121
gaia/apps/system/test/unit/context_menu_view_test.js
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
/* global MocksHelper, AppWindow, ContextMenuView, Service */
|
||||
|
||||
'use strict';
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_app_window.js');
|
||||
requireApp('system/shared/js/event_safety.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/context_menu_view.js');
|
||||
|
||||
var mocksForAppModalDialog = new MocksHelper([
|
||||
'AppWindow', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('ContextMenuView', function() {
|
||||
|
||||
mocksForAppModalDialog.attachTestHelpers();
|
||||
|
||||
var contextMenu, fakeApp;
|
||||
|
||||
var fakeAppConfig = {
|
||||
url: 'app://www.fake/index.html',
|
||||
manifest: {},
|
||||
manifestURL: 'app://wwww.fake/ManifestURL',
|
||||
origin: 'app://www.fake'
|
||||
};
|
||||
|
||||
var fakeMenuItem1 = {
|
||||
id: 'fake-menu-1',
|
||||
label: 'fake-menu-1',
|
||||
icon: 'fake-icon-1',
|
||||
callback: function() {}
|
||||
};
|
||||
var fakeMenuItem2 = {
|
||||
id: 'fake-menu-2',
|
||||
label: 'fake-menu-2',
|
||||
icon: 'fake-icon-2',
|
||||
callback: function() {}
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
fakeApp = new AppWindow(fakeAppConfig);
|
||||
contextMenu = new ContextMenuView({
|
||||
'app': fakeApp,
|
||||
'containerElement': fakeApp.element
|
||||
});
|
||||
});
|
||||
|
||||
test('show(fakeMenus)', function() {
|
||||
var requestStub = this.sinon.stub(Service, 'request');
|
||||
|
||||
contextMenu.show([fakeMenuItem1, fakeMenuItem2]);
|
||||
|
||||
contextMenu.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
|
||||
assert.isTrue(contextMenu.isShown());
|
||||
assert.isTrue(contextMenu.element.classList.contains('visible'));
|
||||
// validate first menu item
|
||||
var menu1 = contextMenu.elements.list.querySelector('button:first-child');
|
||||
assert.equal(menu1.textContent, fakeMenuItem1.label);
|
||||
assert.equal(menu1.style.backgroundImage,
|
||||
'url("' + fakeMenuItem1.icon + '")');
|
||||
// validate second menu item
|
||||
var menu2 = contextMenu.elements.list.querySelector('button:nth-child(2)');
|
||||
assert.equal(menu2.textContent, fakeMenuItem2.label);
|
||||
assert.equal(menu2.style.backgroundImage,
|
||||
'url("' + fakeMenuItem2.icon + '")');
|
||||
assert.isTrue(requestStub.calledWith('focus'));
|
||||
|
||||
requestStub.restore();
|
||||
});
|
||||
|
||||
test('focus context menu', function() {
|
||||
var fakeClock = this.sinon.useFakeTimers();
|
||||
// document.activeElement will not be null. Just stub it.
|
||||
var blurStub = this.sinon.stub(document.activeElement, 'blur');
|
||||
|
||||
contextMenu.show([fakeMenuItem1, fakeMenuItem2]);
|
||||
contextMenu.focus();
|
||||
fakeClock.tick(10);
|
||||
|
||||
assert.isTrue(blurStub.called);
|
||||
blurStub.restore();
|
||||
fakeClock.restore();
|
||||
});
|
||||
|
||||
test('click menu', function(done) {
|
||||
var requestStub = this.sinon.stub(Service, 'request');
|
||||
contextMenu.show([fakeMenuItem1, fakeMenuItem2]);
|
||||
contextMenu.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
|
||||
assert.isTrue(contextMenu.element.classList.contains('visible'));
|
||||
|
||||
var callbackStub = this.sinon.stub(fakeMenuItem1, 'callback');
|
||||
|
||||
contextMenu.elements.list.querySelector('button:first-child').click();
|
||||
assert.isFalse(contextMenu.isShown());
|
||||
assert.isTrue(requestStub.calledWith('focus'));
|
||||
|
||||
assert.isFalse(callbackStub.called);
|
||||
contextMenu.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
Promise.resolve().then(() => {
|
||||
assert.isTrue(callbackStub.called);
|
||||
callbackStub.restore();
|
||||
requestStub.restore();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('click cancel', function() {
|
||||
var requestStub = this.sinon.stub(Service, 'request');
|
||||
contextMenu.show([fakeMenuItem1, fakeMenuItem2]);
|
||||
contextMenu.element.dispatchEvent(new CustomEvent('transitionend'));
|
||||
|
||||
contextMenu.element.querySelector('#ctx-cancel-button').click();
|
||||
assert.isFalse(contextMenu.isShown());
|
||||
assert.isTrue(requestStub.calledWith('focus'));
|
||||
|
||||
requestStub.restore();
|
||||
});
|
||||
|
||||
});
|
||||
102
gaia/apps/system/test/unit/core_test.js
Executable file
102
gaia/apps/system/test/unit/core_test.js
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
/* global BaseModule, MockPromise, MocksHelper, MockWifiManager */
|
||||
'use strict';
|
||||
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_promise.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_wifi_manager.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/core.js');
|
||||
|
||||
|
||||
var mocksForCore = new MocksHelper([
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/Core', function() {
|
||||
mocksForCore.attachTestHelpers();
|
||||
var core;
|
||||
setup(function() {
|
||||
core = new BaseModule.instantiate('Core');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.stop();
|
||||
});
|
||||
|
||||
suite('Start handler', function() {
|
||||
var core;
|
||||
setup(function() {
|
||||
core = new BaseModule.instantiate('Core');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
core.stop();
|
||||
});
|
||||
|
||||
test('Defined under window', function() {
|
||||
var fakePromise = new MockPromise();
|
||||
navigator.newapi = {};
|
||||
this.sinon.stub(BaseModule, 'lazyLoad').returns(fakePromise);
|
||||
core.startAPIHandler('newapi', 'NewApiHandler');
|
||||
window.NewApiHandler = function() {};
|
||||
this.sinon.stub(window, 'NewApiHandler').returns({
|
||||
start: this.sinon.spy()
|
||||
});
|
||||
fakePromise.mFulfillToValue();
|
||||
assert.isTrue(window.NewApiHandler.calledWithNew());
|
||||
assert.isTrue(window.NewApiHandler.calledWith(navigator.newapi, core));
|
||||
});
|
||||
});
|
||||
|
||||
suite('API handler bootstrap', function() {
|
||||
var realWifiManager;
|
||||
setup(function() {
|
||||
realWifiManager = navigator.mozWifiManager;
|
||||
navigator.mozWifiManager = MockWifiManager;
|
||||
this.sinon.stub(BaseModule, 'lazyLoad', function(args) {
|
||||
return Promise.resolve();
|
||||
});
|
||||
var fakeSettingsCore = {
|
||||
start: function() {}
|
||||
};
|
||||
this.sinon.stub(BaseModule, 'instantiate', function() {
|
||||
return fakeSettingsCore;
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
navigator.mozWifiManager = realWifiManager;
|
||||
});
|
||||
|
||||
test('simple launch with Wifi API', function() {
|
||||
this.sinon.stub(core, 'startAPIHandler');
|
||||
core.startAPIHandlers();
|
||||
assert.isTrue(
|
||||
core.startAPIHandler.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Launch without API', function() {
|
||||
var realSettings, realMobileConnections;
|
||||
setup(function() {
|
||||
realSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = undefined;
|
||||
realMobileConnections = navigator.mozMobileConnections;
|
||||
navigator.mozMobileConnections = undefined;
|
||||
this.sinon.stub(BaseModule, 'lazyLoad', function(args) {
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
navigator.mozSettings = realSettings;
|
||||
navigator.mozMobileConnections = realMobileConnections;
|
||||
});
|
||||
test('simple launch without Settings API', function() {
|
||||
this.sinon.stub(core, 'startAPIHandler');
|
||||
core.start();
|
||||
assert.isFalse(
|
||||
core.startAPIHandler.calledWith('mozSettings', 'SettingsCore'));
|
||||
});
|
||||
});
|
||||
});
|
||||
79
gaia/apps/system/test/unit/cost_control_test.js
Executable file
79
gaia/apps/system/test/unit/cost_control_test.js
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
'use strict';
|
||||
/* global CostControl */
|
||||
/* global MockApplications */
|
||||
/* global MocksHelper */
|
||||
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
|
||||
var mocksForCostControl = new MocksHelper([
|
||||
'Applications'
|
||||
]).init();
|
||||
|
||||
suite('system/CostControl', function() {
|
||||
mocksForCostControl.attachTestHelpers();
|
||||
var stubById;
|
||||
var realApplications;
|
||||
var fakeElement;
|
||||
var subject;
|
||||
|
||||
var fakeAppConfig = {
|
||||
'isActivity': false,
|
||||
'url': 'app://costcontrol.gaiamobile.org/index.html',
|
||||
'name': 'CostControl',
|
||||
'manifestURL': 'app://costcontrol.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://costcontrol.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'CostControl'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
setup(function(done) {
|
||||
if (!('setVisible' in HTMLIFrameElement.prototype)) {
|
||||
HTMLIFrameElement.prototype.setVisible = function stub() {};
|
||||
}
|
||||
|
||||
fakeElement = document.createElement('div');
|
||||
fakeElement.style.cssText = 'height: 100px; display: block;';
|
||||
stubById = this.sinon.stub(document, 'getElementById')
|
||||
.returns(fakeElement.cloneNode(true));
|
||||
|
||||
MockApplications.mRegisterMockApp(fakeAppConfig);
|
||||
realApplications = window.applications;
|
||||
window.applications = MockApplications;
|
||||
window.applications.ready = true;
|
||||
|
||||
requireApp('system/js/cost_control.js', function() {
|
||||
subject = new CostControl();
|
||||
subject.start();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubById.restore();
|
||||
window.applications = realApplications;
|
||||
});
|
||||
|
||||
suite('network activity threshold', function() {
|
||||
test('updates widget frame hash', function() {
|
||||
var setVisibleSpy = this.sinon.spy(HTMLIFrameElement.prototype,
|
||||
'setVisible');
|
||||
|
||||
// Dispatch a utilitytrayshow to show the widget.
|
||||
window.dispatchEvent(new CustomEvent('utilitytrayshow'));
|
||||
|
||||
// If we don't have activity the hash should not update.
|
||||
var oldFrameSrc = subject.widgetFrame.src;
|
||||
window.dispatchEvent(new CustomEvent('moznetworkupload'));
|
||||
assert.equal(oldFrameSrc, subject.widgetFrame.src);
|
||||
|
||||
subject.activityCounter = 74;
|
||||
window.dispatchEvent(new CustomEvent('moznetworkupload'));
|
||||
assert.notEqual(oldFrameSrc, subject.widgetFrame.src);
|
||||
|
||||
assert.ok(setVisibleSpy.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
196
gaia/apps/system/test/unit/cover_screen_test.js
Executable file
196
gaia/apps/system/test/unit/cover_screen_test.js
Executable file
|
|
@ -0,0 +1,196 @@
|
|||
/* global MockNavigatorSettings, MockMozPower, BaseModule */
|
||||
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_logo_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/cover_screen.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_power.js');
|
||||
|
||||
suite('CoverScreen >', function() {
|
||||
var settingsCore, realSettings, subject, realMozPower;
|
||||
const DEFAULT_VIDEO_ON = '/resources/power/carrier_power_on.mp4';
|
||||
const DEFAULT_VIDEO_OFF = '/resources/power/carrier_power_off.mp4';
|
||||
const DEFAULT_IMAGE_ON = '/resources/power/carrier_power_on.png';
|
||||
const DEFAULT_IMAGE_OFF = '/resources/power/carrier_power_off.png';
|
||||
const SETTING_POWER = 'operatorResources.power';
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozPower = navigator.mozPower;
|
||||
navigator.mozPower = MockMozPower;
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
realSettings = window.navigator.mozSettings;
|
||||
window.navigator.mozSettings = MockNavigatorSettings;
|
||||
settingsCore = BaseModule.instantiate('SettingsCore');
|
||||
settingsCore.start();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
settingsCore.stop();
|
||||
navigator.mozPower = realMozPower;
|
||||
window.navigator.mozSettings = realSettings;
|
||||
});
|
||||
|
||||
function assertLogoPathValues(expectedValues) {
|
||||
var poweron = subject._poweron;
|
||||
var poweroff = subject._poweroff;
|
||||
assert.ok(poweron);
|
||||
assert.equal(poweron.video, expectedValues.poweron.video);
|
||||
assert.equal(poweron.image, expectedValues.poweron.image);
|
||||
assert.ok(poweroff);
|
||||
assert.equal(poweroff.video, expectedValues.poweroff.video);
|
||||
assert.equal(poweroff.image, expectedValues.poweroff.image);
|
||||
}
|
||||
|
||||
function changeSettings(key, value) {
|
||||
MockNavigatorSettings.mTriggerObservers(key,
|
||||
{ settingValue: value });
|
||||
}
|
||||
|
||||
var testCases = [
|
||||
{
|
||||
'preValSet':
|
||||
{
|
||||
'poweron.video': 'operatorVariantT1/poweron/video.mp4',
|
||||
'poweron.image': 'operatorVariantT1/poweron/image.png',
|
||||
'poweroff.video': 'operatorVariantT1/poweroff/video.mp4',
|
||||
'poweroff.image': 'operatorVariantT1/poweroff/image.png'
|
||||
},
|
||||
'expecValSet':
|
||||
{
|
||||
poweron: {
|
||||
'video': 'operatorVariantT1/poweron/video.mp4',
|
||||
'image': 'operatorVariantT1/poweron/image.png'
|
||||
},
|
||||
poweroff: {
|
||||
'video': 'operatorVariantT1/poweroff/video.mp4',
|
||||
'image': 'operatorVariantT1/poweroff/image.png'
|
||||
}
|
||||
},
|
||||
'title': 'Setting power On/Off exists and has all posible values >'
|
||||
},
|
||||
{
|
||||
'preValSet':
|
||||
{
|
||||
'poweron.image': 'operatorVariantT2/poweron/image.png',
|
||||
'poweroff.video': 'operatorVariantT2/poweroff/video.mp4'
|
||||
},
|
||||
'expecValSet':
|
||||
{
|
||||
poweron: {
|
||||
'video': DEFAULT_VIDEO_ON,
|
||||
'image': 'operatorVariantT2/poweron/image.png'
|
||||
},
|
||||
poweroff: {
|
||||
'video': 'operatorVariantT2/poweroff/video.mp4',
|
||||
'image': DEFAULT_IMAGE_OFF
|
||||
}
|
||||
},
|
||||
'title': 'Setting power On/Off exists and has some of the posible values >'
|
||||
},
|
||||
{
|
||||
'preValSet': {},
|
||||
'expecValSet':
|
||||
{
|
||||
poweron: {
|
||||
'video': DEFAULT_VIDEO_ON,
|
||||
'image': DEFAULT_IMAGE_ON
|
||||
},
|
||||
poweroff: {
|
||||
'video': DEFAULT_VIDEO_OFF,
|
||||
'image': DEFAULT_IMAGE_OFF
|
||||
}
|
||||
},
|
||||
'title': 'Setting power On/Off does not exists >'
|
||||
}
|
||||
];
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(document, 'getElementById', function(id) {
|
||||
var fakeElement = document.createElement('div');
|
||||
if (id === 'poweroff-splash') {
|
||||
return null;
|
||||
} else {
|
||||
return fakeElement.cloneNode(true);
|
||||
}
|
||||
});
|
||||
subject = BaseModule.instantiate('CoverScreen');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
testCases.forEach(function(testCase) {
|
||||
test(testCase.title, function() {
|
||||
subject.start();
|
||||
changeSettings(SETTING_POWER, testCase.preValSet);
|
||||
assertLogoPathValues(testCase.expecValSet);
|
||||
});
|
||||
});
|
||||
|
||||
test('restart requested', function() {
|
||||
var stub = this.sinon.stub(navigator.mozPower, 'reboot');
|
||||
subject.poweroff(true);
|
||||
var element = document.createElement('div');
|
||||
var transitionStub = this.sinon.stub(element, 'addEventListener');
|
||||
subject.poweroffLogoLoader.onload(element);
|
||||
transitionStub.getCall(0).args[1]();
|
||||
assert.ok(stub.calledOnce);
|
||||
});
|
||||
|
||||
test('triggers will-shutdown event on shutdown', function() {
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.poweroff(false);
|
||||
assert.isTrue(subject.publish.calledWith('will-shutdown'));
|
||||
});
|
||||
|
||||
test('poweroff requested', function() {
|
||||
var stub = this.sinon.stub(navigator.mozPower, 'powerOff');
|
||||
subject.poweroff(false);
|
||||
|
||||
var element = document.createElement('div');
|
||||
var transitionStub = this.sinon.stub(element, 'addEventListener');
|
||||
subject.poweroffLogoLoader.onload(element);
|
||||
transitionStub.getCall(0).args[1]();
|
||||
assert.ok(stub.calledOnce);
|
||||
});
|
||||
|
||||
suite('Hierarchy functions', function() {
|
||||
test('Should request addHierarchy when started', function() {
|
||||
this.sinon.stub(subject.service, 'request');
|
||||
subject.start();
|
||||
assert.isTrue(
|
||||
subject.service.request.calledWith('registerHierarchy'));
|
||||
});
|
||||
|
||||
test('isActive', function() {
|
||||
subject.start();
|
||||
subject.poweron();
|
||||
subject._setReady();
|
||||
assert.isTrue(subject.isActive());
|
||||
subject.animatePoweronLogo();
|
||||
assert.isFalse(subject.isActive());
|
||||
});
|
||||
|
||||
test('activated', function() {
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.start();
|
||||
subject.poweron();
|
||||
subject._setReady();
|
||||
assert.isTrue(subject.publish.calledWith('-activated'));
|
||||
});
|
||||
|
||||
test('deactivated', function() {
|
||||
subject.start();
|
||||
subject.poweron();
|
||||
subject._setReady();
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.animatePoweronLogo();
|
||||
assert.isTrue(subject.publish.calledWith('-deactivated'));
|
||||
});
|
||||
});
|
||||
});
|
||||
51
gaia/apps/system/test/unit/cpu_manager_test.js
Executable file
51
gaia/apps/system/test/unit/cpu_manager_test.js
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
/* global CpuManager, CpuWakeLockManager */
|
||||
|
||||
require('/js/wake_lock_manager.js');
|
||||
require('/js/cpu_manager.js');
|
||||
|
||||
suite('CpuManager', function() {
|
||||
var realMozPower;
|
||||
var manager;
|
||||
var stubCpuWakeLockManager;
|
||||
|
||||
setup(function() {
|
||||
realMozPower = navigator.mozPower;
|
||||
var mockMozPower = {
|
||||
cpuSleepAllowed: true
|
||||
};
|
||||
|
||||
Object.defineProperty(navigator, 'mozPower', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return mockMozPower;
|
||||
}
|
||||
});
|
||||
|
||||
stubCpuWakeLockManager = this.sinon.stub(CpuWakeLockManager.prototype);
|
||||
this.sinon.stub(window, 'CpuWakeLockManager')
|
||||
.returns(stubCpuWakeLockManager);
|
||||
|
||||
manager = new CpuManager();
|
||||
manager.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
manager.stop();
|
||||
assert.isTrue(stubCpuWakeLockManager.stop.calledOnce);
|
||||
|
||||
Object.defineProperty(navigator, 'mozPower', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return realMozPower;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('onwakelockchange', function() {
|
||||
stubCpuWakeLockManager.onwakelockchange(true);
|
||||
|
||||
assert.isFalse(navigator.mozPower.cpuSleepAllowed);
|
||||
});
|
||||
});
|
||||
130
gaia/apps/system/test/unit/crash_reporter_test.js
Executable file
130
gaia/apps/system/test/unit/crash_reporter_test.js
Executable file
|
|
@ -0,0 +1,130 @@
|
|||
/*global MocksHelper, MockL10n, MockSettingsListener, MockSystemBanner,
|
||||
MockNavigatorSettings, CrashReporter */
|
||||
/*exported MockSettingsListener */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_system_banner.js');
|
||||
|
||||
var _HTML = `
|
||||
<div id="crash-dialog">
|
||||
<form role="dialog" class="generic-dialog" data-type="confirm">
|
||||
<section id="crash-dialog-contents">
|
||||
<h1 id="crash-dialog-title"></h1>
|
||||
<p data-l10n-id="crash-dialog-message"></p>
|
||||
<p><a id="crash-info-link" data-l10n-id="crash-info-link"></a></p>
|
||||
<p>
|
||||
<input id="always-send" type="checkbox" checked="true" />
|
||||
<label for="always-send" data-l10n-id="crash-always-report"></label>
|
||||
<p>
|
||||
</section>
|
||||
<menu data-items="2">
|
||||
<button id="dont-send-report"
|
||||
disabled="true"
|
||||
data-l10n-id="crash-dont-send"></button>
|
||||
<button id="send-report"
|
||||
class="recommend"
|
||||
data-l10n-id="crash-end"></button>
|
||||
</menu>
|
||||
</form>
|
||||
<section role="region">
|
||||
<gaia-header id="crash-reports-header" action="close">
|
||||
<h1 data-l10n-id="crashReports"></h1>
|
||||
</gaia-header>
|
||||
<div>
|
||||
<ul>
|
||||
<li class="description" data-l10n-id="crash-reports-description-1"></li>
|
||||
<li class="description" data-l10n-id="crash-reports-description-2"></li>
|
||||
<li class="description">
|
||||
<span data-l10n-id="crash-reports-description-3-start"></span>
|
||||
<span data-l10n-id="crash-reports-description-3-privacy"></span>
|
||||
<span data-l10n-id="crash-reports-description-3-end"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
|
||||
var TICK = 1000;
|
||||
var mocksForCrashReporter = new MocksHelper(['SettingsListener',
|
||||
'SystemBanner',
|
||||
'LazyLoader']);
|
||||
|
||||
suite('system/CrashReporter', function() {
|
||||
var app, clock, screen, dialog, realL10n, realMozSettings, spyL10n;
|
||||
|
||||
mocksForCrashReporter.attachTestHelpers();
|
||||
setup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
MockNavigatorSettings.mSetup();
|
||||
|
||||
document.body = document.createElement('body');
|
||||
|
||||
screen = document.createElement('div');
|
||||
screen.id = 'screen';
|
||||
screen.innerHTML = _HTML;
|
||||
|
||||
document.body.appendChild(screen);
|
||||
dialog = document.getElementById('crash-dialog');
|
||||
|
||||
app = { isActive: function() { return true; }, name: null };
|
||||
|
||||
clock = this.sinon.useFakeTimers();
|
||||
spyL10n = this.sinon.spy(MockL10n, 'get');
|
||||
|
||||
requireApp('system/js/crash_reporter.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
clock.restore();
|
||||
spyL10n.restore();
|
||||
|
||||
navigator.mozL10n = realL10n;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
MockNavigatorSettings.mTeardown();
|
||||
|
||||
document.body.removeChild(screen);
|
||||
|
||||
app = null;
|
||||
screen = null;
|
||||
dialog = null;
|
||||
});
|
||||
|
||||
test('should handle null app names in dialog', function() {
|
||||
CrashReporter.handleAppCrash(
|
||||
new CustomEvent('appcrashed', { 'detail': app })
|
||||
);
|
||||
|
||||
CrashReporter.handleCrash(0, false);
|
||||
clock.tick(TICK);
|
||||
|
||||
assert.isTrue(screen.classList.contains('crash-dialog'));
|
||||
assert.isTrue(spyL10n.calledWith('crash-dialog-app-noname'));
|
||||
});
|
||||
|
||||
test('should handle null app names in banner', function() {
|
||||
// Show the banner instead of the dialog this time.
|
||||
MockNavigatorSettings.mSettings['crashReporter.dialogShown'] = true;
|
||||
|
||||
CrashReporter.handleAppCrash(
|
||||
new CustomEvent('appcrashed', { 'detail': app })
|
||||
);
|
||||
|
||||
CrashReporter.handleCrash(0, false);
|
||||
clock.tick(TICK);
|
||||
|
||||
assert.equal(MockSystemBanner.mShowCount, 1);
|
||||
assert.equal(
|
||||
MockSystemBanner.mMessage.args.name, 'crash-dialog-app-noname'
|
||||
);
|
||||
});
|
||||
});
|
||||
36
gaia/apps/system/test/unit/debugging_icon_test.js
Executable file
36
gaia/apps/system/test/unit/debugging_icon_test.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
/* global DebuggingIcon */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/debugging_icon.js');
|
||||
|
||||
suite('system/DebuggingIcon', function() {
|
||||
var subject, manager;
|
||||
|
||||
setup(function() {
|
||||
manager = {
|
||||
enabled: false
|
||||
};
|
||||
subject = new DebuggingIcon(manager);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Debugging is enabled', function() {
|
||||
manager.enabled = true;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Debugging is disabled', function() {
|
||||
manager.enabled = false;
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
});
|
||||
77
gaia/apps/system/test/unit/debugging_monitor_test.js
Executable file
77
gaia/apps/system/test/unit/debugging_monitor_test.js
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
/* global MocksHelper, BaseModule, MockNavigatorSettings,
|
||||
MockLazyLoader */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/debugging_icon.js');
|
||||
requireApp('system/js/settings_core.js');
|
||||
requireApp('system/js/debugging_monitor.js');
|
||||
|
||||
var mocksForDebuggingMonitor = new MocksHelper([
|
||||
'NavigatorSettings',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/DebuggingMonitor', function() {
|
||||
var subject, settingsCore, realMozSettings;
|
||||
mocksForDebuggingMonitor.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
MockLazyLoader.mLoadRightAway = true;
|
||||
settingsCore = BaseModule.instantiate('SettingsCore');
|
||||
settingsCore.start();
|
||||
subject = BaseModule.instantiate('DebuggingMonitor');
|
||||
this.sinon.spy(MockLazyLoader, 'load');
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
settingsCore.stop();
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Should lazy load debugging icon', function() {
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(['js/debugging_icon.js']));
|
||||
});
|
||||
|
||||
suite('Update icon', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject.icon, 'update');
|
||||
});
|
||||
test('Should be enabled if setting value is adb-devtools', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('debugger.remote-mode',
|
||||
{ settingValue: 'adb-devtools' });
|
||||
assert.isTrue(subject.enabled);
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
|
||||
test('Should be enabled if setting value is adb-only', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('debugger.remote-mode',
|
||||
{ settingValue: 'adb-only' });
|
||||
assert.isTrue(subject.enabled);
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
|
||||
test('Should be disabled if setting value is adb-only', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('debugger.remote-mode',
|
||||
{ settingValue: 'disabled' });
|
||||
assert.isFalse(subject.enabled);
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
12
gaia/apps/system/test/unit/deferred.js
Executable file
12
gaia/apps/system/test/unit/deferred.js
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
var Deferred = function() {
|
||||
this.promise = new Promise(function(resolve, reject) {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
}.bind(this));
|
||||
return this;
|
||||
};
|
||||
exports.Deferred = Deferred;
|
||||
}(window));
|
||||
182
gaia/apps/system/test/unit/developer_hud_test.js
Executable file
182
gaia/apps/system/test/unit/developer_hud_test.js
Executable file
|
|
@ -0,0 +1,182 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, DeveloperHud */
|
||||
|
||||
requireApp('system/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
require('/js/devtools/developer_hud.js');
|
||||
|
||||
var mocksForDeveloperHud = new MocksHelper([
|
||||
'SettingsListener', 'Service'
|
||||
]).init();
|
||||
|
||||
|
||||
suite('developerHUD', function() {
|
||||
|
||||
var subject;
|
||||
|
||||
mocksForDeveloperHud.attachTestHelpers();
|
||||
setup(function() {
|
||||
subject = new DeveloperHud();
|
||||
subject.start();
|
||||
});
|
||||
|
||||
function updateMetrics(metrics) {
|
||||
var target = document.getElementById('target');
|
||||
var doc = target.document || target.ownerDocument || target;
|
||||
var event = doc.createEvent('CustomEvent');
|
||||
event.initCustomEvent('developer-hud-update', true, true,
|
||||
{ metrics: metrics });
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function getDeveloperHud() {
|
||||
var iframe = document.getElementById('target');
|
||||
var appwindow = iframe.parentElement;
|
||||
return appwindow.querySelector('.developer-hud');
|
||||
}
|
||||
|
||||
suite('display()', function() {
|
||||
|
||||
setup(function() {
|
||||
document.body.innerHTML = '<div><iframe id=target></iframe></div>';
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
function getCanvasFor(widgets) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.classList.add('widgets');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = 30;
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.font = '18px sans-serif';
|
||||
ctx.textBaseline = 'top';
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Widgets are positioned starting from the right side of the screen.
|
||||
ctx.translate(canvas.width, 0);
|
||||
|
||||
widgets.forEach(function(widget) {
|
||||
// The size of a widget is comprise between 30px and the size of its
|
||||
// content. There is also an additional padding of 5px on each side.
|
||||
var textWidth = ctx.measureText(widget.value).width;
|
||||
var widgetWidth = Math.max(30, textWidth) + (5 * 2);
|
||||
|
||||
// Position the widget relatively to the last position on the left
|
||||
// of the screen.
|
||||
ctx.translate(-widgetWidth, 0);
|
||||
|
||||
// Fill widget background-color.
|
||||
ctx.fillStyle = widget.color;
|
||||
ctx.fillRect(0, 0, widgetWidth, canvas.height);
|
||||
|
||||
// Draw widget text centered both horizontally and vertically.
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillText(widget.value,
|
||||
(widgetWidth - textWidth) / 2,
|
||||
canvas.height / 4);
|
||||
});
|
||||
|
||||
ctx.restore();
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
test('show widgets', function() {
|
||||
updateMetrics([
|
||||
{name: 'bugs', value: 42}
|
||||
]);
|
||||
var view = getDeveloperHud();
|
||||
assert.isDefined(view);
|
||||
var widgets = view.querySelector('.widgets');
|
||||
assert.isDefined(widgets);
|
||||
});
|
||||
|
||||
test('show simple widgets', function() {
|
||||
var metrics = [
|
||||
{name: 'errors', value: 23},
|
||||
{name: 'warnings', value: 16},
|
||||
{name: 'security', value: 1},
|
||||
{name: 'reflows', value: 4},
|
||||
];
|
||||
|
||||
updateMetrics(metrics);
|
||||
var view = getDeveloperHud();
|
||||
assert.isDefined(view);
|
||||
|
||||
var canvas = view.querySelector('canvas');
|
||||
var referenceCanvas = getCanvasFor([
|
||||
{ 'color': 'red', 'value': '23'},
|
||||
{ 'color': 'orange', 'value': '16'},
|
||||
{ 'color': 'black', 'value': '1'},
|
||||
{ 'color': 'purple', 'value': '4'},
|
||||
]);
|
||||
assert.equal(canvas.toDataURL(),
|
||||
referenceCanvas.toDataURL());
|
||||
});
|
||||
|
||||
test('show ms widgets', function() {
|
||||
var metrics = [
|
||||
{name: 'jank', value: 100},
|
||||
];
|
||||
|
||||
updateMetrics(metrics);
|
||||
var view = getDeveloperHud();
|
||||
assert.isDefined(view);
|
||||
|
||||
var canvas = view.querySelector('canvas');
|
||||
var referenceCanvas = getCanvasFor([
|
||||
{ 'color': 'cornflowerblue', 'value': '100ms'},
|
||||
]);
|
||||
assert.equal(canvas.toDataURL(),
|
||||
referenceCanvas.toDataURL());
|
||||
});
|
||||
|
||||
test('show memory widgets', function() {
|
||||
var prefix = ['','K','M','G','T','P','E','Z','Y'];
|
||||
|
||||
for (var i = 0; i < prefix.length; i++) {
|
||||
var value = 1.1 * Math.pow(1024, i);
|
||||
var metrics = [
|
||||
{'name': 'uss', 'value': value},
|
||||
{'name': 'memory', 'value': value},
|
||||
];
|
||||
|
||||
updateMetrics(metrics);
|
||||
var view = getDeveloperHud();
|
||||
assert.isDefined(view);
|
||||
|
||||
var canvas = view.querySelector('canvas');
|
||||
|
||||
while (value > 1024) {
|
||||
value /= 1024;
|
||||
}
|
||||
var referenceValue =
|
||||
(Math.round(value * 100) / 100) + ' ' + prefix[i] + 'B';
|
||||
var referenceCanvas = getCanvasFor([
|
||||
{ 'color': 'dimgrey', 'value': referenceValue },
|
||||
{ 'color': 'lightslategrey', 'value': referenceValue },
|
||||
]);
|
||||
assert.equal(canvas.toDataURL(),
|
||||
referenceCanvas.toDataURL());
|
||||
}
|
||||
});
|
||||
|
||||
test('show widgets and tear down', function() {
|
||||
updateMetrics([
|
||||
{name: 'explosions', value: 15},
|
||||
{name: 'armageddon', value: 8},
|
||||
{name: 'chaos', value: 4}
|
||||
]);
|
||||
updateMetrics();
|
||||
assert.isNull(getDeveloperHud());
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
350
gaia/apps/system/test/unit/device_storage_watcher_test.js
Executable file
350
gaia/apps/system/test/unit/device_storage_watcher_test.js
Executable file
|
|
@ -0,0 +1,350 @@
|
|||
/* global DeviceStorageWatcher, MocksHelper, MockL10n,
|
||||
MockNavigatorGetDeviceStorage, MockSystemBanner */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/device_storage_watcher.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_system_banner.js');
|
||||
requireApp('system/test/unit/mock_notification_screen.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_event_target.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_dom_request.js');
|
||||
requireApp('system/test/unit/mock_navigator_get_device_storage.js');
|
||||
|
||||
var mocksForStorageWatcher = new MocksHelper([
|
||||
'SystemBanner',
|
||||
'NotificationScreen',
|
||||
'LazyLoader',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/DeviceStorageWatcher >', function() {
|
||||
var realL10n;
|
||||
var realNavigatorGetDeviceStorage;
|
||||
var fakeNotif;
|
||||
|
||||
mocksForStorageWatcher.attachTestHelpers();
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
realNavigatorGetDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockNavigatorGetDeviceStorage;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
navigator.getDeviceStorage = realNavigatorGetDeviceStorage;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
fakeNotif = document.createElement('div');
|
||||
fakeNotif.id = 'storage-watcher-container';
|
||||
fakeNotif.innerHTML = [
|
||||
'<div data-icon="storage-circle" aria-hidden="true"></div>',
|
||||
'<div class="title-container"></div>',
|
||||
'<div class="detail"></div>'
|
||||
].join('');
|
||||
|
||||
document.body.appendChild(fakeNotif);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
DeviceStorageWatcher._container = null;
|
||||
|
||||
fakeNotif.parentNode.removeChild(fakeNotif);
|
||||
});
|
||||
|
||||
suite('init', function() {
|
||||
setup(function(done) {
|
||||
DeviceStorageWatcher.start();
|
||||
done();
|
||||
});
|
||||
|
||||
test('should bind DOM elements', function(done) {
|
||||
assert.equal('storage-watcher-container',
|
||||
DeviceStorageWatcher._container.id);
|
||||
assert.equal('title-container', DeviceStorageWatcher._message.className);
|
||||
assert.equal('detail',
|
||||
DeviceStorageWatcher._availableSpace.className);
|
||||
done();
|
||||
});
|
||||
|
||||
test('should bind to the click event', function(done) {
|
||||
assert.equal(DeviceStorageWatcher.containerClicked.name,
|
||||
DeviceStorageWatcher._container.onclick.name);
|
||||
done();
|
||||
});
|
||||
|
||||
test('should add change event listener', function(done) {
|
||||
assert.equal(typeof DeviceStorageWatcher._appStorage._listeners.change,
|
||||
'object');
|
||||
done();
|
||||
});
|
||||
|
||||
test('lowDeviceStorage should be false', function(done) {
|
||||
assert.isTrue(!DeviceStorageWatcher._lowDeviceStorage);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('low device storage', function() {
|
||||
var event;
|
||||
var getSpy;
|
||||
|
||||
setup(function() {
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var freeSpaceSpy = this.sinon.spy(mockDeviceStorage, 'freeSpace');
|
||||
getSpy = this.sinon.spy(navigator.mozL10n, 'get');
|
||||
|
||||
DeviceStorageWatcher.start();
|
||||
event = {
|
||||
type: 'change',
|
||||
reason: 'low-disk-space'
|
||||
};
|
||||
DeviceStorageWatcher.handleEvent(event);
|
||||
|
||||
var freeSpaceRequest = freeSpaceSpy.getCall(0).returnValue;
|
||||
freeSpaceRequest.fireSuccess(0);
|
||||
});
|
||||
|
||||
test('lowDeviceStorage should be true', function() {
|
||||
assert.isTrue(DeviceStorageWatcher._lowDeviceStorage);
|
||||
});
|
||||
|
||||
test('should show system banner', function() {
|
||||
assert.equal(1, MockSystemBanner.mShowCount);
|
||||
assert.deepEqual(['low-device-storage', {
|
||||
id: 'free-space',
|
||||
args: { value: 0, unit: 'byteUnit-B'}
|
||||
}], MockSystemBanner.mMessage);
|
||||
});
|
||||
|
||||
test('should show system banner at every app launch', function() {
|
||||
assert.equal(1, MockSystemBanner.mShowCount);
|
||||
window.dispatchEvent(new CustomEvent('appopening'));
|
||||
assert.equal(2, MockSystemBanner.mShowCount);
|
||||
});
|
||||
|
||||
test('should display the notification', function() {
|
||||
assert.isTrue(fakeNotif.classList.contains('displayed'));
|
||||
assert.equal(fakeNotif.querySelector('.title-container')
|
||||
.getAttribute('data-l10n-id'), 'low-device-storage');
|
||||
var l10nAttrs = navigator.mozL10n.getAttributes(
|
||||
fakeNotif.querySelector('.detail'));
|
||||
assert.equal(l10nAttrs.id, 'free-space');
|
||||
assert.deepEqual(l10nAttrs.args, {
|
||||
value: 0,
|
||||
unit: 'byteUnit-B'
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n.get.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('low device storage, unknown free space', function() {
|
||||
var event;
|
||||
var getSpy;
|
||||
|
||||
setup(function() {
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var freeSpaceSpy = this.sinon.spy(mockDeviceStorage, 'freeSpace');
|
||||
getSpy = this.sinon.spy(navigator.mozL10n, 'get');
|
||||
|
||||
DeviceStorageWatcher.start();
|
||||
event = {
|
||||
type: 'change',
|
||||
reason: 'low-disk-space'
|
||||
};
|
||||
DeviceStorageWatcher.handleEvent(event);
|
||||
|
||||
var freeSpaceRequest = freeSpaceSpy.getCall(0).returnValue;
|
||||
freeSpaceRequest.fireSuccess(undefined);
|
||||
});
|
||||
|
||||
test('lowDeviceStorage should be true', function() {
|
||||
assert.isTrue(DeviceStorageWatcher._lowDeviceStorage);
|
||||
});
|
||||
|
||||
test('should show system banner with unknown space', function() {
|
||||
assert.equal(1, MockSystemBanner.mShowCount);
|
||||
assert.deepEqual(['low-device-storage', 'unknown-free-space'],
|
||||
MockSystemBanner.mMessage);
|
||||
});
|
||||
|
||||
test('should display the notification with unknown space', function() {
|
||||
assert.isTrue(fakeNotif.classList.contains('displayed'));
|
||||
assert.equal(fakeNotif.querySelector('.title-container').
|
||||
getAttribute('data-l10n-id'), 'low-device-storage');
|
||||
assert.equal(
|
||||
fakeNotif.querySelector('.detail').getAttribute('data-l10n-id'),
|
||||
'unknown-free-space');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozL10n.get.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('repeated low device storage notification', function() {
|
||||
var event;
|
||||
|
||||
setup(function() {
|
||||
var mockDeviceStorage = MockNavigatorGetDeviceStorage();
|
||||
var freeSpaceSpy = this.sinon.spy(mockDeviceStorage, 'freeSpace');
|
||||
|
||||
DeviceStorageWatcher.start();
|
||||
event = {
|
||||
type: 'change',
|
||||
reason: 'low-disk-space'
|
||||
};
|
||||
DeviceStorageWatcher.handleEvent(event);
|
||||
|
||||
var freeSpaceRequest = freeSpaceSpy.getCall(0).returnValue;
|
||||
freeSpaceRequest.fireSuccess(2048);
|
||||
|
||||
DeviceStorageWatcher.handleEvent(event);
|
||||
|
||||
var freeSpaceRequest1 = freeSpaceSpy.getCall(1).returnValue;
|
||||
freeSpaceRequest1.fireSuccess(1024);
|
||||
});
|
||||
|
||||
test('lowDeviceStorage should be true', function() {
|
||||
assert.isTrue(DeviceStorageWatcher._lowDeviceStorage);
|
||||
});
|
||||
|
||||
test('should update free space', function() {
|
||||
var l10nAttrs = navigator.mozL10n.getAttributes(
|
||||
fakeNotif.querySelector('.detail'));
|
||||
assert.equal(l10nAttrs.id, 'free-space');
|
||||
assert.deepEqual(l10nAttrs.args, {
|
||||
value: 1,
|
||||
unit: 'byteUnit-KB'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('available device storage', function() {
|
||||
var event;
|
||||
|
||||
setup(function() {
|
||||
DeviceStorageWatcher.start();
|
||||
event = {
|
||||
type: 'change',
|
||||
reason: 'available-disk-space'
|
||||
};
|
||||
DeviceStorageWatcher.handleEvent(event);
|
||||
});
|
||||
|
||||
test('lowDeviceStorage should be false', function() {
|
||||
assert.isTrue(!DeviceStorageWatcher._lowDeviceStorage);
|
||||
});
|
||||
|
||||
test('should hide notification', function() {
|
||||
assert.isTrue(!fakeNotif.classList.contains('displayed'));
|
||||
});
|
||||
|
||||
test('should not show system banner at every app launch', function() {
|
||||
window.dispatchEvent(new CustomEvent('appopening'));
|
||||
assert.equal(0, MockSystemBanner.mShowCount);
|
||||
});
|
||||
});
|
||||
|
||||
suite('formatSize helper', function() {
|
||||
test('empty size', function() {
|
||||
assert.equal(DeviceStorageWatcher.formatSize(), undefined);
|
||||
});
|
||||
|
||||
test('NaN', function() {
|
||||
assert.equal(DeviceStorageWatcher.formatSize('NaN'), undefined);
|
||||
});
|
||||
|
||||
test('bytes', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-B');
|
||||
});
|
||||
|
||||
test('KB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('KB with decimal (round down)', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 + 511);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('KB with decimal (round up)', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 + 512);
|
||||
assert.equal(result.size, 2);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('MB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('MB with decimal (lower than 1K)', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 + 512);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('MB with decimal (0.5MB)', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 + 512 * 1024);
|
||||
assert.equal(result.size, 1.5);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('GB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-GB');
|
||||
});
|
||||
|
||||
test('TB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-TB');
|
||||
});
|
||||
|
||||
test('PB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024 * 1024 *
|
||||
1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-PB');
|
||||
});
|
||||
|
||||
test('EB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024 * 1024 *
|
||||
1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-EB');
|
||||
});
|
||||
|
||||
test('ZB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024 * 1024 *
|
||||
1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-ZB');
|
||||
});
|
||||
|
||||
test('YB', function() {
|
||||
var result = DeviceStorageWatcher.formatSize(1024 * 1024 * 1024 * 1024 *
|
||||
1024 * 1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-YB');
|
||||
});
|
||||
});
|
||||
});
|
||||
531
gaia/apps/system/test/unit/dialer_agent_test.js
Executable file
531
gaia/apps/system/test/unit/dialer_agent_test.js
Executable file
|
|
@ -0,0 +1,531 @@
|
|||
'use strict';
|
||||
|
||||
/* global DialerAgent, MockAppWindow, MocksHelper, MockNavigatorMozTelephony,
|
||||
MockSettingsListener, MockSettingsURL, MockAudio, MockApplications,
|
||||
MockService */
|
||||
|
||||
require('/js/dialer_agent.js');
|
||||
require('/test/unit/mock_app_window.js');
|
||||
require('/test/unit/mock_applications.js');
|
||||
require('/test/unit/mock_attention_window.js');
|
||||
require('/test/unit/mock_callscreen_window.js');
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_url.js');
|
||||
require('/shared/test/unit/mocks/mock_audio.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_telephony.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
|
||||
var mocksForDialerAgent = new MocksHelper([
|
||||
'CallscreenWindow',
|
||||
'Audio',
|
||||
'SettingsListener',
|
||||
'SettingsURL',
|
||||
'LazyLoader',
|
||||
'Service'
|
||||
]).init();
|
||||
|
||||
suite('system/DialerAgent', function() {
|
||||
mocksForDialerAgent.attachTestHelpers();
|
||||
var realTelephony, realVibrate, realApplications;
|
||||
|
||||
var subject;
|
||||
var setVisibleSpy;
|
||||
|
||||
function callschanged() {
|
||||
MockNavigatorMozTelephony.mTriggerEvent(new CustomEvent('callschanged'));
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
realApplications = window.applications;
|
||||
window.applications = MockApplications;
|
||||
realTelephony = navigator.mozTelephony;
|
||||
navigator.mozTelephony = MockNavigatorMozTelephony;
|
||||
realVibrate = navigator.vibrate;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockNavigatorMozTelephony.mSuiteTeardown();
|
||||
navigator.mozTelephony = realTelephony;
|
||||
navigator.vibrate = realVibrate;
|
||||
window.applications = realApplications;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
if (!('setVisible' in HTMLIFrameElement.prototype)) {
|
||||
HTMLIFrameElement.prototype.setVisible = function stub() {};
|
||||
}
|
||||
setVisibleSpy = this.sinon.spy(HTMLIFrameElement.prototype, 'setVisible');
|
||||
|
||||
this.sinon.useFakeTimers();
|
||||
subject = new DialerAgent();
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
MockService.mTeardown();
|
||||
MockNavigatorMozTelephony.mTeardown();
|
||||
});
|
||||
|
||||
function MockCall(state) {
|
||||
this.state = state;
|
||||
this.addEventListener = function() {};
|
||||
this.removeEventListener = function() {};
|
||||
this.hangUp = function() {};
|
||||
}
|
||||
|
||||
test('Should load tone player if just upgraded', function() {
|
||||
window.toneUpgrader = {
|
||||
perform: this.sinon.spy()
|
||||
};
|
||||
subject.stop();
|
||||
MockService.mockQueryWith('justUpgraded', true);
|
||||
subject.start();
|
||||
assert.isTrue(window.toneUpgrader.perform.calledWith('ringtone'));
|
||||
delete window.toneUpgrader;
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
suite('Audio element setup', function() {
|
||||
var mockAudio;
|
||||
|
||||
setup(function() {
|
||||
mockAudio = MockAudio.instances[0];
|
||||
});
|
||||
|
||||
test('it should set the channel', function() {
|
||||
assert.equal(mockAudio.mozAudioChannelType, 'ringer');
|
||||
});
|
||||
|
||||
test('it should preload metadata', function() {
|
||||
assert.equal(mockAudio.preload, 'metadata');
|
||||
});
|
||||
|
||||
test('it should loop', function() {
|
||||
assert.isTrue(mockAudio.loop);
|
||||
});
|
||||
|
||||
test('it should load the ringtone from the settings', function() {
|
||||
assert.isUndefined(mockAudio.src);
|
||||
|
||||
var blob = new Blob([], {type: 'audio/ogg'});
|
||||
var src = '----uniq----';
|
||||
this.sinon.stub(MockSettingsURL.prototype, 'set').withArgs(blob).returns(
|
||||
src
|
||||
);
|
||||
MockSettingsListener.mTriggerCallback('dialer.ringtone', blob);
|
||||
|
||||
assert.equal(mockAudio.src, src);
|
||||
});
|
||||
});
|
||||
|
||||
suite('When an incoming call comes in', function() {
|
||||
var vibrateSpy;
|
||||
var mockCall;
|
||||
var mockAudio;
|
||||
|
||||
setup(function() {
|
||||
vibrateSpy = this.sinon.spy();
|
||||
navigator.vibrate = vibrateSpy;
|
||||
|
||||
mockAudio = MockAudio.instances[0];
|
||||
mockAudio.src = '---';
|
||||
this.sinon.spy(mockAudio, 'play');
|
||||
this.sinon.spy(mockAudio, 'pause');
|
||||
|
||||
mockCall = new MockCall('incoming');
|
||||
this.sinon.spy(mockCall, 'addEventListener');
|
||||
this.sinon.spy(mockCall, 'removeEventListener');
|
||||
MockNavigatorMozTelephony.calls = [mockCall];
|
||||
});
|
||||
|
||||
suite('if the vibration is enabled', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should start vibrating', function() {
|
||||
assert.isTrue(vibrateSpy.calledWith([200]));
|
||||
});
|
||||
|
||||
test('it should vibrate every 600ms', function() {
|
||||
this.sinon.clock.tick(600);
|
||||
assert.isTrue(vibrateSpy.calledTwice);
|
||||
this.sinon.clock.tick(600);
|
||||
assert.isTrue(vibrateSpy.calledThrice);
|
||||
});
|
||||
|
||||
test('it should stop when the call state changes', function() {
|
||||
mockCall.addEventListener.yield();
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
assert.isTrue(vibrateSpy.notCalled);
|
||||
});
|
||||
|
||||
test('it should stop when the user presses volume down', function() {
|
||||
window.dispatchEvent(new CustomEvent('volumedown'));
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
assert.isTrue(vibrateSpy.notCalled);
|
||||
});
|
||||
|
||||
test('it should stop when the user presses the power button', function() {
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.notCalled(vibrateSpy);
|
||||
});
|
||||
});
|
||||
|
||||
suite('if the vibration is disabled', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('vibration.enabled', false);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should not vibrate', function() {
|
||||
assert.isTrue(vibrateSpy.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
suite('if the ringtone has a volume', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should play the ringtone', function() {
|
||||
assert.isTrue(mockAudio.play.calledOnce);
|
||||
});
|
||||
|
||||
test('it should pause when the call state changes', function() {
|
||||
mockCall.addEventListener.yield();
|
||||
assert.isTrue(mockAudio.pause.calledOnce);
|
||||
});
|
||||
|
||||
test('it should pause when the user presses the sleep button',
|
||||
function() {
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
assert.isTrue(mockAudio.pause.calledOnce);
|
||||
});
|
||||
|
||||
suite('but we have no audio source loaded', function() {
|
||||
setup(function() {
|
||||
mockAudio.readyState = 0;
|
||||
});
|
||||
|
||||
test('pressing the sleep button should not do anything', function() {
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
assert.isTrue(mockAudio.pause.notCalled);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('if the ringtone is muted', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('audio.volume.notification', 0);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should play the silent ringtone', function() {
|
||||
sinon.assert.calledOnce(mockAudio.play);
|
||||
});
|
||||
});
|
||||
|
||||
test('it should listen to the state changes of the call', function() {
|
||||
callschanged();
|
||||
assert.isTrue(mockCall.addEventListener.calledWith('statechange'));
|
||||
});
|
||||
|
||||
test('it should not listen twice if we get multiple callschanged',
|
||||
function() {
|
||||
callschanged();
|
||||
callschanged();
|
||||
assert.isTrue(mockCall.addEventListener.calledOnce);
|
||||
});
|
||||
|
||||
test('it should remove the statechange listener after the first trigger',
|
||||
function() {
|
||||
callschanged();
|
||||
mockCall.addEventListener.yield();
|
||||
assert.isTrue(mockCall.removeEventListener.calledWith('statechange'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('When a second incoming call comes in', function() {
|
||||
var vibrateSpy;
|
||||
var secondCall;
|
||||
var mockAudio;
|
||||
|
||||
setup(function() {
|
||||
var mockCall = new MockCall('incoming');
|
||||
this.sinon.spy(mockCall, 'addEventListener');
|
||||
MockNavigatorMozTelephony.calls = [mockCall];
|
||||
callschanged();
|
||||
mockCall.addEventListener.yield();
|
||||
mockCall.state = 'connected';
|
||||
|
||||
secondCall = new MockCall('incoming');
|
||||
this.sinon.spy(secondCall, 'addEventListener');
|
||||
MockNavigatorMozTelephony.calls = [mockCall, secondCall];
|
||||
|
||||
vibrateSpy = this.sinon.spy();
|
||||
navigator.vibrate = vibrateSpy;
|
||||
|
||||
mockAudio = MockAudio.instances[0];
|
||||
this.sinon.spy(mockAudio, 'play');
|
||||
|
||||
callschanged();
|
||||
});
|
||||
|
||||
suite('if the vibration is enabled', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should start vibrating', function() {
|
||||
sinon.assert.calledWith(vibrateSpy, [200]);
|
||||
});
|
||||
|
||||
test('it should vibrate every 600ms', function() {
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.calledTwice(vibrateSpy);
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.calledThrice(vibrateSpy);
|
||||
});
|
||||
|
||||
test('it should stop when the call state changes', function() {
|
||||
secondCall.addEventListener.yield();
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.notCalled(vibrateSpy);
|
||||
});
|
||||
|
||||
test('it should stop when the user presses volume down', function() {
|
||||
window.dispatchEvent(new CustomEvent('volumedown'));
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.notCalled(vibrateSpy);
|
||||
});
|
||||
|
||||
test('it should stop when the user presses the power button', function() {
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
vibrateSpy.reset();
|
||||
this.sinon.clock.tick(600);
|
||||
sinon.assert.notCalled(vibrateSpy);
|
||||
});
|
||||
});
|
||||
|
||||
suite('even if the ringtone has a volume', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
|
||||
});
|
||||
|
||||
test('it should play the silent ringtone', function() {
|
||||
sinon.assert.called(mockAudio.play);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('When a outgoing call goes out', function() {
|
||||
var vibrateSpy;
|
||||
var mockCall;
|
||||
var mockAudio;
|
||||
|
||||
setup(function() {
|
||||
vibrateSpy = this.sinon.spy();
|
||||
navigator.vibrate = vibrateSpy;
|
||||
|
||||
mockAudio = MockAudio.instances[0];
|
||||
this.sinon.spy(mockAudio, 'play');
|
||||
|
||||
mockCall = new MockCall('dialing');
|
||||
this.sinon.spy(mockCall, 'addEventListener');
|
||||
MockNavigatorMozTelephony.calls = [mockCall];
|
||||
});
|
||||
|
||||
suite('even if the vibration is enabled', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should not vibrate', function() {
|
||||
assert.isTrue(vibrateSpy.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
suite('even if the ringtone has a volume', function() {
|
||||
setup(function() {
|
||||
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
|
||||
callschanged();
|
||||
});
|
||||
|
||||
test('it should not play', function() {
|
||||
assert.isTrue(mockAudio.play.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
test('it should not listen to the state changes of the call', function() {
|
||||
callschanged();
|
||||
assert.isTrue(mockCall.addEventListener.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw if started twice', function(done) {
|
||||
try {
|
||||
subject.start();
|
||||
} catch (e) {
|
||||
assert.ok(e);
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
test('should not do anything if mozTelephony is unavailable', function() {
|
||||
subject.stop();
|
||||
MockAudio.mTeardown();
|
||||
|
||||
MockSettingsListener.mCallbacks = {};
|
||||
navigator.mozTelephony = undefined;
|
||||
|
||||
subject = new DialerAgent();
|
||||
subject.start();
|
||||
|
||||
assert.equal(MockAudio.instances.length, 0);
|
||||
assert.deepEqual(MockSettingsListener.mCallbacks, {});
|
||||
|
||||
navigator.mozTelephony = MockNavigatorMozTelephony;
|
||||
});
|
||||
|
||||
suite('handling memory pressure events',
|
||||
function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(subject._callscreenWindow, 'free');
|
||||
});
|
||||
|
||||
test('callscreen should be freed once memory is under pressure',
|
||||
function() {
|
||||
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
|
||||
sinon.assert.calledOnce(subject._callscreenWindow.free);
|
||||
});
|
||||
|
||||
test('callscreen should not be freed if a call is present', function() {
|
||||
MockNavigatorMozTelephony.calls = [{}];
|
||||
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
|
||||
sinon.assert.notCalled(subject._callscreenWindow.free);
|
||||
});
|
||||
|
||||
test('callscreen should not be freed if a conference call is present',
|
||||
function() {
|
||||
MockNavigatorMozTelephony.conferenceGroup.calls = [{}];
|
||||
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
|
||||
sinon.assert.notCalled(subject._callscreenWindow.free);
|
||||
});
|
||||
|
||||
test('callscreen should not be freed if it is visible',
|
||||
function() {
|
||||
this.sinon.stub(MockAppWindow.prototype, 'isVisible').returns(true);
|
||||
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
|
||||
sinon.assert.notCalled(subject._callscreenWindow.free);
|
||||
});
|
||||
});
|
||||
|
||||
suite('wake events', function() {
|
||||
setup(function() {
|
||||
this.sinon.spy(MockService, 'request');
|
||||
});
|
||||
|
||||
test('during a call should turn on the screen', function() {
|
||||
MockNavigatorMozTelephony.calls = [new MockCall()];
|
||||
window.dispatchEvent(new CustomEvent('wake'));
|
||||
sinon.assert.calledOnce(MockService.request);
|
||||
sinon.assert.calledWith(MockService.request, 'turnScreenOn');
|
||||
});
|
||||
|
||||
test('when not on a call should be ignored', function() {
|
||||
window.dispatchEvent(new CustomEvent('wake'));
|
||||
sinon.assert.notCalled(MockService.request);
|
||||
});
|
||||
});
|
||||
|
||||
suite('sleep events', function() {
|
||||
test('when alerting stop playing the ringtone', function() {
|
||||
var mockAudio = MockAudio.instances[0];
|
||||
|
||||
this.sinon.spy(mockAudio, 'pause');
|
||||
MockNavigatorMozTelephony.calls = [new MockCall('incoming')];
|
||||
MockNavigatorMozTelephony.mTriggerCallsChanged();
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
sinon.assert.calledOnce(mockAudio.pause);
|
||||
});
|
||||
|
||||
test('when not alerting hang up all connected calls', function() {
|
||||
var mockCalls = [ new MockCall() , new MockCall() ];
|
||||
|
||||
mockCalls.forEach((mockCall) => this.sinon.spy(mockCall, 'hangUp'));
|
||||
MockNavigatorMozTelephony.calls = mockCalls;
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
mockCalls.forEach((mockCall) => sinon.assert.calledOnce(mockCall.hangUp));
|
||||
});
|
||||
|
||||
test('when not alerting hang up the conference call', function() {
|
||||
var mockCalls = [ new MockCall() , new MockCall() ];
|
||||
|
||||
MockNavigatorMozTelephony.conferenceGroup.calls = mockCalls;
|
||||
this.sinon.spy(MockNavigatorMozTelephony.conferenceGroup, 'hangUp');
|
||||
MockNavigatorMozTelephony.calls = mockCalls;
|
||||
window.dispatchEvent(new CustomEvent('sleep'));
|
||||
sinon.assert.calledOnce(MockNavigatorMozTelephony.conferenceGroup.hangUp);
|
||||
});
|
||||
});
|
||||
|
||||
test('Make fake notification if application is ready', function() {
|
||||
subject.stop();
|
||||
subject = new DialerAgent();
|
||||
MockApplications.ready = false;
|
||||
var stubMakeFakeNotification =
|
||||
this.sinon.stub(subject, 'makeFakeNotification');
|
||||
subject.start();
|
||||
assert.isFalse(stubMakeFakeNotification.called);
|
||||
window.dispatchEvent(new CustomEvent('applicationready'));
|
||||
assert.isTrue(stubMakeFakeNotification.called);
|
||||
});
|
||||
|
||||
suite('onCall', function() {
|
||||
test('returns true when on a call', function() {
|
||||
MockNavigatorMozTelephony.calls = [ new MockCall() ];
|
||||
|
||||
assert.isTrue(subject.onCall());
|
||||
});
|
||||
|
||||
test('returns true when on a conference call', function() {
|
||||
MockNavigatorMozTelephony.conferenceGroup.calls = [
|
||||
new MockCall() , new MockCall()
|
||||
];
|
||||
|
||||
assert.isTrue(subject.onCall());
|
||||
});
|
||||
|
||||
test('returns false when not on a call', function() {
|
||||
assert.isFalse(subject.onCall());
|
||||
});
|
||||
|
||||
test('registers as a service when the dialer service is alive', function() {
|
||||
subject.stop();
|
||||
|
||||
this.sinon.spy(MockService, 'registerState');
|
||||
this.sinon.spy(MockService, 'unregisterState');
|
||||
|
||||
subject = new DialerAgent();
|
||||
subject.start();
|
||||
sinon.assert.calledOnce(MockService.registerState);
|
||||
sinon.assert.calledWith(MockService.registerState, 'onCall', subject);
|
||||
subject.stop();
|
||||
sinon.assert.calledOnce(MockService.unregisterState);
|
||||
sinon.assert.calledWith(MockService.unregisterState, 'onCall', subject);
|
||||
});
|
||||
});
|
||||
});
|
||||
100
gaia/apps/system/test/unit/download_icon_test.js
Executable file
100
gaia/apps/system/test/unit/download_icon_test.js
Executable file
|
|
@ -0,0 +1,100 @@
|
|||
/* global DownloadIcon */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/download_icon.js');
|
||||
|
||||
suite('system/DownloadIcon', function() {
|
||||
var subject, MockDownload;
|
||||
|
||||
setup(function() {
|
||||
MockDownload = {
|
||||
id: 'this-is-a-fake-uuid',
|
||||
pause: this.sinon.spy(),
|
||||
onstatechange: this.sinon.spy(),
|
||||
state: 'downloading'
|
||||
};
|
||||
subject = new DownloadIcon();
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Start a new download', function() {
|
||||
subject.handle(MockDownload);
|
||||
MockDownload.state = 'downloading';
|
||||
MockDownload.onstatechange({
|
||||
download: MockDownload
|
||||
});
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Stop the download', function() {
|
||||
subject.handle(MockDownload);
|
||||
MockDownload.state = 'downloading';
|
||||
MockDownload.onstatechange({
|
||||
download: MockDownload
|
||||
});
|
||||
|
||||
MockDownload.state = 'stopped';
|
||||
MockDownload.onstatechange({
|
||||
download: MockDownload
|
||||
});
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Finalize the download', function() {
|
||||
subject.handle(MockDownload);
|
||||
MockDownload.state = 'finalized';
|
||||
MockDownload.onstatechange({
|
||||
download: MockDownload
|
||||
});
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
|
||||
suite('Download count inc/dec', function() {
|
||||
test('incrementing should display the icon', function() {
|
||||
subject.incDownloads();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
test('incrementing then decrementing should not display the icon',
|
||||
function() {
|
||||
subject.incDownloads();
|
||||
subject.decDownloads();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
test('incrementing twice then decrementing once should display the icon',
|
||||
function() {
|
||||
subject.incDownloads();
|
||||
subject.incDownloads();
|
||||
subject.decDownloads();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
test('incrementing then decrementing twice should not display the icon',
|
||||
function() {
|
||||
subject.incDownloads();
|
||||
subject.decDownloads();
|
||||
subject.decDownloads();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
|
||||
/* JW: testing that we can't have a negative counter */
|
||||
// These tests are currently failing and have been
|
||||
// temporarily disabled as per Bug 838993.
|
||||
// They should be fixed and re-enabled as soon as possible as per
|
||||
// Bug 840500.
|
||||
test('incrementing then decrementing twice then incrementing should ' +
|
||||
'display the icon', function() {
|
||||
subject.incDownloads();
|
||||
subject.decDownloads();
|
||||
subject.decDownloads();
|
||||
subject.incDownloads();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
});
|
||||
});
|
||||
62
gaia/apps/system/test/unit/download_manager_test.js
Executable file
62
gaia/apps/system/test/unit/download_manager_test.js
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
/* global MocksHelper, MockDownloadNotification */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_navigator_moz_download_manager.js');
|
||||
requireApp('system/test/unit/mock_download_notification.js');
|
||||
requireApp('system/test/unit/mock_download_formatter.js');
|
||||
requireApp('system/test/unit/mock_notification_screen.js');
|
||||
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/download_icon.js');
|
||||
|
||||
requireApp('system/js/download/download_manager.js');
|
||||
|
||||
var mocksForDownloadManager = new MocksHelper([
|
||||
'DownloadNotification',
|
||||
'DownloadFormatter',
|
||||
'NotificationScreen',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/DownloadManager >', function() {
|
||||
|
||||
var mockDownload = {
|
||||
id: 'this-is-a-fake-uuid',
|
||||
pause: sinon.spy()
|
||||
};
|
||||
|
||||
mocksForDownloadManager.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(window, 'DownloadIcon');
|
||||
navigator.mozDownloadManager.ondownloadstart({
|
||||
download: mockDownload
|
||||
});
|
||||
});
|
||||
|
||||
test('Notification has been created successfully', function() {
|
||||
assert.equal(MockDownloadNotification.methodCalled, 'DownloadNotification');
|
||||
});
|
||||
|
||||
test('Notification has been clicked', function() {
|
||||
var event = new CustomEvent('notification-clicked', {
|
||||
detail: {
|
||||
id: mockDownload.id
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
|
||||
assert.equal(MockDownloadNotification.methodCalled, 'onClick');
|
||||
});
|
||||
|
||||
test('Pause when shutdown', function() {
|
||||
var event = new CustomEvent('will-shutdown');
|
||||
window.dispatchEvent(event);
|
||||
assert.isTrue(mockDownload.pause.called);
|
||||
});
|
||||
});
|
||||
286
gaia/apps/system/test/unit/download_notification_test.js
Executable file
286
gaia/apps/system/test/unit/download_notification_test.js
Executable file
|
|
@ -0,0 +1,286 @@
|
|||
/* global Download, DownloadFormatter, DownloadStore, DownloadNotification,
|
||||
DownloadHelper, DownloadUI, MocksHelper, MockL10n, NotificationScreen,
|
||||
mockMozActivityInstance */
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_download.js');
|
||||
requireApp('system/test/unit/mock_download_store.js');
|
||||
requireApp('system/test/unit/mock_download_ui.js');
|
||||
requireApp('system/test/unit/mock_download_formatter.js');
|
||||
requireApp('system/test/unit/mock_download_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/test/unit/mock_notification_screen.js');
|
||||
requireApp('system/test/unit/mock_activity.js');
|
||||
|
||||
requireApp('system/js/download/download_notification.js');
|
||||
|
||||
var mocksForDownloadNotification = new MocksHelper([
|
||||
'Download',
|
||||
'NotificationScreen',
|
||||
'L10n',
|
||||
'LazyLoader',
|
||||
'MozActivity',
|
||||
'DownloadHelper',
|
||||
'DownloadFormatter',
|
||||
'DownloadUI',
|
||||
'DownloadStore'
|
||||
]).init();
|
||||
|
||||
suite('system/DownloadNotification >', function() {
|
||||
var ERRORS = {
|
||||
NO_MEMORY: 2152857616,
|
||||
NO_SDCARD: 2152857618,
|
||||
UNMOUNTED_SDCARD: 2152857621
|
||||
};
|
||||
|
||||
var notification, realL10n, download, realOnLine, isOnLine;
|
||||
|
||||
function navigatorOnLine() {
|
||||
return isOnLine;
|
||||
}
|
||||
|
||||
function setNavigatorOnLine(value) {
|
||||
isOnLine = value;
|
||||
}
|
||||
|
||||
mocksForDownloadNotification.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
// This suite checks the life cycle of a download notification
|
||||
download = new Download();
|
||||
download.resume = function() {};
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
realOnLine = Object.getOwnPropertyDescriptor(navigator, 'onLine');
|
||||
Object.defineProperty(navigator, 'onLine', {
|
||||
configurable: true,
|
||||
get: navigatorOnLine,
|
||||
set: setNavigatorOnLine
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
if (realOnLine) {
|
||||
Object.defineProperty(navigator, 'onLine', realOnLine);
|
||||
}
|
||||
});
|
||||
|
||||
function assertUpdatedNotification(download, state) {
|
||||
assert.isTrue(NotificationScreen.addNotification.called);
|
||||
|
||||
var args = NotificationScreen.addNotification.args[0];
|
||||
var fileName = DownloadFormatter.getFileName(download);
|
||||
assert.isTrue(args[0].text.indexOf(fileName) !== -1);
|
||||
state = state || download.state;
|
||||
assert.equal(args[0].type, 'download-notification-' + state);
|
||||
}
|
||||
|
||||
suite('Download whole life cycle', function() {
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(NotificationScreen, 'addNotification');
|
||||
this.sinon.spy(DownloadStore, 'add');
|
||||
navigator.onLine = true;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
download.error = null;
|
||||
});
|
||||
|
||||
test('Download notification has been created', function() {
|
||||
notification = new DownloadNotification(download);
|
||||
assert.isTrue(NotificationScreen.addNotification.called);
|
||||
});
|
||||
|
||||
test('The download starts', function() {
|
||||
notification.state = 'started';
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'downloading';
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
|
||||
assert.isUndefined(
|
||||
NotificationScreen.addNotification.args[0][0].noNotify);
|
||||
});
|
||||
|
||||
test('The download continues', function() {
|
||||
notification.state = 'downloading';
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'downloading';
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
|
||||
assert.isTrue(
|
||||
NotificationScreen.addNotification.args[0][0].noNotify);
|
||||
});
|
||||
|
||||
test('The notification was clicked while downloading > Show download list',
|
||||
function() {
|
||||
notification.onClick();
|
||||
assert.equal(mockMozActivityInstance.name, 'configure');
|
||||
assert.equal(mockMozActivityInstance.data.target, 'device');
|
||||
assert.equal(mockMozActivityInstance.data.section, 'downloads');
|
||||
});
|
||||
|
||||
test('The download failed', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
download.error = {
|
||||
name: 'DownloadError'
|
||||
};
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download, 'failed');
|
||||
assert.equal(DownloadHelper.methodCalled, 'getFreeSpace');
|
||||
assert.isNull(DownloadUI.methodCalled);
|
||||
});
|
||||
|
||||
test('Failed notification was clicked > Show confirmation', function() {
|
||||
notification.onClick();
|
||||
assert.equal(DownloadUI.methodCalled, 'show');
|
||||
});
|
||||
|
||||
test('Download continues downloading', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'downloading';
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
|
||||
assert.isUndefined(
|
||||
NotificationScreen.addNotification.args[0][0].noNotify);
|
||||
});
|
||||
|
||||
test('Download was stopped by the user', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
});
|
||||
|
||||
test('Stopped notification was clicked > Show confirmation', function() {
|
||||
notification.onClick();
|
||||
assert.equal(DownloadUI.methodCalled, 'show');
|
||||
});
|
||||
|
||||
test('Download continues downloading', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'downloading';
|
||||
download.currentBytes = 300;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
|
||||
assert.isUndefined(
|
||||
NotificationScreen.addNotification.args[0][0].noNotify);
|
||||
});
|
||||
|
||||
test('The download failed because the SD card is missing', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
download.error = {
|
||||
name: 'DownloadError',
|
||||
message: ERRORS.NO_SDCARD
|
||||
};
|
||||
DownloadHelper.bytes = 0;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download, 'failed');
|
||||
assert.equal(DownloadUI.methodCalled, 'show');
|
||||
|
||||
// pretend like the user fixed the issue and move onto the next failure.
|
||||
download.state = 'downloading';
|
||||
download.currentBytes = 400;
|
||||
download.listeners[0]();
|
||||
});
|
||||
|
||||
test('The download failed because the SD card is busy', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
download.error = {
|
||||
name: 'DownloadError',
|
||||
message: ERRORS.UNMOUNTED_SDCARD
|
||||
};
|
||||
DownloadHelper.bytes = 0;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download, 'failed');
|
||||
assert.equal(DownloadUI.methodCalled, 'show');
|
||||
|
||||
// pretend like the user fixed the issue and move onto the next failure.
|
||||
download.state = 'downloading';
|
||||
download.currentBytes = 400;
|
||||
download.listeners[0]();
|
||||
});
|
||||
|
||||
test('The download failed because of no free memory', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
download.error = {
|
||||
name: 'DownloadError',
|
||||
message: ERRORS.NO_MEMORY
|
||||
};
|
||||
DownloadHelper.bytes = 0;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download, 'failed');
|
||||
assert.equal(DownloadUI.methodCalled, 'show');
|
||||
});
|
||||
|
||||
test('Download continues downloading', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'downloading';
|
||||
download.currentBytes = 400;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
|
||||
assert.isUndefined(
|
||||
NotificationScreen.addNotification.args[0][0].noNotify);
|
||||
});
|
||||
|
||||
test('Download was stopped because the connectivity was lost', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'stopped';
|
||||
navigator.onLine = false;
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download, 'downloading');
|
||||
});
|
||||
|
||||
test('Download finishes', function() {
|
||||
assert.isFalse(NotificationScreen.addNotification.called);
|
||||
download.state = 'succeeded';
|
||||
download.listeners[0]();
|
||||
assertUpdatedNotification(download);
|
||||
assert.ok(DownloadStore.add.calledOnce);
|
||||
});
|
||||
|
||||
test('Finished notification was clicked > Open file', function() {
|
||||
notification.onClick(function() {});
|
||||
assert.equal(DownloadHelper.methodCalled, 'open');
|
||||
|
||||
assert.isNull(notification.id);
|
||||
assert.isNull(notification.download);
|
||||
assert.isNull(notification.state);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Download removed from download list', function() {
|
||||
suiteSetup(function() {
|
||||
download.listeners = [];
|
||||
});
|
||||
|
||||
test('Download notification has been created ', function() {
|
||||
this.sinon.stub(NotificationScreen, 'addNotification');
|
||||
notification = new DownloadNotification(download);
|
||||
sinon.assert.called(NotificationScreen.addNotification);
|
||||
});
|
||||
|
||||
test('The download finalizes (download object is dead on the gecko side) ',
|
||||
function() {
|
||||
this.sinon.stub(NotificationScreen, 'removeNotification');
|
||||
download.state = 'finalized';
|
||||
download.listeners[0]();
|
||||
assert.isTrue(NotificationScreen.removeNotification.called,
|
||||
'Notification should not remain when download is finalized.');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
504
gaia/apps/system/test/unit/dynamic_input_registry_test.js
Executable file
504
gaia/apps/system/test/unit/dynamic_input_registry_test.js
Executable file
|
|
@ -0,0 +1,504 @@
|
|||
'use strict';
|
||||
|
||||
/* global DynamicInputRegistry, InputAppList, InputApp,
|
||||
MockNavigatorMozSettings, MockNavigatorMozSettingsLock,
|
||||
MockDOMRequest, MockEventTarget */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_event_target.js');
|
||||
require('/shared/test/unit/mocks/mock_dom_request.js');
|
||||
require('/shared/js/input_mgmt/mock_navigator_mozsettings.js');
|
||||
require('/shared/test/unit/mocks/mock_event_target.js');
|
||||
|
||||
require('/shared/js/input_mgmt/input_app_list.js');
|
||||
require('/js/dynamic_input_registry.js');
|
||||
|
||||
var MOCK_DOM_APP = {
|
||||
manifestURL: 'app://keyboard.gaiamobile.org/manifest.webapp',
|
||||
manifest: {
|
||||
role: 'input',
|
||||
type: 'certified',
|
||||
inputs: {
|
||||
en: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#en'
|
||||
},
|
||||
es: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#es'
|
||||
},
|
||||
number: {
|
||||
types: ['number'],
|
||||
launch_path: '/index.html#number'
|
||||
}
|
||||
},
|
||||
permissions: {
|
||||
input: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
suite('DynamicInputRegistry', function(){
|
||||
var realMozSettings;
|
||||
var realMozInputMethod;
|
||||
var lockGetStub;
|
||||
var lockSetStub;
|
||||
|
||||
var registry;
|
||||
|
||||
var domApp;
|
||||
var inputApp;
|
||||
|
||||
var getResult;
|
||||
var setResult;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
var mozSettings = navigator.mozSettings = new MockNavigatorMozSettings();
|
||||
navigator.mozInputMethod = {
|
||||
mgmt: new MockEventTarget()
|
||||
};
|
||||
|
||||
var createLockStub = this.sinon.stub(mozSettings, 'createLock');
|
||||
var lock = new MockNavigatorMozSettingsLock();
|
||||
|
||||
lockGetStub = this.sinon.stub(lock, 'get', function() {
|
||||
var req = new MockDOMRequest();
|
||||
Promise.resolve().then(function() {
|
||||
if ('result' in getResult) {
|
||||
req.fireSuccess(getResult.result);
|
||||
} else {
|
||||
req.fireError(getResult.error);
|
||||
}
|
||||
});
|
||||
return req;
|
||||
});
|
||||
lockSetStub = this.sinon.stub(lock, 'set', function() {
|
||||
var req = new MockDOMRequest();
|
||||
Promise.resolve().then(function() {
|
||||
if ('result' in setResult) {
|
||||
req.fireSuccess(setResult.result);
|
||||
} else {
|
||||
req.fireError(setResult.error);
|
||||
}
|
||||
});
|
||||
return req;
|
||||
});
|
||||
createLockStub.returns(lock);
|
||||
|
||||
this.sinon.spy(window, 'addEventListener');
|
||||
this.sinon.spy(window, 'removeEventListener');
|
||||
|
||||
domApp = Object.create(MOCK_DOM_APP);
|
||||
inputApp = new InputApp(domApp);
|
||||
|
||||
var stubInputAppList =
|
||||
this.sinon.stub(Object.create(InputAppList.prototype));
|
||||
stubInputAppList.getList.returns([ inputApp ]);
|
||||
window.KeyboardHelper = {
|
||||
inputAppList: stubInputAppList
|
||||
};
|
||||
|
||||
registry = new DynamicInputRegistry();
|
||||
registry.start();
|
||||
|
||||
registry.taskQueue.then(done, done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
registry.stop();
|
||||
|
||||
navigator.mozInputMethod = realMozInputMethod;
|
||||
});
|
||||
|
||||
suite('inputregistry-add', function() {
|
||||
test('add an input', function(done) {
|
||||
var evt = {
|
||||
type: 'addinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
inputManifest: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
},
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
assert.isTrue(evt.preventDefault.calledOnce);
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isTrue(lockSetStub.calledWith({
|
||||
'keyboard.dynamic-inputs': {
|
||||
'app://keyboard.gaiamobile.org/manifest.webapp': {
|
||||
foo: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(true, 'resolved');
|
||||
}, function(e) {
|
||||
throw e || 'Should not reject.';
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('fail to get settings', function(done) {
|
||||
var evt = {
|
||||
type: 'addinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
inputManifest: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
},
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
getResult = { error: 'Mocked Error' };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Error updating input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('fail to set settings', function(done) {
|
||||
var evt = {
|
||||
type: 'addinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
inputManifest: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
},
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { error: 'Mocked Error' };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Error updating input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('add an input for uninstalled app', function(done) {
|
||||
var evt = {
|
||||
type: 'addinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: 'app://myfunnykeyboard.org/manifest.webapp',
|
||||
inputId: 'foo',
|
||||
inputManifest: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
},
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'App not installed');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('add an input for static layout', function(done) {
|
||||
var evt = {
|
||||
type: 'addinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'en',
|
||||
inputManifest: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#en'
|
||||
},
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Can\'t mutate a statically declared input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('inputregistry-remove', function() {
|
||||
test('remove an input', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {
|
||||
'app://keyboard.gaiamobile.org/manifest.webapp': {
|
||||
foo: {
|
||||
types: ['url', 'text'],
|
||||
launch_path: '/index.html#foo'
|
||||
}
|
||||
}
|
||||
};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isTrue(lockSetStub.calledWith({
|
||||
'keyboard.dynamic-inputs': {}
|
||||
}));
|
||||
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(true, 'resolved');
|
||||
}, function(e) {
|
||||
throw e || 'Should not reject.';
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('remove an non-exist input', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo2',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {
|
||||
'app://keyboard.gaiamobile.org/manifest.webapp': {}
|
||||
};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isTrue(lockSetStub.calledWith({
|
||||
'keyboard.dynamic-inputs': {}
|
||||
}));
|
||||
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(true, 'resolved');
|
||||
}, function(e) {
|
||||
throw e || 'Should not reject.';
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('fail to get settings', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
getResult = { error: 'Mocked Error' };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Error updating input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('fail to set settings', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'foo',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { error: 'Mocked Error' };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Error updating input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('remove an input for uninstalled app', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: 'app://myfunnykeyboard.org/manifest.webapp',
|
||||
inputId: 'foo',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'App not installed');
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('remove an input for static layout', function(done) {
|
||||
var evt = {
|
||||
type: 'removeinputrequest',
|
||||
detail: {
|
||||
id: 1,
|
||||
manifestURL: domApp.manifestURL,
|
||||
inputId: 'en',
|
||||
waitUntil: this.sinon.stub()
|
||||
},
|
||||
preventDefault: this.sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozInputMethod.mgmt.dispatchEvent(evt);
|
||||
|
||||
var obj = {};
|
||||
obj[registry.SETTING_KEY] = {};
|
||||
getResult = { result: obj };
|
||||
setResult = { result: undefined };
|
||||
|
||||
registry.taskQueue.then(function() {
|
||||
assert.isFalse(lockSetStub.calledOnce);
|
||||
assert.isTrue(evt.detail.waitUntil.calledOnce);
|
||||
return evt.detail.waitUntil.firstCall.args[0];
|
||||
}).then(function(p) {
|
||||
assert.ok(false, 'Should not resolve.');
|
||||
}, function(e) {
|
||||
if (typeof e === 'object') { throw e; }
|
||||
assert.equal(e, 'Can\'t mutate a statically declared input.');
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
1135
gaia/apps/system/test/unit/edge_swipe_detector_test.js
Executable file
1135
gaia/apps/system/test/unit/edge_swipe_detector_test.js
Executable file
File diff suppressed because it is too large
Load diff
34
gaia/apps/system/test/unit/emergency_callback_icon_test.js
Executable file
34
gaia/apps/system/test/unit/emergency_callback_icon_test.js
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
/* global EmergencyCallbackIcon, MockEmergencyCallbackManager */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/emergency_callback_icon.js');
|
||||
requireApp('system/test/unit/mock_emergency_callback_manager.js');
|
||||
|
||||
suite('system/EmergencyCallbackIcon', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
subject = new EmergencyCallbackIcon(MockEmergencyCallbackManager);
|
||||
subject.start();
|
||||
subject.element = document.createElement('div');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Emergency callback is deactivated', function() {
|
||||
MockEmergencyCallbackManager.active = false;
|
||||
subject.update();
|
||||
assert.isFalse(subject.isVisible());
|
||||
});
|
||||
|
||||
test('Emergency callback is activated', function() {
|
||||
MockEmergencyCallbackManager.active = true;
|
||||
subject.update();
|
||||
assert.isTrue(subject.isVisible());
|
||||
});
|
||||
});
|
||||
102
gaia/apps/system/test/unit/emergency_callback_manager_test.js
Executable file
102
gaia/apps/system/test/unit/emergency_callback_manager_test.js
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
'use strict';
|
||||
/* global MockNavigatorMozMobileConnections, BaseModule,
|
||||
MocksHelper, MockLazyLoader, EmergencyCallbackIcon */
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/base_ui.js');
|
||||
requireApp('system/js/base_icon.js');
|
||||
requireApp('system/js/emergency_callback_icon.js');
|
||||
requireApp('system/js/emergency_callback_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
var mocksForEmergencyCallbackManager = new MocksHelper([
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/emergency_callback_manager', function() {
|
||||
var subject;
|
||||
mocksForEmergencyCallbackManager.attachTestHelpers();
|
||||
suiteSetup(function() {
|
||||
loadBodyHTML('/index.html');
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.spy(MockLazyLoader, 'load');
|
||||
subject = BaseModule.instantiate('EmergencyCallbackManager',
|
||||
{
|
||||
mobileConnections: MockNavigatorMozMobileConnections
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Should lazy load icon', function() {
|
||||
subject.start();
|
||||
assert.isTrue(MockLazyLoader.load.calledWith(
|
||||
['js/emergency_callback_icon.js']));
|
||||
});
|
||||
|
||||
suite('EmergencyCbManager init', function() {
|
||||
test('emergencycbmodechange registed while connections exists', function() {
|
||||
MockNavigatorMozMobileConnections[0].addEventListener =
|
||||
this.sinon.stub();
|
||||
subject.start();
|
||||
assert.ok(subject.notification);
|
||||
assert.ok(subject.message);
|
||||
assert.ok(subject.toaster);
|
||||
assert.ok(subject.toasterMessage);
|
||||
assert.ok(subject.okButton);
|
||||
assert.ok(subject.cancelButton);
|
||||
assert.ok(subject.cancelButton);
|
||||
sinon.assert.called(
|
||||
MockNavigatorMozMobileConnections[0].addEventListener);
|
||||
});
|
||||
});
|
||||
|
||||
suite('onEmergencyCbModeChange', function() {
|
||||
setup(function() {
|
||||
subject.publish = this.sinon.stub();
|
||||
this.sinon.useFakeTimers();
|
||||
subject.start();
|
||||
subject.icon = new EmergencyCallbackIcon(subject);
|
||||
this.sinon.stub(subject.icon, 'update');
|
||||
});
|
||||
|
||||
test('EmergencyCbMode changes to active with 1 min duration', function() {
|
||||
subject.onEmergencyCbModeChange({
|
||||
active: true,
|
||||
timeoutMs: 60 * 1000
|
||||
});
|
||||
|
||||
assert.equal(subject.timer, 60 * 1000);
|
||||
assert.ok(subject.timeoutController);
|
||||
assert.ok(subject._conn.ondataerror);
|
||||
assert.isTrue(subject.notification.classList.contains('displayed'));
|
||||
assert.isTrue(subject.toaster.classList.contains('displayed'));
|
||||
|
||||
// Toaster should hide after timeout
|
||||
this.sinon.clock.tick(subject.TOASTER_TIMEOUT + 1);
|
||||
assert.isFalse(subject.toaster.classList.contains('displayed'));
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
|
||||
// clear timeoutController after 1 min
|
||||
this.sinon.clock.tick(60 * 1000);
|
||||
assert.isNull(subject.timeoutController);
|
||||
});
|
||||
|
||||
test('EmergencyCbMode changes to inactive', function() {
|
||||
subject.onEmergencyCbModeChange({ active: false });
|
||||
assert.isFalse(subject.warningDialog.classList.contains('visible'));
|
||||
assert.isTrue(subject.warningDialog.hidden);
|
||||
assert.isNull(subject.timeoutController);
|
||||
assert.isNull(subject._conn.ondataerror);
|
||||
assert.isFalse(subject.notification.classList.contains('displayed'));
|
||||
assert.isTrue(subject.icon.update.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
14
gaia/apps/system/test/unit/entery_sheet_test.js
Executable file
14
gaia/apps/system/test/unit/entery_sheet_test.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
/* global EntrySheet */
|
||||
'use strict';
|
||||
|
||||
/* Unit test of entry_sheet.js */
|
||||
requireApp('system/js/entry_sheet.js');
|
||||
|
||||
suite('entry sheet class > ', function() {
|
||||
test('Simple entry sheet instance creation..', function() {
|
||||
var entrySheet =
|
||||
new EntrySheet(document.body, 'unit test', document.createElement('div'));
|
||||
assert.ok(entrySheet.hasOwnProperty('element'));
|
||||
});
|
||||
});
|
||||
|
||||
559
gaia/apps/system/test/unit/eu_roaming_manager_test.js
Executable file
559
gaia/apps/system/test/unit/eu_roaming_manager_test.js
Executable file
|
|
@ -0,0 +1,559 @@
|
|||
/* global BaseModule, Promise, Notification, MockSIMSlotManager,
|
||||
MockNotificationHelper */
|
||||
'use strict';
|
||||
|
||||
require('shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_notification_helper.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/eu_roaming_manager.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_simslot_manager.js');
|
||||
|
||||
suite('system/EuRoamingManager', function() {
|
||||
var realNotificationHelper;
|
||||
|
||||
setup(function() {
|
||||
realNotificationHelper = window.NotificationHelper;
|
||||
window.NotificationHelper = MockNotificationHelper;
|
||||
|
||||
this.fakeConnections = [{
|
||||
addEventListener: function() {},
|
||||
data: {
|
||||
connected: true
|
||||
}
|
||||
}];
|
||||
|
||||
this.euRoamingManager = BaseModule.instantiate('EuRoamingManager', {
|
||||
mobileConnections: this.fakeConnections
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.NotificationHelper = realNotificationHelper;
|
||||
navigator.mozMobileConnections = this.reallMobileConnections;
|
||||
});
|
||||
|
||||
suite('start', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(this.euRoamingManager, '_clearNotifications');
|
||||
this.sinon.stub(this.euRoamingManager, '_init');
|
||||
});
|
||||
|
||||
test('should clear notifications and init the module', function() {
|
||||
this.euRoamingManager.start();
|
||||
sinon.assert.called(this.euRoamingManager._clearNotifications);
|
||||
sinon.assert.called(this.euRoamingManager._init);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_init', function() {
|
||||
setup(function() {
|
||||
var that = this;
|
||||
this.mockEuRoamingFile = {
|
||||
home: {
|
||||
'000': {
|
||||
'11': true
|
||||
}
|
||||
},
|
||||
foreign: {
|
||||
'000': {
|
||||
'11': true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.sinon.stub(this.euRoamingManager, '_loadJSON', function() {
|
||||
return new Promise(function(resolve) {
|
||||
resolve(that.mockEuRoamingFile);
|
||||
});
|
||||
});
|
||||
this.sinon.stub(this.euRoamingManager, '_initValues');
|
||||
this.sinon.stub(this.euRoamingManager, '_addSimChangeListener');
|
||||
this.sinon.stub(this.euRoamingManager, '_addDataChangeListener');
|
||||
this.sinon.stub(this.euRoamingManager, '_tryShowEuRoamingNotification');
|
||||
});
|
||||
|
||||
test('should init operator lists properly', function(done) {
|
||||
this.mockEuRoamingFile = {
|
||||
home: {},
|
||||
foreign: {}
|
||||
};
|
||||
|
||||
this.euRoamingManager._init().then(function() {
|
||||
assert.equal(this.euRoamingManager._homeOperatorList,
|
||||
this.mockEuRoamingFile.home);
|
||||
assert.equal(this.euRoamingManager._foreignOperatorList,
|
||||
this.mockEuRoamingFile.foreign);
|
||||
}.bind(this), function() {
|
||||
// This function does not reject.
|
||||
assert.isTrue(false);
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('should init listeners properly and do an initial update when EU ' +
|
||||
'roaming operators are available', function(done) {
|
||||
this.euRoamingManager._init().then(function() {
|
||||
sinon.assert.calledOnce(this.euRoamingManager._initValues);
|
||||
sinon.assert.calledOnce(this.euRoamingManager._addSimChangeListener);
|
||||
sinon.assert.calledOnce(this.euRoamingManager._addDataChangeListener);
|
||||
this.fakeConnections.forEach(function(conn, index) {
|
||||
sinon.assert.calledWith(
|
||||
this.euRoamingManager._tryShowEuRoamingNotification, conn, index);
|
||||
}, this);
|
||||
}.bind(this), function() {
|
||||
// This function does not reject.
|
||||
assert.isTrue(false);
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('should not init listeners properly and do an initial update when ' +
|
||||
'EU roaming operators are unavailable', function(done) {
|
||||
this.mockEuRoamingFile = null;
|
||||
this.euRoamingManager._init().then(function() {
|
||||
sinon.assert.notCalled(this.euRoamingManager._initValues);
|
||||
sinon.assert.notCalled(this.euRoamingManager._addSimChangeListener);
|
||||
sinon.assert.notCalled(this.euRoamingManager._addDataChangeListener);
|
||||
sinon.assert.notCalled(
|
||||
this.euRoamingManager._tryShowEuRoamingNotification);
|
||||
}.bind(this), function() {
|
||||
// This function does not reject.
|
||||
assert.isTrue(false);
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_initValues', function() {
|
||||
suiteSetup(function() {
|
||||
this.fakeSlots = [{
|
||||
simCard: {
|
||||
iccInfo: {
|
||||
mcc: '000',
|
||||
mnc: '11'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
simCard: {
|
||||
iccInfo: null
|
||||
}
|
||||
}, {}];
|
||||
|
||||
this.realSIMSlotManager = window.SIMSlotManager;
|
||||
window.SIMSlotManager = MockSIMSlotManager;
|
||||
MockSIMSlotManager.mInstances = this.fakeSlots;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.SIMSlotManager = this.realSIMSlotManager;
|
||||
});
|
||||
|
||||
test('should init _simMobileCodes properly', function() {
|
||||
this.euRoamingManager._initValues();
|
||||
|
||||
assert.deepEqual(this.euRoamingManager._curNetworkMobileCodes,
|
||||
[null, null, null]);
|
||||
assert.deepEqual(this.euRoamingManager._simMobileCodes,
|
||||
[this.fakeSlots[0].simCard.iccInfo, null, null]);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_isEURoamingHomeOperator', function() {
|
||||
setup(function() {
|
||||
this.fakeHomeOperatorList = {
|
||||
'000': {
|
||||
'11': true
|
||||
}
|
||||
};
|
||||
this.euRoamingManager._homeOperatorList = this.fakeHomeOperatorList;
|
||||
});
|
||||
|
||||
test('should return true when the mcc and mnc are matched', function() {
|
||||
assert.isTrue(
|
||||
this.euRoamingManager._isEURoamingHomeOperator('000', '11'));
|
||||
});
|
||||
|
||||
test('should return false when the mcc and mnc are not matched',
|
||||
function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingHomeOperator('000', '22'));
|
||||
});
|
||||
|
||||
test('should return false when _homeOperatorList is not available',
|
||||
function() {
|
||||
this.euRoamingManager._homeOperatorList = null;
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingHomeOperator('000', '11'));
|
||||
});
|
||||
|
||||
test('should return false when mcc is not available', function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingHomeOperator(null, '11'));
|
||||
});
|
||||
|
||||
test('should return false when mnc is not available', function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingHomeOperator('000', null));
|
||||
});
|
||||
});
|
||||
|
||||
suite('_isEURoamingForeignOperator', function() {
|
||||
setup(function() {
|
||||
this.fakeForeignOperatorList = {
|
||||
'000': {
|
||||
'11': true
|
||||
}
|
||||
};
|
||||
this.euRoamingManager._foreignOperatorList = this.fakeForeignOperatorList;
|
||||
});
|
||||
|
||||
test('should return true when the mcc and mnc are matched', function() {
|
||||
assert.isTrue(
|
||||
this.euRoamingManager._isEURoamingForeignOperator('000', '11'));
|
||||
});
|
||||
|
||||
test('should return false when the mcc and mnc are not matched',
|
||||
function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingForeignOperator('000', '22'));
|
||||
});
|
||||
|
||||
test('should return false when _foreignOperatorList is not available',
|
||||
function() {
|
||||
this.euRoamingManager._foreignOperatorList = null;
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingForeignOperator('000', '11'));
|
||||
});
|
||||
|
||||
test('should return false when mcc is not available', function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingForeignOperator(null, '11'));
|
||||
});
|
||||
|
||||
test('should return false when mnc is not available', function() {
|
||||
assert.isFalse(
|
||||
this.euRoamingManager._isEURoamingForeignOperator('000', null));
|
||||
});
|
||||
});
|
||||
|
||||
suite('_addSimChangeListener', function() {
|
||||
test('listeners are added correctly', function() {
|
||||
this.sinon.stub(window, 'addEventListener');
|
||||
this.sinon.stub(this.euRoamingManager, '_onSimChanged');
|
||||
|
||||
this.euRoamingManager._addSimChangeListener();
|
||||
['updated', 'iccinfochange', 'cardstatechange'].forEach(
|
||||
function(eventName, index) {
|
||||
sinon.assert.calledWith(window.addEventListener,
|
||||
'simslot-' + eventName);
|
||||
window.addEventListener.args[index][1]();
|
||||
});
|
||||
assert.equal(this.euRoamingManager._onSimChanged.callCount, 3);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_addDataChangeListener', function() {
|
||||
test('listeners are added correctly', function() {
|
||||
this.fakeConnections.forEach(function(conn) {
|
||||
this.sinon.stub(conn, 'addEventListener');
|
||||
}, this);
|
||||
this.sinon.stub(this.euRoamingManager, '_tryShowEuRoamingNotification');
|
||||
|
||||
|
||||
this.euRoamingManager._addDataChangeListener();
|
||||
this.fakeConnections.forEach(function(conn, index) {
|
||||
sinon.assert.calledWith(conn.addEventListener, 'datachange');
|
||||
conn.addEventListener.args[index][1]();
|
||||
});
|
||||
assert.equal(
|
||||
this.euRoamingManager._tryShowEuRoamingNotification.callCount,
|
||||
this.fakeConnections.length);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_onSimChanged', function() {
|
||||
suiteSetup(function() {
|
||||
this.fakeSlots = [{
|
||||
index: 0,
|
||||
conn: {},
|
||||
simCard: {
|
||||
iccInfo: {
|
||||
mcc: '000',
|
||||
mnc: '11'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
index: 1,
|
||||
simCard: {
|
||||
iccInfo: null
|
||||
}
|
||||
}, {
|
||||
index: 2
|
||||
}];
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(this.euRoamingManager, '_tryShowEuRoamingNotification');
|
||||
});
|
||||
|
||||
test('should set _simMobileCodes and call to ' +
|
||||
'_tryShowEuRoamingNotification properly', function() {
|
||||
this.euRoamingManager._onSimChanged({
|
||||
detail: this.fakeSlots[0]
|
||||
});
|
||||
|
||||
assert.deepEqual(this.euRoamingManager._simMobileCodes[0],
|
||||
this.fakeSlots[0].simCard.iccInfo);
|
||||
sinon.assert.calledWith(
|
||||
this.euRoamingManager._tryShowEuRoamingNotification,
|
||||
this.fakeSlots[0].conn, this.fakeSlots[0].index);
|
||||
});
|
||||
|
||||
test('should not called to _tryShowEuRoamingNotification when iccInfo is ' +
|
||||
'not available', function() {
|
||||
// Use slots that have no iccInfo available.
|
||||
this.euRoamingManager._onSimChanged({
|
||||
detail: this.fakeSlots[1]
|
||||
});
|
||||
this.euRoamingManager._onSimChanged({
|
||||
detail: this.fakeSlots[2]
|
||||
});
|
||||
|
||||
sinon.assert.notCalled(
|
||||
this.euRoamingManager._tryShowEuRoamingNotification);
|
||||
});
|
||||
|
||||
test('should not change _simMobileCodes when iccInfo is not available',
|
||||
function() {
|
||||
var fakeMobileCodes = {};
|
||||
this.euRoamingManager._simMobileCodes = [fakeMobileCodes];
|
||||
// Use slots that have no iccInfo available.
|
||||
this.euRoamingManager._onSimChanged({});
|
||||
|
||||
assert.equal(this.euRoamingManager._simMobileCodes[0], fakeMobileCodes);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_tryShowEuRoamingNotification', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(this.euRoamingManager, '_isEURoamingHomeOperator');
|
||||
this.sinon.stub(this.euRoamingManager, '_isEURoamingForeignOperator');
|
||||
this.sinon.stub(this.euRoamingManager, '_getState', function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
this.sinon.stub(this.euRoamingManager, '_setState', function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
this.sinon.stub(this.euRoamingManager, '_showNotification');
|
||||
});
|
||||
|
||||
suite('when new network is detected', function() {
|
||||
setup(function() {
|
||||
this.targetIndex = 0;
|
||||
this.originalMobileCodes = { mcc: '000', mnc: '111' };
|
||||
this.currentMobileCodes = { mcc: '222', mnc: '333' };
|
||||
this.euRoamingManager._curNetworkMobileCodes[this.targetIndex] =
|
||||
this.originalMobileCodes;
|
||||
});
|
||||
|
||||
test('should update _curNetworkMobileCodes', function() {
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex);
|
||||
|
||||
assert.deepEqual(
|
||||
this.euRoamingManager._curNetworkMobileCodes[this.targetIndex],
|
||||
this.currentMobileCodes);
|
||||
});
|
||||
|
||||
suite('when the mobile codes are matched and roaming', function() {
|
||||
setup(function() {
|
||||
this.euRoamingManager._isEURoamingHomeOperator.restore();
|
||||
this.euRoamingManager._isEURoamingForeignOperator.restore();
|
||||
this.sinon.stub(this.euRoamingManager, '_isEURoamingHomeOperator')
|
||||
.returns(true);
|
||||
this.sinon.stub(this.euRoamingManager,
|
||||
'_isEURoamingForeignOperator').returns(true);
|
||||
});
|
||||
|
||||
test('should set the value under EU_ROAMING_ENABLED_KEY to true',
|
||||
function(done) {
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
roaming: true,
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex).then(function() {
|
||||
sinon.assert.calledWith(this.euRoamingManager._setState,
|
||||
this.euRoamingManager.EU_ROAMING_ENABLED_KEY + this.targetIndex,
|
||||
true);
|
||||
}.bind(this)).then(done, done);
|
||||
});
|
||||
|
||||
test('should show notification when the value under ' +
|
||||
'EU_ROAMING_NOTIFICATION_STATE_KEY is not NOTIFICATION_STATES.OPENED',
|
||||
function(done) {
|
||||
var that = this;
|
||||
this.euRoamingManager._getState.restore();
|
||||
this.sinon.stub(this.euRoamingManager, '_getState', function() {
|
||||
return Promise.resolve(
|
||||
that.euRoamingManager.NOTIFICATION_STATES.DISPLAYED);
|
||||
});
|
||||
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
roaming: true,
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex).then(function() {
|
||||
sinon.assert.called(this.euRoamingManager._showNotification);
|
||||
// Should also set the value to NOTIFICATION_STATES.DISPLAYED
|
||||
sinon.assert.calledWith(this.euRoamingManager._setState,
|
||||
this.euRoamingManager.EU_ROAMING_NOTIFICATION_STATE_KEY +
|
||||
this.targetIndex,
|
||||
this.euRoamingManager.NOTIFICATION_STATES.DISPLAYED);
|
||||
}.bind(this)).then(done, done);
|
||||
});
|
||||
|
||||
test('should not show notification when the value under ' +
|
||||
'EU_ROAMING_NOTIFICATION_STATE_KEY is NOTIFICATION_STATES.OPENED',
|
||||
function(done) {
|
||||
var that = this;
|
||||
this.euRoamingManager._getState.restore();
|
||||
this.sinon.stub(this.euRoamingManager, '_getState', function() {
|
||||
return Promise.resolve(
|
||||
that.euRoamingManager.NOTIFICATION_STATES.OPENED);
|
||||
});
|
||||
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
roaming: true,
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex).then(function() {
|
||||
sinon.assert.notCalled(this.euRoamingManager._showNotification);
|
||||
}.bind(this)).then(done, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('when the mobile codes are not matched or not roaming', function() {
|
||||
setup(function(done) {
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
roaming: false,
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex).then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should set the value under EU_ROAMING_ENABLED_KEY to false',
|
||||
function() {
|
||||
sinon.assert.calledWith(this.euRoamingManager._setState,
|
||||
this.euRoamingManager.EU_ROAMING_ENABLED_KEY + this.targetIndex,
|
||||
false);
|
||||
});
|
||||
|
||||
test('should set the value under EU_ROAMING_NOTIFICATION_STATE_KEY ' +
|
||||
' to NOTIFICATION_STATES.UNAVAILABLE',
|
||||
function() {
|
||||
sinon.assert.calledWith(this.euRoamingManager._setState,
|
||||
this.euRoamingManager.EU_ROAMING_NOTIFICATION_STATE_KEY +
|
||||
this.targetIndex,
|
||||
this.euRoamingManager.NOTIFICATION_STATES.UNAVAILABLE);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('when network is not changed', function() {
|
||||
setup(function() {
|
||||
this.targetIndex = 0;
|
||||
this.originalMobileCodes = { mcc: '000', mnc: '111' };
|
||||
this.currentMobileCodes = { mcc: '000', mnc: '111' };
|
||||
this.euRoamingManager._curNetworkMobileCodes[this.targetIndex] =
|
||||
this.originalMobileCodes;
|
||||
});
|
||||
|
||||
test('should not update _curNetworkMobileCodes', function() {
|
||||
this.euRoamingManager._tryShowEuRoamingNotification({
|
||||
data: {
|
||||
network: this.currentMobileCodes
|
||||
}
|
||||
}, this.targetIndex);
|
||||
|
||||
assert.equal(
|
||||
this.euRoamingManager._curNetworkMobileCodes[this.targetIndex],
|
||||
this.originalMobileCodes);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('_clearNotifications', function() {
|
||||
setup(function() {
|
||||
this.notificationOfEuRoaming = {
|
||||
tag: this.euRoamingManager.TAG_PREFIX + 'tag',
|
||||
close: sinon.spy()
|
||||
};
|
||||
this.notificationOfOthers = {
|
||||
tag: 'othertag',
|
||||
close: sinon.spy()
|
||||
};
|
||||
this.fakeNotifications = [
|
||||
this.notificationOfEuRoaming,
|
||||
this.notificationOfOthers
|
||||
];
|
||||
this.sinon.stub(Notification, 'get', function() {
|
||||
return Promise.resolve(this.fakeNotifications);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
test('should close notifications', function(done) {
|
||||
this.euRoamingManager._clearNotifications()
|
||||
.then(function() {
|
||||
sinon.assert.called(this.notificationOfEuRoaming.close);
|
||||
sinon.assert.notCalled(this.notificationOfOthers.close);
|
||||
}.bind(this), function() {
|
||||
// This function does not reject.
|
||||
assert.isTrue(false);
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_showNotification', function() {
|
||||
setup(function() {
|
||||
this.targetIndex = 0;
|
||||
this.sinon.spy(window.NotificationHelper, 'send');
|
||||
});
|
||||
|
||||
test('should show notification', function(done) {
|
||||
this.euRoamingManager._showNotification(this.targetIndex).then(
|
||||
() => {
|
||||
sinon.assert.calledWith(window.NotificationHelper.send,
|
||||
'euRoamingNotificationTitle');
|
||||
var notificationOption = window.NotificationHelper.send.args[0][1];
|
||||
assert.equal(notificationOption.tag,
|
||||
this.euRoamingManager.TAG_PREFIX + this.targetIndex);
|
||||
assert.equal(notificationOption.bodyL10n,
|
||||
'euRoamingNotificationMsg');
|
||||
assert.equal(notificationOption.mozbehavior.showOnlyOnce, true);
|
||||
}
|
||||
).then(done, done);
|
||||
});
|
||||
|
||||
test('should trigger settings activity when clicking on it',
|
||||
function(done) {
|
||||
this.sinon.stub(this.euRoamingManager, '_triggerSettingsActivity');
|
||||
|
||||
this.euRoamingManager._showNotification(this.targetIndex).then(
|
||||
notification => {
|
||||
notification.onclick();
|
||||
|
||||
sinon.assert.calledWith(
|
||||
this.euRoamingManager._triggerSettingsActivity,
|
||||
this.targetIndex);
|
||||
}
|
||||
).then(done,done);
|
||||
});
|
||||
});
|
||||
});
|
||||
685
gaia/apps/system/test/unit/external_storage_monitor_test.js
Executable file
685
gaia/apps/system/test/unit/external_storage_monitor_test.js
Executable file
|
|
@ -0,0 +1,685 @@
|
|||
'use strict';
|
||||
/* global ExternalStorageMonitor, MocksHelper, MockNotification, MockL10n,
|
||||
MockNotificationHelper, MockGetDeviceStorages, MockMozActivity,
|
||||
MockNavigatorSettings */
|
||||
|
||||
requireApp('system/js/external_storage_monitor.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_notification.js');
|
||||
require('/shared/test/unit/mocks/mock_notification_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_activity.js');
|
||||
require('/shared/test/unit/mocks/mock_event_target.js');
|
||||
require('/shared/test/unit/mocks/mock_dom_request.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_getdevicestorage.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_getdevicestorages.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
|
||||
var mocksForExternalStorageMonitor = new MocksHelper([
|
||||
'MozActivity'
|
||||
]).init();
|
||||
|
||||
/**
|
||||
* Test ExternalStorageMonitor functionality.
|
||||
*/
|
||||
suite('system/ExternalStorageMonitor', function() {
|
||||
|
||||
var realL10n;
|
||||
var realNotification;
|
||||
var realNotificationHelper;
|
||||
var realNavigatorGetDeviceStorages;
|
||||
var realMozActivity;
|
||||
var realMozSettings;
|
||||
|
||||
var externalStorageMonitor;
|
||||
|
||||
mocksForExternalStorageMonitor.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
realNotification = window.Notification;
|
||||
window.Notification = MockNotification;
|
||||
|
||||
realNotificationHelper = window.NotificationHelper;
|
||||
window.NotificationHelper = MockNotificationHelper;
|
||||
|
||||
realNavigatorGetDeviceStorages = navigator.getDeviceStorages;
|
||||
navigator.getDeviceStorages = MockGetDeviceStorages;
|
||||
|
||||
realMozActivity = window.MozActivity;
|
||||
window.MozActivity = MockMozActivity;
|
||||
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
externalStorageMonitor = new ExternalStorageMonitor();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
window.Notification = realNotification;
|
||||
window.NotificationHelper = realNotificationHelper;
|
||||
navigator.getDeviceStorages = realNavigatorGetDeviceStorages;
|
||||
window.MozActivity = realMozActivity;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
MockNavigatorSettings.mTeardown();
|
||||
});
|
||||
|
||||
suite('new > ', function() {
|
||||
var spyGetDeviceStorages, tempExternalStorageMonitor;
|
||||
setup(function() {
|
||||
spyGetDeviceStorages = this.sinon.spy(navigator, 'getDeviceStorages');
|
||||
tempExternalStorageMonitor = new ExternalStorageMonitor();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
tempExternalStorageMonitor = null;
|
||||
});
|
||||
|
||||
test('call getDeviceStorages, store _storage..', function() {
|
||||
assert.isTrue(spyGetDeviceStorages.calledWith('sdcard'),
|
||||
'getDeviceStorages should be called with sdcard');
|
||||
assert.isDefined(externalStorageMonitor._storage,
|
||||
'this._storage should be defined');
|
||||
});
|
||||
});
|
||||
|
||||
suite('start > ', function() {
|
||||
suite('has external storage > ', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
this.sinon.spy(externalStorageMonitor._storage, 'storageStatus');
|
||||
this.sinon.stub(externalStorageMonitor._storage, 'addEventListener');
|
||||
externalStorageMonitor.start();
|
||||
});
|
||||
|
||||
test('will addEventListener with "storage-state-change" ' +
|
||||
'get storage status success..', function() {
|
||||
var req =
|
||||
externalStorageMonitor._storage.storageStatus.getCall(0).returnValue;
|
||||
req.fireSuccess('');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor._storage.addEventListener.calledWith(
|
||||
'storage-state-change'),
|
||||
'event "storage-state-change" should be listened');
|
||||
});
|
||||
|
||||
test('will addEventListener with "storage-state-change" ' +
|
||||
'get storage status fail..', function() {
|
||||
var req =
|
||||
externalStorageMonitor._storage.storageStatus.getCall(0).returnValue;
|
||||
req.fireError();
|
||||
assert.isTrue(
|
||||
externalStorageMonitor._storage.addEventListener.calledWith(
|
||||
'storage-state-change'),
|
||||
'event "storage-state-change" should be listened');
|
||||
});
|
||||
|
||||
test('will call enableStorageUnrecognised', function() {
|
||||
var req =
|
||||
externalStorageMonitor._storage.storageStatus.getCall(0).returnValue;
|
||||
req.fireSuccess('Idle');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(false),
|
||||
'with false');
|
||||
});
|
||||
|
||||
test('will call enableStorageUnrecognised', function() {
|
||||
var req =
|
||||
externalStorageMonitor._storage.storageStatus.getCall(0).returnValue;
|
||||
req.fireSuccess('Mount-Fail');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(true),
|
||||
'with true');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('pushStatus > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.pushStatus('Mounted');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('status stack is pushed..', function() {
|
||||
assert.equal(externalStorageMonitor.statusStack.length, 1,
|
||||
'should be one status in stack');
|
||||
assert.equal(externalStorageMonitor.statusStack[0], 4,
|
||||
'first element should be "Mounted" status "4" in stack');
|
||||
});
|
||||
});
|
||||
|
||||
suite('clearStatus > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [4, 5];
|
||||
externalStorageMonitor.clearStatus();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('status stack is cleared, keep the latest storage status in stack ..',
|
||||
function() {
|
||||
assert.equal(externalStorageMonitor.statusStack.length, 1,
|
||||
'should keep one status only');
|
||||
assert.equal(externalStorageMonitor.statusStack[0], 5,
|
||||
'should keep latest status');
|
||||
});
|
||||
});
|
||||
|
||||
suite('enableEnterIdleStateTimer > ', function() {
|
||||
var fakeTimer;
|
||||
setup(function() {
|
||||
fakeTimer = this.sinon.useFakeTimers();
|
||||
externalStorageMonitor.justEnterIdleLessThanOneSecond = false;
|
||||
externalStorageMonitor.enableEnterIdleStateTimer();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fakeTimer.restore();
|
||||
externalStorageMonitor.justEnterIdleLessThanOneSecond = false;
|
||||
externalStorageMonitor.resetJustEnterIdleFlagTimer = null;
|
||||
});
|
||||
|
||||
test('enable flag "justEnterIdleLessThanOneSecond", ' +
|
||||
'then reset it after 1 second..', function() {
|
||||
assert.isTrue(externalStorageMonitor.justEnterIdleLessThanOneSecond,
|
||||
'flag "justEnterIdleLessThanOneSecond" should be true');
|
||||
fakeTimer.tick(1000);
|
||||
assert.isFalse(externalStorageMonitor.justEnterIdleLessThanOneSecond,
|
||||
'flag "justEnterIdleLessThanOneSecond" should be reset to false');
|
||||
});
|
||||
});
|
||||
|
||||
suite('recogniseStorageActions > ', function() {
|
||||
suite('action: Recognised > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [0, 2, 1, 3, 4];
|
||||
this.sinon.stub(externalStorageMonitor, 'clearStatus');
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
this.sinon.stub(externalStorageMonitor, 'createMessage');
|
||||
externalStorageMonitor.recogniseStorageActions();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('match "Recognised"..', function() {
|
||||
assert.isTrue(externalStorageMonitor.clearStatus.called,
|
||||
'clearStatus() should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(false),
|
||||
'enableStorageUnrecognised() should be called with "false"');
|
||||
assert.isTrue(externalStorageMonitor.createMessage.calledWith(
|
||||
'detected-recognised'),
|
||||
'createMessage() should be called with "detected-recognised"');
|
||||
});
|
||||
});
|
||||
|
||||
suite('action: Unrecognised > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [0, 1, 3, 9];
|
||||
this.sinon.stub(externalStorageMonitor, 'clearStatus');
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
this.sinon.stub(externalStorageMonitor, 'createMessage');
|
||||
externalStorageMonitor.recogniseStorageActions();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('match "Unrecognised"..', function() {
|
||||
assert.isTrue(externalStorageMonitor.clearStatus.called,
|
||||
'clearStatus() should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(true),
|
||||
'enableStorageUnrecognised() should be called with "true"');
|
||||
assert.isTrue(externalStorageMonitor.createMessage.calledWith(
|
||||
'detected-unrecognised'),
|
||||
'createMessage() should be called with "detected-unrecognised"');
|
||||
});
|
||||
});
|
||||
|
||||
suite('action: Removed > ', function() {
|
||||
suite('in case of "normally-removed" > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [4, 5, 1, 0];
|
||||
externalStorageMonitor.justEnterIdleLessThanOneSecond = false;
|
||||
this.sinon.stub(externalStorageMonitor, 'clearStatus');
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
this.sinon.stub(externalStorageMonitor, 'createMessage');
|
||||
externalStorageMonitor.recogniseStorageActions();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('match "Removed"..', function() {
|
||||
assert.isTrue(externalStorageMonitor.clearStatus.called,
|
||||
'clearStatus() should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(false),
|
||||
'enableStorageUnrecognised() should be called with "false"');
|
||||
assert.isTrue(externalStorageMonitor.createMessage.calledWith(
|
||||
'normally-removed'),
|
||||
'createMessage() should be called with "normally-removed"');
|
||||
});
|
||||
});
|
||||
|
||||
suite('in case of "unexpectedly-removed" > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [4, 5, 1, 0];
|
||||
externalStorageMonitor.justEnterIdleLessThanOneSecond = true;
|
||||
this.sinon.stub(externalStorageMonitor, 'clearStatus');
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
this.sinon.stub(externalStorageMonitor, 'createMessage');
|
||||
externalStorageMonitor.recogniseStorageActions();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('match "Removed"..', function() {
|
||||
assert.isTrue(externalStorageMonitor.clearStatus.called,
|
||||
'clearStatus() should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(false),
|
||||
'enableStorageUnrecognised() should be called with "false"');
|
||||
assert.isTrue(externalStorageMonitor.createMessage.calledWith(
|
||||
'unexpectedly-removed'),
|
||||
'createMessage() should be called with "unexpectedly-removed"');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('action: UnrecognisedStorageRemoved > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.statusStack = [9, 0];
|
||||
this.sinon.stub(externalStorageMonitor, 'clearStatus');
|
||||
this.sinon.stub(externalStorageMonitor, 'enableStorageUnrecognised');
|
||||
externalStorageMonitor.recogniseStorageActions();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
externalStorageMonitor.statusStack = [];
|
||||
});
|
||||
|
||||
test('match "UnrecognisedStorageRemoved"..', function() {
|
||||
assert.isTrue(externalStorageMonitor.clearStatus.called,
|
||||
'clearStatus() should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableStorageUnrecognised.calledWith(false),
|
||||
'enableStorageUnrecognised() should be called with "false"');
|
||||
});
|
||||
});
|
||||
|
||||
suite('createMessage > ', function() {
|
||||
suite('case: "detected-recognised" > ', function() {
|
||||
var stubGetTotalSpace, fakeTotalSpace;
|
||||
setup(function() {
|
||||
fakeTotalSpace = {
|
||||
size: '7.2',
|
||||
unit: 'GB'
|
||||
};
|
||||
stubGetTotalSpace = this.sinon.stub(externalStorageMonitor,
|
||||
'getTotalSpace');
|
||||
this.sinon.stub(externalStorageMonitor, 'fireNotification');
|
||||
externalStorageMonitor.createMessage('detected-recognised');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubGetTotalSpace.restore();
|
||||
});
|
||||
|
||||
test('fireNotification() should be called ' +
|
||||
'after got total space..', function() {
|
||||
assert.isTrue(stubGetTotalSpace.called);
|
||||
var gotTotalSpaceCallback = stubGetTotalSpace.getCall(0).args[0];
|
||||
gotTotalSpaceCallback(fakeTotalSpace);
|
||||
var titleL10n = 'sdcard-detected-title';
|
||||
var bodyL10n = {
|
||||
id: 'sdcard-total-size-body',
|
||||
args: {
|
||||
size: fakeTotalSpace.size,
|
||||
unit: fakeTotalSpace.unit
|
||||
}
|
||||
};
|
||||
assert.isTrue(externalStorageMonitor.fireNotification.calledWith(
|
||||
titleL10n, bodyL10n, true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('case: "detected-unrecognised" > ', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'fireNotification');
|
||||
externalStorageMonitor.createMessage('detected-unrecognised');
|
||||
});
|
||||
|
||||
test('fireNotification() should be called with three args', function() {
|
||||
var title = 'sdcard-detected-title';
|
||||
var body = 'sdcard-unknown-size-then-tap-to-format-body';
|
||||
assert.isTrue(externalStorageMonitor.fireNotification.calledWith(
|
||||
title, body, true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('case: "normally-removed" > ', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'fireNotification');
|
||||
externalStorageMonitor.createMessage('normally-removed');
|
||||
});
|
||||
|
||||
test('fireNotification() should be called with two args', function() {
|
||||
var title = 'sdcard-removed-title';
|
||||
var body = 'sdcard-removed-ejected-successfully';
|
||||
assert.isTrue(externalStorageMonitor.fireNotification.calledWith(
|
||||
title, body));
|
||||
});
|
||||
});
|
||||
|
||||
suite('case: "unexpectedly-removed" > ', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'fireNotification');
|
||||
externalStorageMonitor.createMessage('unexpectedly-removed');
|
||||
});
|
||||
|
||||
test('fireNotification() should be called with two args', function() {
|
||||
var title = 'sdcard-removed-title';
|
||||
var body = 'sdcard-removed-not-ejected-properly';
|
||||
assert.isTrue(externalStorageMonitor.fireNotification.calledWith(
|
||||
title, body));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('enableStorageUnrecognised > ', function() {
|
||||
setup(function() {
|
||||
externalStorageMonitor.enableStorageUnrecognised(true);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete MockNavigatorSettings.mSettings['volume.external.unrecognised'];
|
||||
});
|
||||
|
||||
test('settings key "volume.external.unrecognised" should be set ' +
|
||||
'after enableStorageUnrecognised() called.. ', function() {
|
||||
assert.isTrue(
|
||||
MockNavigatorSettings.mSettings['volume.external.unrecognised'],
|
||||
'settings key "volume.external.unrecognised" should be true');
|
||||
});
|
||||
});
|
||||
|
||||
suite('fireNotification > ', function() {
|
||||
var notificationSpy, title, body, openSettings;
|
||||
setup(function() {
|
||||
notificationSpy = this.sinon.spy(window.NotificationHelper, 'send');
|
||||
title = 'SD card removed';
|
||||
body = 'SD card removed eject successfully';
|
||||
openSettings = true;
|
||||
externalStorageMonitor.fireNotification(title, body, openSettings);
|
||||
});
|
||||
|
||||
test('new and fired one notification, set notification ' +
|
||||
'onclick handler ', function() {
|
||||
assert.isTrue(notificationSpy.calledOnce,
|
||||
'Notification should be called');
|
||||
assert.equal(notificationSpy.firstCall.args[0], title,
|
||||
'Notification should be called with correct title');
|
||||
assert.equal(notificationSpy.firstCall.args[1].body, body,
|
||||
'Notification should be called with correct body');
|
||||
});
|
||||
});
|
||||
|
||||
suite('notificationHandler > ', function() {
|
||||
suite('no need to openSettings > ', function() {
|
||||
var mockNotification, stubMockNotification, mozActivitySpy;
|
||||
setup(function() {
|
||||
mockNotification = {
|
||||
close: function() {}
|
||||
};
|
||||
stubMockNotification = this.sinon.stub(mockNotification, 'close');
|
||||
mozActivitySpy = this.sinon.stub(window, 'MozActivity');
|
||||
externalStorageMonitor.notificationHandler(mockNotification, false);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubMockNotification.restore();
|
||||
mozActivitySpy.restore();
|
||||
});
|
||||
|
||||
test('close notification and do early return..', function() {
|
||||
assert.isTrue(stubMockNotification.called,
|
||||
'notification.close() should be called');
|
||||
assert.isFalse(mozActivitySpy.called,
|
||||
'MozActivity should not be called');
|
||||
});
|
||||
});
|
||||
|
||||
suite('will request MozActivity with "configure" > ', function() {
|
||||
var mockNotification, stubMockNotification;
|
||||
setup(function() {
|
||||
MockMozActivity.mSetup();
|
||||
mockNotification = {
|
||||
close: function() {}
|
||||
};
|
||||
stubMockNotification = this.sinon.stub(mockNotification, 'close');
|
||||
externalStorageMonitor.notificationHandler(mockNotification, true);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockMozActivity.mTeardown();
|
||||
});
|
||||
|
||||
test('close notification and new MozActivity with ' +
|
||||
'"configure"', function() {
|
||||
assert.isTrue(stubMockNotification.called,
|
||||
'notification.close() should be called');
|
||||
var activity = MockMozActivity.calls[0];
|
||||
assert.deepEqual(activity, {
|
||||
name: 'configure',
|
||||
data: {
|
||||
target: 'device',
|
||||
section: 'mediaStorage'
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('handleEvent > ', function() {
|
||||
suite('"storage-state-change" event coming, status is not "Idle"',
|
||||
function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'pushStatus');
|
||||
this.sinon.stub(externalStorageMonitor,
|
||||
'enableEnterIdleStateTimer');
|
||||
this.sinon.stub(externalStorageMonitor, 'recogniseStorageActions');
|
||||
|
||||
var event = {
|
||||
type: 'storage-state-change',
|
||||
reason: 'Mounted'
|
||||
};
|
||||
|
||||
externalStorageMonitor.handleEvent(event);
|
||||
});
|
||||
|
||||
test('pushStatus(), recogniseStorageActions() should be called..',
|
||||
function() {
|
||||
assert.isTrue(externalStorageMonitor.pushStatus.called,
|
||||
'pushStatus should be called');
|
||||
assert.isFalse(
|
||||
externalStorageMonitor.enableEnterIdleStateTimer.called,
|
||||
'enableEnterIdleStateTimer should not be called');
|
||||
assert.isTrue(externalStorageMonitor.recogniseStorageActions.called,
|
||||
'recogniseStorageActions should be called');
|
||||
});
|
||||
});
|
||||
|
||||
suite('"storage-state-change" event coming, status is "Idle"',
|
||||
function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(externalStorageMonitor, 'pushStatus');
|
||||
this.sinon.stub(externalStorageMonitor,
|
||||
'enableEnterIdleStateTimer');
|
||||
this.sinon.stub(externalStorageMonitor, 'recogniseStorageActions');
|
||||
|
||||
var event = {
|
||||
type: 'storage-state-change',
|
||||
reason: 'Idle'
|
||||
};
|
||||
|
||||
externalStorageMonitor.handleEvent(event);
|
||||
});
|
||||
|
||||
test('pushStatus(), enableEnterIdleStateTimer(), ' +
|
||||
'recogniseStorageActions() should be called..', function() {
|
||||
assert.isTrue(externalStorageMonitor.pushStatus.called,
|
||||
'pushStatus should be called');
|
||||
assert.isTrue(
|
||||
externalStorageMonitor.enableEnterIdleStateTimer.called,
|
||||
'enableEnterIdleStateTimer should be called');
|
||||
assert.isTrue(externalStorageMonitor.recogniseStorageActions.called,
|
||||
'recogniseStorageActions should be called');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getTotalSpace > ', function() {
|
||||
var callback;
|
||||
setup(function() {
|
||||
callback = this.sinon.stub();
|
||||
var storages = MockGetDeviceStorages('sdcard');
|
||||
externalStorageMonitor._storage = storages[0];
|
||||
this.sinon.spy(externalStorageMonitor._storage, 'usedSpace');
|
||||
this.sinon.spy(externalStorageMonitor._storage, 'freeSpace');
|
||||
this.sinon.stub(externalStorageMonitor, 'formatSize').returns(400);
|
||||
externalStorageMonitor.getTotalSpace(callback);
|
||||
});
|
||||
|
||||
test('callback function should be called with total space', function() {
|
||||
assert.isTrue(externalStorageMonitor._storage.usedSpace.called,
|
||||
'usedSpace() should be called');
|
||||
var req =
|
||||
externalStorageMonitor._storage.usedSpace.getCall(0).returnValue;
|
||||
req.fireSuccess(100);
|
||||
|
||||
assert.isTrue(externalStorageMonitor._storage.freeSpace.called,
|
||||
'freeSpace() should be called');
|
||||
var req2 =
|
||||
externalStorageMonitor._storage.freeSpace.getCall(0).returnValue;
|
||||
req2.fireSuccess(300);
|
||||
|
||||
assert.isTrue(externalStorageMonitor.formatSize.calledWith(400));
|
||||
assert.isTrue(callback.calledWith(400));
|
||||
});
|
||||
});
|
||||
|
||||
suite('formatSize > ', function() {
|
||||
test('empty size', function() {
|
||||
assert.equal(externalStorageMonitor.formatSize(), undefined);
|
||||
});
|
||||
|
||||
test('NaN', function() {
|
||||
assert.equal(externalStorageMonitor.formatSize('NaN'), undefined);
|
||||
});
|
||||
|
||||
test('bytes', function() {
|
||||
var result = externalStorageMonitor.formatSize(1);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-B');
|
||||
});
|
||||
|
||||
test('KB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('KB with decimal (round down)', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 + 511);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('KB with decimal (round up)', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 + 512);
|
||||
assert.equal(result.size, 2);
|
||||
assert.equal(result.unit, 'byteUnit-KB');
|
||||
});
|
||||
|
||||
test('MB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('MB with decimal (lower than 1K)', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024 + 512);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('MB with decimal (0.5MB)', function() {
|
||||
var result =
|
||||
externalStorageMonitor.formatSize(1024 * 1024 + 512 * 1024);
|
||||
assert.equal(result.size, 1.5);
|
||||
assert.equal(result.unit, 'byteUnit-MB');
|
||||
});
|
||||
|
||||
test('GB', function() {
|
||||
var result =
|
||||
externalStorageMonitor.formatSize(1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-GB');
|
||||
});
|
||||
|
||||
test('TB', function() {
|
||||
var result =
|
||||
externalStorageMonitor.formatSize(1024 * 1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-TB');
|
||||
});
|
||||
|
||||
test('PB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024 * 1024 *
|
||||
1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-PB');
|
||||
});
|
||||
|
||||
test('EB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024 * 1024 *
|
||||
1024 * 1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-EB');
|
||||
});
|
||||
|
||||
test('ZB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024 * 1024 *
|
||||
1024 * 1024 * 1024 *
|
||||
1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-ZB');
|
||||
});
|
||||
|
||||
test('YB', function() {
|
||||
var result = externalStorageMonitor.formatSize(1024 * 1024 * 1024 *
|
||||
1024 * 1024 * 1024 *
|
||||
1024 * 1024);
|
||||
assert.equal(result.size, 1);
|
||||
assert.equal(result.unit, 'byteUnit-YB');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
29
gaia/apps/system/test/unit/feature_detector_test.js
Executable file
29
gaia/apps/system/test/unit/feature_detector_test.js
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
/* global BaseModule */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/feature_detector.js');
|
||||
|
||||
suite('system/FeatureDetector', function() {
|
||||
var subject;
|
||||
|
||||
setup(function() {
|
||||
var getFeaturePromise = Promise.resolve(768);
|
||||
navigator.getFeature = this.sinon.stub().returns(getFeaturePromise);
|
||||
|
||||
subject = BaseModule.instantiate('FeatureDetector');
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
test('Hardware memory is correctly retrieved', function(done) {
|
||||
assert.isTrue(navigator.getFeature.calledWith('hardware.memory'));
|
||||
subject.getDeviceMemory().then(function(mem) {
|
||||
assert.equal(mem, 768);
|
||||
}).then(done, done);
|
||||
});
|
||||
});
|
||||
305
gaia/apps/system/test/unit/findmydevice_launcher_test.js
Executable file
305
gaia/apps/system/test/unit/findmydevice_launcher_test.js
Executable file
|
|
@ -0,0 +1,305 @@
|
|||
/* global FMDNotificationsHandler,
|
||||
MocksHelper,
|
||||
MockL10n,
|
||||
MockMozActivity,
|
||||
MockNavigatormozSetMessageHandler,
|
||||
MockNavigatorSettings,
|
||||
MockNotificationHelper,
|
||||
MockService,
|
||||
MockSettingsHelper,
|
||||
IAC_API_WAKEUP_REASON_LOGIN,
|
||||
IAC_API_WAKEUP_REASON_LOGOUT,
|
||||
IAC_API_WAKEUP_REASON_STALE_REGISTRATION,
|
||||
IAC_API_WAKEUP_REASON_ENABLED_CHANGED,
|
||||
IAC_API_WAKEUP_REASON_LOCKSCREEN_CLOSED,
|
||||
FMDInit
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_activity.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_dump.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_set_message_handler.js');
|
||||
require('/shared/test/unit/mocks/mock_service.js');
|
||||
require('/shared/js/findmydevice_iac_api.js');
|
||||
require('/shared/test/unit/mocks/mock_notification_helper.js');
|
||||
|
||||
const FMD_RETRIES = 5;
|
||||
const FMD_TAG = 'findmydevice.enable-failed';
|
||||
|
||||
var mocksForFindMyDevice = new MocksHelper([
|
||||
'Dump', 'SettingsHelper', 'MozActivity', 'Service'
|
||||
]).init();
|
||||
|
||||
suite('FindMyDevice Launcher >', function() {
|
||||
var realMozSettings;
|
||||
var realMozL10n;
|
||||
var realMozSetMessageHandler;
|
||||
var realNotificationHelper;
|
||||
|
||||
mocksForFindMyDevice.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
realMozL10n = navigator.mozL10n;
|
||||
realMozSetMessageHandler = navigator.mozSetMessageHandler;
|
||||
realNotificationHelper = window.NotificationHelper;
|
||||
window.NotificationHelper = MockNotificationHelper;
|
||||
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
|
||||
MockMozActivity.mSetup();
|
||||
|
||||
navigator.mozSetMessageHandler = MockNavigatormozSetMessageHandler;
|
||||
MockNavigatormozSetMessageHandler.mSetup();
|
||||
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
navigator.mozL10n = realMozL10n;
|
||||
window.NotificationHelper = realNotificationHelper;
|
||||
navigator.mozSetMessageHandler = realMozSetMessageHandler;
|
||||
MockNavigatorSettings.mTeardown();
|
||||
MockNavigatormozSetMessageHandler.mTeardown();
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
MockNavigatorSettings.mSetup();
|
||||
require('/js/findmydevice_launcher.js', (function() {
|
||||
FMDInit();
|
||||
this.sinon.stub(window, 'wakeUpFindMyDevice');
|
||||
done();
|
||||
}).bind(this));
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockNavigatorSettings.mTeardown();
|
||||
});
|
||||
|
||||
test('send ENABLED_CHANGED wakeup message when enabled', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.enabled',
|
||||
{settingValue: true});
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_ENABLED_CHANGED);
|
||||
});
|
||||
|
||||
test('send ENABLED_CHANGED wakeup message when disabled', function() {
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.enabled',
|
||||
{settingValue: false});
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_ENABLED_CHANGED);
|
||||
});
|
||||
|
||||
test('send STALE_REGISTRATION wakeup message when geolocation is enabled',
|
||||
function() {
|
||||
MockNavigatorSettings.mTriggerObservers('geolocation.enabled',
|
||||
{settingValue: true});
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_STALE_REGISTRATION);
|
||||
});
|
||||
|
||||
test('send STALE_REGISTRATION wakeup message when geolocation is disabled',
|
||||
function() {
|
||||
MockNavigatorSettings.mTriggerObservers('geolocation.enabled',
|
||||
{settingValue: false});
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_STALE_REGISTRATION);
|
||||
});
|
||||
|
||||
test('Notification appears only when FMD retry count >= limit', function() {
|
||||
var notificationSpy = this.sinon.spy(window.NotificationHelper, 'send');
|
||||
|
||||
// try a retry count less than the limit
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.retry-count',
|
||||
{settingValue: FMD_RETRIES - 1});
|
||||
sinon.assert.callCount(notificationSpy, 0);
|
||||
|
||||
// equal to the limit
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.retry-count',
|
||||
{settingValue: FMD_RETRIES});
|
||||
sinon.assert.callCount(notificationSpy, 1);
|
||||
|
||||
// greater than the limit
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.retry-count',
|
||||
{settingValue: FMD_RETRIES + 1});
|
||||
sinon.assert.callCount(notificationSpy, 2);
|
||||
|
||||
assert.equal(notificationSpy.firstCall.args[0], 'unable-to-connect');
|
||||
|
||||
var options = notificationSpy.firstCall.args[1];
|
||||
assert.equal(options.icon, 'style/find_my_device/images/findMyDevice.png');
|
||||
assert.equal(options.tag, FMD_TAG);
|
||||
assert.equal(options.data.systemMessageTarget, 'findmydevice');
|
||||
});
|
||||
|
||||
test('MozActivity is issued if notification clicked', function(done) {
|
||||
var notification = {
|
||||
onclick: undefined,
|
||||
};
|
||||
this.sinon.stub(window.NotificationHelper, 'send').returns(
|
||||
Promise.resolve(notification));
|
||||
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.retry-count',
|
||||
{settingValue: FMD_RETRIES});
|
||||
|
||||
var activitySpy = this.sinon.spy(window, 'MozActivity');
|
||||
|
||||
var expectedActivity = {
|
||||
name : 'configure',
|
||||
data : {
|
||||
target : 'device',
|
||||
section : 'findmydevice'
|
||||
}
|
||||
};
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
notification.onclick();
|
||||
|
||||
assert.isTrue(activitySpy.calledWithNew());
|
||||
sinon.assert.calledWith(activitySpy, expectedActivity);
|
||||
}).then(done, done);
|
||||
});
|
||||
|
||||
test('FMD disabled if retry-count >= limit, notification tapped', function() {
|
||||
MockSettingsHelper('findmydevice.enabled').set(true);
|
||||
MockNavigatorSettings.mTriggerObservers('findmydevice.retry-count',
|
||||
{settingValue: FMD_RETRIES});
|
||||
|
||||
MockSettingsHelper('findmydevice.enabled').get(
|
||||
function(val) {
|
||||
assert.equal(val, false, 'enabled should be false');
|
||||
});
|
||||
});
|
||||
|
||||
test('clear lockscreen message when the lockscreen unlocks', function() {
|
||||
window.dispatchEvent(new CustomEvent('lockscreen-request-unlock'));
|
||||
assert.equal(
|
||||
MockSettingsHelper.instances['lockscreen.lock-message'].value, '');
|
||||
});
|
||||
|
||||
test('fmd is awoken with LOCKSCREEN_CLOSED on lockscreen unlock', function() {
|
||||
window.dispatchEvent(new CustomEvent('lockscreen-request-unlock'));
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_LOCKSCREEN_CLOSED);
|
||||
});
|
||||
|
||||
test('fmd is not awoken with LOCKSCREEN_CLOSED on lockscreen camera launch',
|
||||
function() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('lockscreen-request-unlock',
|
||||
{detail: {activity: {name: 'record'}}}));
|
||||
sinon.assert.notCalled(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_LOCKSCREEN_CLOSED);
|
||||
}
|
||||
);
|
||||
|
||||
test('send LOGIN wakeup message on FxA login', function() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('mozFxAccountsUnsolChromeEvent',
|
||||
{detail: {eventName: 'onlogin'}}));
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_LOGIN);
|
||||
});
|
||||
|
||||
test('send LOGIN wakeup message on FxA verified', function() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('mozFxAccountsUnsolChromeEvent',
|
||||
{detail: {eventName: 'onverified'}}));
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_LOGIN);
|
||||
});
|
||||
|
||||
test('send LOGOUT wakeup message on FxA logout', function() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('mozFxAccountsUnsolChromeEvent',
|
||||
{detail: {eventName: 'onlogout'}}));
|
||||
sinon.assert.calledWith(window.wakeUpFindMyDevice,
|
||||
IAC_API_WAKEUP_REASON_LOGOUT);
|
||||
});
|
||||
|
||||
suite('System message notification', function() {
|
||||
var serviceSpy;
|
||||
|
||||
var notification = {
|
||||
body: 'tap-to-check-settings',
|
||||
tag: FMD_TAG,
|
||||
data: {
|
||||
systemMessageTarget: 'screenshot'
|
||||
},
|
||||
close: function() {}
|
||||
};
|
||||
|
||||
suite('start condition', function() {
|
||||
test('FMDInit() requests handleSystemMessageNotification service',
|
||||
function() {
|
||||
serviceSpy = this.sinon.spy(MockService, 'request');
|
||||
FMDInit();
|
||||
assert.isTrue(serviceSpy.calledOnce);
|
||||
assert.isTrue(serviceSpy.calledWith(
|
||||
'handleSystemMessageNotification', 'findmydevice',
|
||||
FMDNotificationsHandler));
|
||||
});
|
||||
});
|
||||
|
||||
suite('handleSystemMessageNotification behavior', function() {
|
||||
test('calls FMDOpenSettings', function() {
|
||||
var FMDOpenSettingsSpy = this.sinon.spy(window, 'FMDOpenSettings');
|
||||
FMDNotificationsHandler.handleSystemMessageNotification(notification);
|
||||
assert.isTrue(FMDOpenSettingsSpy.calledOnce);
|
||||
});
|
||||
|
||||
test('calls closeSystemMessageNotification',
|
||||
function() {
|
||||
var closeSpy = this.sinon.spy(FMDNotificationsHandler,
|
||||
'closeSystemMessageNotification');
|
||||
FMDNotificationsHandler.handleSystemMessageNotification(notification);
|
||||
assert.isTrue(closeSpy.calledOnce);
|
||||
assert.isTrue(closeSpy.calledWith(notification));
|
||||
});
|
||||
});
|
||||
|
||||
suite('closeSystemMessageNotification behavior', function() {
|
||||
var notifCloseSpy, notificationGetStub;
|
||||
|
||||
setup(function() {
|
||||
notifCloseSpy = this.sinon.spy(notification, 'close');
|
||||
notificationGetStub = function notificationGet() {
|
||||
return {
|
||||
then: function(cb) {
|
||||
cb && cb([ notification ]);
|
||||
}
|
||||
};
|
||||
};
|
||||
this.sinon.stub(window.Notification, 'get', notificationGetStub);
|
||||
});
|
||||
|
||||
test('closes notification by tag', function() {
|
||||
FMDNotificationsHandler.closeSystemMessageNotification(notification);
|
||||
assert.isTrue(window.Notification.get.calledOnce);
|
||||
assert.isTrue(window.Notification.get.calledWith(
|
||||
{ tag: notification.tag}));
|
||||
assert.isTrue(notifCloseSpy.calledOnce);
|
||||
});
|
||||
|
||||
test('closes notification by body', function() {
|
||||
var tag = notification.tag;
|
||||
notification.tag = undefined;
|
||||
|
||||
FMDNotificationsHandler.closeSystemMessageNotification(notification);
|
||||
assert.isTrue(window.Notification.get.calledOnce);
|
||||
assert.isTrue(window.Notification.get.calledWith(
|
||||
{ tag: notification.tag}));
|
||||
assert.isTrue(notifCloseSpy.calledOnce);
|
||||
|
||||
notification.tag = tag;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
99
gaia/apps/system/test/unit/ftu_late_customization_test.js
Executable file
99
gaia/apps/system/test/unit/ftu_late_customization_test.js
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
/* global Service, MockPromise, FtuLateCustomization */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_promise.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/ftu_late_customization.js');
|
||||
|
||||
suite('ftu customization >', function() {
|
||||
var realMozSettings, subject;
|
||||
var realPromise = window.Promise;
|
||||
|
||||
function sendIACFTUCommsAppsEvent(urls) {
|
||||
var evt = new CustomEvent('iac-ftucomms', {
|
||||
detail: {
|
||||
type: 'late-customization-apps',
|
||||
urls: urls
|
||||
}
|
||||
});
|
||||
window.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
suiteSetup(function() {
|
||||
window.Promise = MockPromise;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
window.Promise = realPromise;
|
||||
});
|
||||
|
||||
var fakeListener;
|
||||
var appUrls = new Map([
|
||||
['http://ernst.tld/manifest.webapp', null],
|
||||
['http://arp.tld/manifest.webapp', null],
|
||||
['http://duchamp.tld/manifest.webapp', null]
|
||||
]);
|
||||
|
||||
setup(function() {
|
||||
fakeListener = sinon.spy();
|
||||
window.addEventListener('ftucustomizationbegin', fakeListener);
|
||||
window.addEventListener('ftucustomizationend', fakeListener);
|
||||
subject = new FtuLateCustomization();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject && subject.stop();
|
||||
});
|
||||
|
||||
test('start', function() {
|
||||
this.sinon.spy(subject, 'gotInstallUrls');
|
||||
subject.start();
|
||||
sendIACFTUCommsAppsEvent([...appUrls]);
|
||||
assert.ok(subject.gotInstallUrls.calledOnce);
|
||||
|
||||
assert.ok(fakeListener.calledOnce);
|
||||
var beginEvent = fakeListener.firstCall.args[0];
|
||||
assert.equal(beginEvent.type, 'ftucustomizationbegin');
|
||||
assert.ok(Array.isArray( beginEvent.detail.manifestURLs ));
|
||||
});
|
||||
|
||||
test('Service:ftuCustomizationContains', function() {
|
||||
assert.ok(!Service.query('Service:ftuCustomizationContains',
|
||||
'http://ernst.tld/manifest.webapp'));
|
||||
|
||||
subject.start();
|
||||
subject.appsToInstall = appUrls;
|
||||
|
||||
assert.isTrue(subject.ftuCustomizationContains(
|
||||
'http://ernst.tld/manifest.webapp'));
|
||||
assert.isFalse(Service.query('ftuCustomizationContains',
|
||||
'http://nosuch.tld/manifest.webapp'));
|
||||
|
||||
subject.stop();
|
||||
assert.ok(!Service.query('Service:ftuCustomizationContains',
|
||||
'http://ernst.tld/manifest.webapp'));
|
||||
});
|
||||
|
||||
test('end', function() {
|
||||
this.sinon.spy(subject, 'gotInstallUrls');
|
||||
subject.start();
|
||||
fakeListener.reset();
|
||||
subject.stop();
|
||||
|
||||
assert.ok(fakeListener.calledOnce);
|
||||
var endEvent = fakeListener.firstCall.args[0];
|
||||
assert.ok(endEvent);
|
||||
assert.equal(endEvent.type, 'ftucustomizationend');
|
||||
|
||||
this.sinon.stub(subject, 'handleEvent');
|
||||
sendIACFTUCommsAppsEvent([...appUrls]);
|
||||
assert.isFalse(subject.handleEvent.called);
|
||||
|
||||
assert.isFalse(subject.ftuCustomizationContains(
|
||||
'http://ernst.tld/manifest.webapp'));
|
||||
});
|
||||
|
||||
});
|
||||
173
gaia/apps/system/test/unit/ftu_launcher_test.js
Executable file
173
gaia/apps/system/test/unit/ftu_launcher_test.js
Executable file
|
|
@ -0,0 +1,173 @@
|
|||
/* global BaseModule, MocksHelper, SettingsMigrator,
|
||||
MockasyncStorage, MockNavigatorSettings, MockPromise,
|
||||
FtuLateCustomization */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/js/version_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_promise.js');
|
||||
require('/apps/system/test/unit/mock_asyncStorage.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/js/service.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
requireApp('system/js/ftu_launcher.js');
|
||||
|
||||
var mocksForFtuLauncher = new MocksHelper([
|
||||
'LazyLoader',
|
||||
]).init();
|
||||
|
||||
suite('launch ftu >', function() {
|
||||
|
||||
mocksForFtuLauncher.attachTestHelpers();
|
||||
var realAsyncStorage, realMozSettings, realFtuPing, subject;
|
||||
var startAllPromise;
|
||||
|
||||
|
||||
var mockIACFTUCommsStartedEvent = {
|
||||
detail: 'started'
|
||||
};
|
||||
var mockIACFTUCommsStepEvent = {
|
||||
detail: { type: 'step' }
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realFtuPing = window.FtuPing;
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
realMozSettings = navigator.mozSettings;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
window.FtuPing = function() {
|
||||
this.ensurePingCalled = false;
|
||||
this.ensurePing = function() { this.ensurePingCalled = true; };
|
||||
};
|
||||
window.FtuLateCustomization = function() {
|
||||
this.start = sinon.stub();
|
||||
this.stop = sinon.stub();
|
||||
FtuLateCustomization.instance = this;
|
||||
};
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
window.SettingsMigrator = function() {};
|
||||
SettingsMigrator.prototype.start = function() {};
|
||||
subject = BaseModule.instantiate('FtuLauncher');
|
||||
startAllPromise = new MockPromise();
|
||||
this.sinon.stub(Promise, 'all').returns(startAllPromise);
|
||||
subject.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.SettingsMigrator = null;
|
||||
subject.stop();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
window.FtuPing = realFtuPing;
|
||||
});
|
||||
|
||||
suite('ftu.enabled >', function() {
|
||||
setup(function() {
|
||||
startAllPromise.mFulfillToValue([]);
|
||||
});
|
||||
test('ftu ping is called', function() {
|
||||
assert.ok(subject.getFtuPing().ensurePingCalled);
|
||||
});
|
||||
});
|
||||
|
||||
suite('_handle_iac-ftucomms', function() {
|
||||
setup(function() {
|
||||
startAllPromise.mFulfillToValue([]);
|
||||
});
|
||||
var publishStub;
|
||||
setup(function() {
|
||||
publishStub = this.sinon.stub(subject, 'publish');
|
||||
});
|
||||
|
||||
test('dont publish ftustarted on ftucomms started event', function() {
|
||||
subject['_handle_iac-ftucomms'](mockIACFTUCommsStartedEvent);
|
||||
assert.isFalse(publishStub.calledWith('started'));
|
||||
});
|
||||
|
||||
test('handle step event', function() {
|
||||
subject['_handle_iac-ftucomms'](mockIACFTUCommsStepEvent);
|
||||
assert.isTrue(publishStub.calledWith('step'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('stepReady', function() {
|
||||
setup(function() {
|
||||
startAllPromise.mFulfillToValue([]);
|
||||
});
|
||||
test('When FTU is closed, any step should be ready', function(done) {
|
||||
subject.close();
|
||||
subject.stepReady('#wifi').then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
test('When FTU is skipped, any step should be ready', function(done) {
|
||||
subject.skip();
|
||||
subject.stepReady('#wifi').then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
test('Navigator to #languages', function(done) {
|
||||
var evt = new CustomEvent('iac-ftucomms', {
|
||||
detail: {
|
||||
type: 'step',
|
||||
hash: '#languages'
|
||||
}
|
||||
});
|
||||
subject.handleEvent(evt);
|
||||
subject.stepReady('#languages').then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Navigate to wifi', function(done) {
|
||||
var evt = new CustomEvent('iac-ftucomms', {
|
||||
detail: {
|
||||
type: 'step',
|
||||
hash: '#languages'
|
||||
}
|
||||
});
|
||||
subject.handleEvent(evt);
|
||||
var evt2 = new CustomEvent('iac-ftucomms', {
|
||||
detail: {
|
||||
type: 'step',
|
||||
hash: '#wifi'
|
||||
}
|
||||
});
|
||||
subject.handleEvent(evt2);
|
||||
subject.stepReady('#wifi').then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Late Customization', function() {
|
||||
var customizationUrl = 'http://foo.com/api/operator/';
|
||||
setup(function() {
|
||||
startAllPromise.mFulfillToValue([customizationUrl]);
|
||||
});
|
||||
|
||||
test('start', function() {
|
||||
assert.ok(subject.isFtuCustomizing());
|
||||
assert.ok(FtuLateCustomization.instance &&
|
||||
FtuLateCustomization.instance.start.calledOnce);
|
||||
});
|
||||
|
||||
test('skip', function() {
|
||||
subject.skip();
|
||||
assert.ok(FtuLateCustomization.instance.stop.calledOnce);
|
||||
assert.isFalse(subject.isFtuCustomizing());
|
||||
});
|
||||
|
||||
test('done', function() {
|
||||
subject.skip();
|
||||
assert.ok(FtuLateCustomization.instance.stop.calledOnce);
|
||||
assert.isFalse(subject.isFtuCustomizing());
|
||||
});
|
||||
});
|
||||
});
|
||||
569
gaia/apps/system/test/unit/ftu_ping_test.js
Executable file
569
gaia/apps/system/test/unit/ftu_ping_test.js
Executable file
|
|
@ -0,0 +1,569 @@
|
|||
'use strict';
|
||||
|
||||
/* global MockNavigatorSettings, MockasyncStorage, MockXMLHttpRequest,
|
||||
MockNavigatorMozMobileConnections, MockNavigatorMozIccManager,
|
||||
MockNavigatorMozTelephony, MockMobileOperator, MockSIMSlotManager,
|
||||
MockSIMSlot, MockAppsMgmt, MocksHelper, MockNavigatorMozWifiManager */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/apps/system/test/unit/mock_asyncStorage.js');
|
||||
require('/apps/system/test/unit/mock_xmlhttprequest.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_mobile_connections.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_icc_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_telephony.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_wifi_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_mobile_operator.js');
|
||||
requireApp('system/test/unit/mock_apps_mgmt.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
require('/shared/js/telemetry.js');
|
||||
require('/shared/js/uuid.js');
|
||||
require('/shared/test/unit/mocks/mock_simslot_manager.js');
|
||||
require('/shared/test/unit/mocks/mock_simslot.js');
|
||||
require('/apps/system/js/ftu_ping.js');
|
||||
|
||||
function switchReadOnlyProperty(originObject, propName, targetObj) {
|
||||
Object.defineProperty(originObject, propName, {
|
||||
configurable: true,
|
||||
get: function() { return targetObj; }
|
||||
});
|
||||
}
|
||||
|
||||
function stubDial(self) {
|
||||
self.sinon.stub(navigator.mozTelephony, 'dial', function() {
|
||||
return Promise.resolve({
|
||||
result: Promise.resolve({
|
||||
success: true,
|
||||
serviceCode: 'scImei',
|
||||
statusMessage: 'fakeImei'
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!window.asyncStorage) {
|
||||
window.asyncStorage = null;
|
||||
}
|
||||
|
||||
if (!window.MobileOperator) {
|
||||
window.MobileOperator = null;
|
||||
}
|
||||
|
||||
if (!window.XMLHttpRequest) {
|
||||
window.XMLHttpRequest = null;
|
||||
}
|
||||
|
||||
if (!window.SIMSlotManager) {
|
||||
window.SIMSlotManager = null;
|
||||
}
|
||||
|
||||
|
||||
var mocksForFtuPing = new MocksHelper([
|
||||
'LazyLoader',
|
||||
]).init();
|
||||
|
||||
suite('FtuPing', function() {
|
||||
mocksForFtuPing.attachTestHelpers();
|
||||
var realMozSettings, realAsyncStorage, realXHR;
|
||||
var realMobileConnections, realIccManager;
|
||||
var realMobileOperator, realSIMSlotManager;
|
||||
var realNavigatorLanguage;
|
||||
var realMozApps, realMozTelephony, realMozWifiManager;
|
||||
var FtuPing;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozSettings = navigator.mozSettings;
|
||||
realAsyncStorage = window.asyncStorage;
|
||||
realXHR = window.XMLHttpRequest;
|
||||
realMobileConnections = navigator.mozMobileConnections;
|
||||
realIccManager = navigator.mozIccManager;
|
||||
realMobileOperator = window.MobileOperator;
|
||||
realSIMSlotManager = window.SIMSlotManager;
|
||||
realMozApps = navigator.mozApps;
|
||||
realNavigatorLanguage = navigator.language;
|
||||
realMozTelephony = navigator.mozTelephony;
|
||||
realMozWifiManager = navigator.mozWifiManager;
|
||||
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
window.asyncStorage = MockasyncStorage;
|
||||
window.XMLHttpRequest = MockXMLHttpRequest;
|
||||
navigator.mozMobileConnections = MockNavigatorMozMobileConnections;
|
||||
navigator.mozIccManager = MockNavigatorMozIccManager;
|
||||
window.MobileOperator = MockMobileOperator;
|
||||
window.SIMSlotManager = MockSIMSlotManager;
|
||||
navigator.mozApps = { mgmt: MockAppsMgmt };
|
||||
navigator.mozTelephony = MockNavigatorMozTelephony;
|
||||
navigator.mozWifiManager = MockNavigatorMozWifiManager;
|
||||
switchReadOnlyProperty(navigator,'language', realNavigatorLanguage);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozSettings = realMozSettings;
|
||||
window.asyncStorage = realAsyncStorage;
|
||||
window.XMLHttpRequest = realXHR;
|
||||
navigator.mozMobileConnections = realMobileConnections;
|
||||
navigator.mozIccManager = realIccManager;
|
||||
window.MobileOperator = realMobileOperator;
|
||||
window.SIMSlotManager = realSIMSlotManager;
|
||||
navigator.mozApps = realMozApps;
|
||||
navigator.mozTelephony = realMozTelephony;
|
||||
navigator.mozWifiManager = realMozWifiManager;
|
||||
switchReadOnlyProperty(navigator,'language', realNavigatorLanguage);
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
FtuPing = new window.FtuPing();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockNavigatorSettings.mTeardown();
|
||||
MockasyncStorage.mTeardown();
|
||||
MockXMLHttpRequest.mTeardown();
|
||||
MockNavigatorMozMobileConnections.mTeardown();
|
||||
MockMobileOperator.mTeardown();
|
||||
MockSIMSlotManager.mTeardown();
|
||||
MockAppsMgmt.mTeardown();
|
||||
FtuPing = null;
|
||||
});
|
||||
|
||||
test('getAsyncStorageItems gets all items', function(done) {
|
||||
this.timeout(5000);
|
||||
MockasyncStorage.mItems.a = 1;
|
||||
MockasyncStorage.mItems.b = 2;
|
||||
MockasyncStorage.mItems.c = 3;
|
||||
FtuPing.getAsyncStorageItems(['a', 'b', 'c'], function(items) {
|
||||
assert.equal(items.a, 1);
|
||||
assert.equal(items.b, 2);
|
||||
assert.equal(items.c, 3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('getSettings gets all settings', function(done) {
|
||||
this.timeout(5000);
|
||||
MockNavigatorSettings.mSettings.a = 1;
|
||||
MockNavigatorSettings.mSettings.b = 2;
|
||||
MockNavigatorSettings.mSettings.c = 3;
|
||||
FtuPing.getSettings(['a', 'b', 'c'], function(settings) {
|
||||
assert.equal(settings.a, 1);
|
||||
assert.equal(settings.b, 2);
|
||||
assert.equal(settings.c, 3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite('ensurePing', function() {
|
||||
var realStartPing;
|
||||
var doneCallback;
|
||||
|
||||
setup(function() {
|
||||
realStartPing = FtuPing.startPing;
|
||||
FtuPing.startPing = function() {
|
||||
if (doneCallback) {
|
||||
doneCallback();
|
||||
}
|
||||
};
|
||||
MockNavigatorSettings.mSettings['ftu.pingURL'] = 'test_url';
|
||||
MockAppsMgmt.mApps = [
|
||||
{ manifestURL: 'app://testapp.org/manifest.webapp',
|
||||
manifest: { name: 'Test' } },
|
||||
];
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FtuPing.startPing = realStartPing;
|
||||
doneCallback = null;
|
||||
});
|
||||
|
||||
test('window properties are set', function(done) {
|
||||
this.timeout(3000);
|
||||
doneCallback = function() {
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.equal(pingData.screenHeight, window.screen.height);
|
||||
assert.equal(pingData.screenWidth, window.screen.width);
|
||||
assert.equal(pingData.devicePixelRatio, window.devicePixelRatio);
|
||||
assert.equal(pingData.locale, navigator.language);
|
||||
done();
|
||||
};
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
|
||||
test('empty settings are generated', function(done) {
|
||||
this.timeout(3000);
|
||||
doneCallback = function() {
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.ok(pingData.activationTime);
|
||||
assert.equal(pingData.activationTime,
|
||||
MockasyncStorage.mItems['ftu.pingActivation']);
|
||||
|
||||
assert.ok(FtuPing.isEnabled());
|
||||
assert.equal(FtuPing.getNetworkFailCount(), 0);
|
||||
|
||||
assert.equal(FtuPing.getTryInterval(), 60 * 60 * 1000);
|
||||
assert.equal(FtuPing.getPingTimeout(), 60 * 1000);
|
||||
assert.equal(FtuPing.getMaxNetworkFails(), 24);
|
||||
done();
|
||||
};
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
|
||||
test('existing settings are set', function(done) {
|
||||
this.timeout(3000);
|
||||
MockasyncStorage.mItems['ftu.pingActivation'] = 'test_activation';
|
||||
MockasyncStorage.mItems['ftu.pingEnabled'] = false;
|
||||
MockasyncStorage.mItems['ftu.pingNetworkFailCount'] = 10;
|
||||
|
||||
var mockSettings = MockNavigatorSettings.mSettings;
|
||||
mockSettings['ftu.pingTryInterval'] = 10000;
|
||||
mockSettings['ftu.pingTimeout'] = 1000;
|
||||
mockSettings['ftu.pingMaxNetworkFails'] = 100;
|
||||
mockSettings['deviceinfo.os'] = 'test_os';
|
||||
mockSettings['deviceinfo.software'] = 'test_software';
|
||||
mockSettings['deviceinfo.platform_build_id'] = 'test_build_id';
|
||||
mockSettings['deviceinfo.platform_version'] = 'test_version';
|
||||
mockSettings['deviceinfo.product_model'] = 'test_model';
|
||||
mockSettings['deviceinfo.firmware_revision'] = 'test_revision';
|
||||
mockSettings['deviceinfo.hardware'] = 'test_hardware';
|
||||
mockSettings['app.update.channel'] = 'test_channel';
|
||||
|
||||
doneCallback = function() {
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.equal(pingData.activationTime, 'test_activation');
|
||||
assert.equal(FtuPing.isEnabled(), false);
|
||||
assert.equal(FtuPing.getNetworkFailCount(), 10);
|
||||
assert.equal(FtuPing.getPingURL(), 'test_url');
|
||||
assert.equal(FtuPing.getTryInterval(), 10000);
|
||||
assert.equal(FtuPing.getPingTimeout(), 1000);
|
||||
assert.equal(FtuPing.getMaxNetworkFails(), 100);
|
||||
|
||||
assert.equal(pingData['deviceinfo.os'], 'test_os');
|
||||
assert.equal(pingData['deviceinfo.software'], 'test_software');
|
||||
assert.equal(pingData['deviceinfo.product_model'], 'test_model');
|
||||
assert.equal(pingData['deviceinfo.firmware_revision'], 'test_revision');
|
||||
assert.equal(pingData['deviceinfo.hardware'], 'test_hardware');
|
||||
|
||||
var infoData = FtuPing.getInfoData();
|
||||
assert.equal(infoData['deviceinfo.platform_build_id'], 'test_build_id');
|
||||
assert.equal(infoData['deviceinfo.platform_version'], 'test_version');
|
||||
assert.equal(infoData['app.update.channel'], 'test_channel');
|
||||
|
||||
done();
|
||||
};
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
|
||||
test('startPing is called from ensurePing', function(done) {
|
||||
this.timeout(3000);
|
||||
doneCallback = done;
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
|
||||
test('preinstalled apps are fetched', function(done) {
|
||||
doneCallback = function() {
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.ok(pingData.preinstalled);
|
||||
assert.equal(Object.keys(pingData.preinstalled).length, 1);
|
||||
assert.equal(pingData.preinstalled['app://testapp.org/manifest.webapp'],
|
||||
'Test');
|
||||
done();
|
||||
};
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
test('ping asks assemblePingData for data', function(done) {
|
||||
var spy = this.sinon.spy(FtuPing, 'assemblePingData');
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
});
|
||||
doneCallback = function() {
|
||||
assert.ok(spy.called);
|
||||
done();
|
||||
};
|
||||
FtuPing.ensurePing();
|
||||
});
|
||||
});
|
||||
|
||||
function addMockMobileConnection() {
|
||||
MockNavigatorMozMobileConnections.mAddMobileConnection();
|
||||
|
||||
var mockConn = MockNavigatorMozMobileConnections[0];
|
||||
mockConn.iccId = 'test_icc';
|
||||
mockConn.voice = {
|
||||
network: {
|
||||
mnc: 'voice_mnc',
|
||||
mcc: 'voice_mcc'
|
||||
}
|
||||
};
|
||||
|
||||
var mockIcc = {
|
||||
iccInfo: {
|
||||
mnc: 'icc_mnc',
|
||||
mcc: 'icc_mcc',
|
||||
spn: 'icc_spn'
|
||||
}
|
||||
};
|
||||
|
||||
MockNavigatorMozIccManager.addIcc('test_icc', mockIcc);
|
||||
MockMobileOperator.mOperator = 'test_operator';
|
||||
MockMobileOperator.mCarrier = 'test_carrier';
|
||||
MockMobileOperator.mRegion = 'test_region';
|
||||
return mockConn;
|
||||
}
|
||||
|
||||
suite('checkMobileNetwork', function() {
|
||||
test('fails with no sim card connected to network', function() {
|
||||
this.sinon.stub(MockSIMSlotManager, 'noSIMCardConnectedToNetwork')
|
||||
.returns(true);
|
||||
assert.throw(function() { FtuPing.checkMobileNetwork(); },
|
||||
/No SIM cards/);
|
||||
assert.equal(FtuPing.getNetworkFailCount(), 1);
|
||||
MockSIMSlotManager.noSIMCardConnectedToNetwork.restore();
|
||||
});
|
||||
|
||||
test('fails with no mobile connections', function() {
|
||||
this.sinon.stub(MockSIMSlotManager, 'noSIMCardConnectedToNetwork')
|
||||
.returns(false);
|
||||
assert.throw(function() { FtuPing.checkMobileNetwork(); },
|
||||
/No unlocked or active SIM cards found/);
|
||||
assert.equal(FtuPing.getNetworkFailCount(), 1);
|
||||
MockSIMSlotManager.noSIMCardConnectedToNetwork.restore();
|
||||
});
|
||||
|
||||
test('fails with no SIM slots', function() {
|
||||
this.sinon.stub(MockSIMSlotManager, 'noSIMCardConnectedToNetwork')
|
||||
.returns(false);
|
||||
MockNavigatorMozMobileConnections.mAddMobileConnection();
|
||||
assert.throw(function() { FtuPing.checkMobileNetwork(); },
|
||||
/No unlocked or active SIM cards found/);
|
||||
MockSIMSlotManager.noSIMCardConnectedToNetwork.restore();
|
||||
});
|
||||
|
||||
suite('dual SIM', function() {
|
||||
var slot1, slot2, conn;
|
||||
setup(function() {
|
||||
this.sinon.stub(MockSIMSlotManager, 'noSIMCardConnectedToNetwork')
|
||||
.returns(false);
|
||||
conn = addMockMobileConnection();
|
||||
|
||||
slot1 = new MockSIMSlot(conn, 0), slot2 = new MockSIMSlot(conn, 1);
|
||||
MockSIMSlotManager.mInstances.push(slot1);
|
||||
MockSIMSlotManager.mInstances.push(slot2);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockSIMSlotManager.noSIMCardConnectedToNetwork.restore();
|
||||
});
|
||||
|
||||
test('fails when both absent', function() {
|
||||
slot1.absent = true;
|
||||
slot2.absent = true;
|
||||
assert.throw(function() { FtuPing.checkMobileNetwork(); },
|
||||
/No unlocked or active/);
|
||||
});
|
||||
|
||||
test('fails when only slot 2 is active but locked', function() {
|
||||
slot1.absent = true;
|
||||
slot2.locked = true;
|
||||
assert.throw(function() { FtuPing.checkMobileNetwork(); },
|
||||
/No unlocked or active/);
|
||||
});
|
||||
|
||||
test('succeeds with only slot 1 active and unlocked', function() {
|
||||
slot2.absent = true;
|
||||
assert.doesNotThrow(function() { FtuPing.checkMobileNetwork(); });
|
||||
});
|
||||
|
||||
test('succeeds with only slot 2 active and unlocked', function() {
|
||||
slot1.absent = true;
|
||||
assert.doesNotThrow(function() { FtuPing.checkMobileNetwork(); });
|
||||
});
|
||||
});
|
||||
|
||||
test('max mobile failures pings anyway', function(done) {
|
||||
MockasyncStorage.mItems['ftu.pingNetworkFailCount'] = 1;
|
||||
MockNavigatorSettings.mSettings['ftu.pingMaxNetworkFails'] = 1;
|
||||
MockNavigatorSettings.mSettings['deviceinfo.os'] = 'test_os';
|
||||
|
||||
FtuPing.initSettings().then(function() {
|
||||
assert.doesNotThrow(function() { FtuPing.checkMobileNetwork(); });
|
||||
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.ok(!pingData.network);
|
||||
assert.ok(!pingData.icc);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('tryPing', function() {
|
||||
var realPing, pingCallback;
|
||||
setup(function() {
|
||||
realPing = FtuPing.ping;
|
||||
FtuPing.ping = function() {
|
||||
if (pingCallback) {
|
||||
pingCallback();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FtuPing.ping = realPing;
|
||||
pingCallback = null;
|
||||
});
|
||||
|
||||
test('no deviceinfo.os fails', function(done) {
|
||||
MockasyncStorage.mItems['ftu.pingNetworkFailCount'] = 1;
|
||||
MockNavigatorSettings.mSettings['ftu.pingMaxNetworkFails'] = 1;
|
||||
FtuPing.initSettings().then(function() {
|
||||
assert.ok(!FtuPing.tryPing());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('iccinfo and voice network make it into pingData', function(done) {
|
||||
MockNavigatorSettings.mSettings['deviceinfo.os'] = 'test_os';
|
||||
MockNavigatorMozWifiManager.setMacAddress('00:0a:f5:cb:63:dc');
|
||||
this.sinon.stub(MockSIMSlotManager, 'noSIMCardConnectedToNetwork')
|
||||
.returns(false);
|
||||
stubDial(this);
|
||||
var conn = addMockMobileConnection();
|
||||
MockSIMSlotManager.mInstances.push(new MockSIMSlot(conn, 0));
|
||||
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing.tryPing();
|
||||
|
||||
var pingData = FtuPing.assemblePingData();
|
||||
assert.ok(pingData.icc);
|
||||
assert.equal(pingData.icc.mnc, 'icc_mnc');
|
||||
assert.equal(pingData.icc.mcc, 'icc_mcc');
|
||||
assert.equal(pingData.icc.spn, 'icc_spn');
|
||||
|
||||
assert.ok(pingData.network);
|
||||
assert.equal(pingData.network.mnc, 'voice_mnc');
|
||||
assert.equal(pingData.network.mcc, 'voice_mcc');
|
||||
assert.equal(pingData.network.operator, 'test_operator');
|
||||
assert.equal(pingData.network.carrier, 'test_carrier');
|
||||
assert.equal(pingData.network.region, 'test_region');
|
||||
MockSIMSlotManager.noSIMCardConnectedToNetwork.restore();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('ping', function() {
|
||||
setup(function() {
|
||||
MockNavigatorSettings.mSettings['ftu.pingURL'] = 'test_url';
|
||||
MockasyncStorage.mItems['ftu.pingEnabled'] = true;
|
||||
});
|
||||
|
||||
test('pingData and url are valid', function(done) {
|
||||
MockNavigatorSettings.mSettings['deviceinfo.os'] = 'test_os';
|
||||
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
assert.equal(MockXMLHttpRequest.mLastOpenedUrl,
|
||||
'test_url/test_id/ftu/FirefoxOS/unknown/unknown/unknown');
|
||||
assert.equal(MockXMLHttpRequest.mHeaders['Content-type'],
|
||||
'application/json');
|
||||
|
||||
var data = JSON.parse(MockXMLHttpRequest.mLastSendData);
|
||||
assert.ok(data.info);
|
||||
assert.equal(data.ver, 1);
|
||||
assert.equal(data.info['deviceinfo.os'], 'test_os');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('OK clears enabled flag', function(done) {
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
MockXMLHttpRequest.mSendOnLoad({ responseText: 'OK' });
|
||||
assert.equal(MockasyncStorage.mItems['ftu.pingEnabled'], false);
|
||||
assert.equal(FtuPing.isEnabled(), false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('bad response doesn\'t clear flag', function(done) {
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
MockXMLHttpRequest.mSendOnLoad({ responseText: 'bla' });
|
||||
assert.equal(MockasyncStorage.mItems['ftu.pingEnabled'], true);
|
||||
assert.equal(FtuPing.isEnabled(), true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('error doesn\'t clear flag', function(done) {
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
MockXMLHttpRequest.mSendError();
|
||||
assert.equal(MockasyncStorage.mItems['ftu.pingEnabled'], true);
|
||||
assert.equal(FtuPing.isEnabled(), true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('timeout doesn\'t clear flag', function(done) {
|
||||
FtuPing.initSettings().then(function() {
|
||||
FtuPing._pingData.pingID = 'test_id';
|
||||
FtuPing.ping();
|
||||
MockXMLHttpRequest.mSendTimeout();
|
||||
assert.equal(MockasyncStorage.mItems['ftu.pingEnabled'], true);
|
||||
assert.equal(FtuPing.isEnabled(), true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('preinstalled apps', function() {
|
||||
setup(function() {
|
||||
MockAppsMgmt.mApps = [
|
||||
{ manifestURL: 'app://testgaia.gaiamobile.org/manifest.webapp',
|
||||
manifest: { name: 'Test' } },
|
||||
{ manifestURL: 'app://testapp1.org/path/manifest.webapp',
|
||||
manifest: { name: 'TestWithPath' } },
|
||||
{ manifestURL: 'http://testapp2.com/manifest.webapp',
|
||||
manifest: { name: 'HttpTest' } },
|
||||
];
|
||||
FtuPing.reset();
|
||||
});
|
||||
|
||||
test('gets preinstalled apps', function(done) {
|
||||
FtuPing.initPreinstalledApps().then(function() {
|
||||
var preinstalled = FtuPing.assemblePingData().preinstalled;
|
||||
assert.equal(Object.keys(preinstalled).length, 2);
|
||||
assert.equal(preinstalled['app://testapp1.org/path/manifest.webapp'],
|
||||
'TestWithPath');
|
||||
assert.equal(preinstalled['http://testapp2.com/manifest.webapp'],
|
||||
'HttpTest');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('locale', function() {
|
||||
setup(function() {
|
||||
FtuPing.initSettings();
|
||||
});
|
||||
teardown(function() {
|
||||
switchReadOnlyProperty(navigator,'language', realNavigatorLanguage);
|
||||
});
|
||||
|
||||
test('initial language', function() {
|
||||
assert.equal(FtuPing.assemblePingData().locale,
|
||||
window.navigator.language);
|
||||
});
|
||||
|
||||
test('late change to language', function() {
|
||||
var newLocale = 'zh-TW';
|
||||
switchReadOnlyProperty(navigator,'language', newLocale);
|
||||
assert.equal(FtuPing.assemblePingData().locale, newLocale);
|
||||
});
|
||||
});
|
||||
});
|
||||
371
gaia/apps/system/test/unit/fx_accounts_client_test.js
Executable file
371
gaia/apps/system/test/unit/fx_accounts_client_test.js
Executable file
|
|
@ -0,0 +1,371 @@
|
|||
/* global FxAccountsClient */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/fx_accounts_client.js');
|
||||
|
||||
var MockEventListener = {};
|
||||
var MockDispatchedEvents = [];
|
||||
|
||||
function MockAddEventListener(event, listener) {
|
||||
MockEventListener[event] = listener;
|
||||
}
|
||||
|
||||
function MockRemoveEventListener(event, listener) {
|
||||
delete MockEventListener[event];
|
||||
}
|
||||
|
||||
function MockDispatchEvent(event) {
|
||||
MockDispatchedEvents.push(event);
|
||||
}
|
||||
|
||||
|
||||
suite('system/FxAccountsClient >', function() {
|
||||
var result = null;
|
||||
var error = null;
|
||||
|
||||
var expectedData = 'data';
|
||||
var expectedError = 'error';
|
||||
|
||||
var successCbCalled = false;
|
||||
var errorCbCalled = false;
|
||||
|
||||
var stubAddEventListener;
|
||||
var stubRemoveEventListener;
|
||||
var stubDispatchEvent;
|
||||
|
||||
function successCb(data) {
|
||||
successCbCalled = true;
|
||||
result = data;
|
||||
}
|
||||
|
||||
function errorCb(errorMsg) {
|
||||
errorCbCalled = true;
|
||||
error = errorMsg;
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
stubAddEventListener = this.sinon.stub(window, 'addEventListener',
|
||||
MockAddEventListener);
|
||||
stubRemoveEventListener = this.sinon.stub(window, 'removeEventListener',
|
||||
MockRemoveEventListener);
|
||||
stubDispatchEvent = this.sinon.stub(window, 'dispatchEvent',
|
||||
MockDispatchEvent);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubAddEventListener.restore();
|
||||
stubRemoveEventListener.restore();
|
||||
stubDispatchEvent.restore();
|
||||
});
|
||||
|
||||
suite('Init', function() {
|
||||
test('Integrity', function() {
|
||||
assert.isNotNull(FxAccountsClient);
|
||||
assert.equal(Object.keys(FxAccountsClient).length, 9);
|
||||
});
|
||||
|
||||
test('No event listeners', function() {
|
||||
assert.isUndefined(MockEventListener.mozFxAccountsChromeEvent);
|
||||
});
|
||||
});
|
||||
|
||||
// API calls
|
||||
|
||||
suite('getAccount', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getAccount(successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'getAccount'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAccount reply success', function() {
|
||||
setup(function() {
|
||||
MockEventListener.mozFxAccountsChromeEvent({
|
||||
detail: {
|
||||
id: MockDispatchedEvents[0].detail.id,
|
||||
data: expectedData
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
result = null;
|
||||
error = null;
|
||||
successCbCalled = false;
|
||||
errorCbCalled = false;
|
||||
});
|
||||
|
||||
test('On chrome event', function() {
|
||||
assert.isTrue(successCbCalled);
|
||||
assert.isFalse(errorCbCalled);
|
||||
assert.equal(result, expectedData);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAccount', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getAccount(successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'getAccount'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAccount reply error', function() {
|
||||
setup(function() {
|
||||
MockEventListener.mozFxAccountsChromeEvent({
|
||||
detail: {
|
||||
id: MockDispatchedEvents[0].detail.id,
|
||||
error: expectedError
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
result = null;
|
||||
error = null;
|
||||
successCbCalled = false;
|
||||
errorCbCalled = false;
|
||||
});
|
||||
|
||||
test('On chrome event', function() {
|
||||
assert.isFalse(successCbCalled);
|
||||
assert.isTrue(errorCbCalled);
|
||||
assert.equal(error, expectedError);
|
||||
});
|
||||
});
|
||||
|
||||
suite('logout', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.logout(successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'logout'
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
});
|
||||
|
||||
suite('queryAccount/verificationStatus', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.queryAccount('email', successCb, errorCb);
|
||||
FxAccountsClient.verificationStatus('email', successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 2);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[1].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.ok(MockDispatchedEvents[1].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'queryAccount',
|
||||
email: 'email'
|
||||
});
|
||||
assert.deepEqual(MockDispatchedEvents[1].detail.data, {
|
||||
method: 'verificationStatus',
|
||||
email: 'email'
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
});
|
||||
|
||||
suite('signIn/signUp', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.signIn('email', 'pass', successCb, errorCb);
|
||||
FxAccountsClient.signUp('email', 'pass', successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 2);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[1].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.ok(MockDispatchedEvents[1].detail.data);
|
||||
|
||||
var signInData = MockDispatchedEvents[0].detail.data;
|
||||
assert.equal(signInData.method, 'signIn');
|
||||
assert.equal(signInData.email, 'email');
|
||||
assert.equal(signInData.password, 'pass');
|
||||
assert.ok(signInData.fetchKeys !== undefined);
|
||||
|
||||
var signUpData = MockDispatchedEvents[1].detail.data;
|
||||
assert.equal(signUpData.method, 'signUp');
|
||||
assert.equal(signUpData.email, 'email');
|
||||
assert.equal(signUpData.password, 'pass');
|
||||
assert.ok(signUpData.fetchKeys !== undefined);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
});
|
||||
|
||||
suite('resendVerificationEmail', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.resendVerificationEmail('email', successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'resendVerificationEmail',
|
||||
email: 'email'
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
});
|
||||
|
||||
suite('getKeys', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getKeys(successCb, errorCb);
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'getKeys'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getKeys response', function() {
|
||||
setup(function() {
|
||||
MockEventListener.mozFxAccountsChromeEvent({
|
||||
detail: {
|
||||
id: MockDispatchedEvents[0].detail.id,
|
||||
data: expectedData
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
result = null;
|
||||
error = null;
|
||||
successCbCalled = false;
|
||||
errorCbCalled = false;
|
||||
});
|
||||
|
||||
test('On chrome event', function() {
|
||||
assert.isTrue(successCbCalled);
|
||||
assert.isFalse(errorCbCalled);
|
||||
assert.equal(result, expectedData);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAssertion', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getAssertion({
|
||||
silent: true,
|
||||
audience: 'audience'
|
||||
}, successCb, errorCb);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'getAssertion',
|
||||
silent: true,
|
||||
audience: 'audience'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAssertion - no options', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getAssertion(null, successCb, errorCb);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
});
|
||||
|
||||
test('Event dispatched to chrome side', function() {
|
||||
assert.equal(MockDispatchedEvents.length, 1);
|
||||
assert.ok(MockEventListener.mozFxAccountsChromeEvent);
|
||||
assert.ok(MockDispatchedEvents[0].detail.id);
|
||||
assert.ok(MockDispatchedEvents[0].detail.data);
|
||||
assert.deepEqual(MockDispatchedEvents[0].detail.data, {
|
||||
method: 'getAssertion',
|
||||
silent: null,
|
||||
audience: null
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAssertion response', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient.getAssertion(null, successCb, errorCb);
|
||||
MockEventListener.mozFxAccountsChromeEvent({
|
||||
detail: {
|
||||
id: MockDispatchedEvents[0].detail.id,
|
||||
data: expectedData
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
MockDispatchedEvents = [];
|
||||
result = null;
|
||||
error = null;
|
||||
successCbCalled = false;
|
||||
errorCbCalled = false;
|
||||
});
|
||||
|
||||
test('On chrome event', function() {
|
||||
assert.isTrue(successCbCalled);
|
||||
assert.isFalse(errorCbCalled);
|
||||
assert.equal(result, expectedData);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
445
gaia/apps/system/test/unit/fx_accounts_manager_test.js
Executable file
445
gaia/apps/system/test/unit/fx_accounts_manager_test.js
Executable file
|
|
@ -0,0 +1,445 @@
|
|||
/* global FxAccountsClient, FxAccountsManager, FxAccountsUI,
|
||||
MocksHelper, MockIACPort */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/js/fx_accounts_manager.js');
|
||||
requireApp('system/test/unit/mock_fxa_client.js');
|
||||
requireApp('system/test/unit/mock_fxa_ui.js');
|
||||
requireApp('system/test/unit/mock_iac_handler.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
var MockEventListener = {};
|
||||
function MockAddEventListener(event, listener) {
|
||||
MockEventListener[event] = listener;
|
||||
}
|
||||
|
||||
var mocksHelperFxAManager = new MocksHelper([
|
||||
'FxAccountsClient',
|
||||
'FxAccountsUI',
|
||||
'IACHandler',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('system/FxAccountManager >', function() {
|
||||
var stubAddEventListener;
|
||||
|
||||
mocksHelperFxAManager.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
stubAddEventListener = this.sinon.stub(window, 'addEventListener',
|
||||
MockAddEventListener);
|
||||
FxAccountsManager.start();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
stubAddEventListener.restore();
|
||||
});
|
||||
|
||||
suite('Init', function() {
|
||||
test('Integrity', function() {
|
||||
assert.isNotNull(FxAccountsManager);
|
||||
assert.equal(Object.keys(FxAccountsManager).length, 5);
|
||||
});
|
||||
|
||||
test('Test event listeners', function() {
|
||||
assert.ok(MockEventListener['iac-fxa-mgmt']);
|
||||
assert.ok(MockEventListener['iac-fxa-mgmt'] instanceof Function);
|
||||
assert.ok(MockEventListener.mozFxAccountsUnsolChromeEvent);
|
||||
assert.ok(MockEventListener.mozFxAccountsUnsolChromeEvent instanceof
|
||||
Object);
|
||||
});
|
||||
});
|
||||
|
||||
suite('On getAccount port message, successCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._successMsg = 'success';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'getAccount'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.getAccount called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'getAccount');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'getAccount',
|
||||
'data': 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On getAccount port message, errorCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._errorMsg = 'error';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'getAccount'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.getAccount called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'getAccount');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'getAccount',
|
||||
'error': 'error'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On logout port message, successCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._successMsg = 'success';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'logout'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.logout called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'logout');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'logout',
|
||||
'data': 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On logout port message, errorCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._errorMsg = 'error';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'logout'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.logout called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'logout');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'logout',
|
||||
'error': 'error'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On openFlow port message, successCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsUI._successMsg = 'success';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'openFlow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.login called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'login');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'openFlow',
|
||||
'data': 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On openFlow port message, errorCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsUI._errorMsg = 'error';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'openFlow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.login called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'login');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'openFlow',
|
||||
'error': 'error'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On openFlow mozFxAccountsRPChromeEvent', function() {
|
||||
var id = 123;
|
||||
var dispatchEventStub;
|
||||
setup(function() {
|
||||
dispatchEventStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
|
||||
FxAccountsUI._successMsg = 'success';
|
||||
FxAccountsManager.handleEvent({
|
||||
'detail': {
|
||||
'id': id,
|
||||
'eventName': 'openFlow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
dispatchEventStub.restore();
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.login called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'login');
|
||||
});
|
||||
|
||||
test('on FxAccountsUI reply sendContentEvent', function() {
|
||||
sinon.assert.calledOnce(dispatchEventStub);
|
||||
});
|
||||
});
|
||||
|
||||
suite('On refreshAuthentication port message, successCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsUI._successMsg = 'success';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'refreshAuthentication',
|
||||
'email': 'dummy@domain.org'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.refreshAuthentication called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'refreshAuthentication');
|
||||
assert.equal(FxAccountsUI._email, 'dummy@domain.org');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'refreshAuthentication',
|
||||
'data': 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On refreshAuthentication port message, errorCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsUI._errorMsg = 'error';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'refreshAuthentication',
|
||||
'email': 'dummy@domain.org'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.refreshAuthentication called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'refreshAuthentication');
|
||||
assert.equal(FxAccountsUI._email, 'dummy@domain.org');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'refreshAuthentication',
|
||||
'error': 'error'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On refreshAuthentication mozFxAccountsRPChromeEvent', function() {
|
||||
var id = 123;
|
||||
var dispatchEventStub;
|
||||
setup(function() {
|
||||
dispatchEventStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
|
||||
FxAccountsUI._successMsg = 'success';
|
||||
FxAccountsManager.handleEvent({
|
||||
'detail': {
|
||||
'id': id,
|
||||
'eventName': 'refreshAuthentication',
|
||||
'data': {
|
||||
'email': 'dummy@domain.org'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
dispatchEventStub.restore();
|
||||
FxAccountsUI._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsUI.refreshAuthentication called', function() {
|
||||
assert.equal(FxAccountsUI._call, 'refreshAuthentication');
|
||||
assert.equal(FxAccountsUI._email, 'dummy@domain.org');
|
||||
});
|
||||
|
||||
test('on FxAccountsUI reply sendContentEvent', function() {
|
||||
sinon.assert.calledOnce(dispatchEventStub);
|
||||
});
|
||||
});
|
||||
|
||||
suite('On resendVerificationEmail port message, successCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._successMsg = 'success';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'resendVerificationEmail',
|
||||
'email': 'dummy@domain.org'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.resendVerificationEmail called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'resendVerificationEmail');
|
||||
assert.equal(FxAccountsClient._email, 'dummy@domain.org');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'resendVerificationEmail',
|
||||
'data': 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('On resendVerificationEmail port message, errorCb', function() {
|
||||
setup(function() {
|
||||
FxAccountsClient._errorMsg = 'error';
|
||||
FxAccountsManager.onPortMessage({
|
||||
'detail': {
|
||||
'name': 'resendVerificationEmail',
|
||||
'email': 'dummy@domain.org'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsClient._reset();
|
||||
});
|
||||
|
||||
test('FxAccountsClient.resendVerificationEmail called', function() {
|
||||
assert.equal(FxAccountsClient._call, 'resendVerificationEmail');
|
||||
assert.equal(FxAccountsClient._email, 'dummy@domain.org');
|
||||
});
|
||||
|
||||
test('Got fxa-mgmt port', function() {
|
||||
assert.equal(MockIACPort._name, 'fxa-mgmt');
|
||||
});
|
||||
|
||||
test('Sent success message through port', function() {
|
||||
assert.equal(MockIACPort._messages.length, 1);
|
||||
assert.ok(MockIACPort._messages[0] instanceof Object);
|
||||
assert.deepEqual(MockIACPort._messages[0], {
|
||||
'methodName': 'resendVerificationEmail',
|
||||
'error': 'error'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
163
gaia/apps/system/test/unit/fxa_dialog_test.js
Executable file
163
gaia/apps/system/test/unit/fxa_dialog_test.js
Executable file
|
|
@ -0,0 +1,163 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, FxAccountsDialog, SystemDialog, LayoutManager */
|
||||
|
||||
require('/test/unit/mock_app_window_manager.js');
|
||||
require('/test/unit/mock_layout_manager.js');
|
||||
require('/test/unit/mock_system_dialog_manager.js');
|
||||
require('/test/unit/mock_keyboard_manager.js');
|
||||
require('/js/service.js');
|
||||
require('/js/base_ui.js');
|
||||
require('/js/system_dialog.js');
|
||||
require('/js/fxa_dialog.js');
|
||||
|
||||
var mocksForFxAccountsDialog = new MocksHelper([
|
||||
'AppWindowManager',
|
||||
'LayoutManager',
|
||||
'SystemDialogManager',
|
||||
'KeyboardManager'
|
||||
]).init();
|
||||
|
||||
suite('system/FxAccountsDialog', function() {
|
||||
var stubDispatch, container,
|
||||
fakeOptions = {
|
||||
onShow: function() {},
|
||||
onHide: function() {}
|
||||
};
|
||||
mocksForFxAccountsDialog.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
SystemDialog.prototype.containerElement = container;
|
||||
|
||||
stubDispatch = this.sinon.stub(window, 'dispatchEvent');
|
||||
|
||||
window.layoutManager = new LayoutManager();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
document.body.removeChild(container);
|
||||
SystemDialog.prototype.containerElement = container = null;
|
||||
|
||||
stubDispatch.restore();
|
||||
|
||||
window.layoutManager = null;
|
||||
});
|
||||
|
||||
suite('Handle events', function() {
|
||||
test('Create system dialog would trigger events', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
assert.isTrue(stubDispatch.calledWithMatch(sinon.match(
|
||||
function(e) {
|
||||
return 'system-dialog-created' === e.type;
|
||||
})),
|
||||
'the event has not been fired');
|
||||
fxAccountsDialog = null;
|
||||
});
|
||||
|
||||
test('Show system dialog would trigger events', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
fxAccountsDialog.show();
|
||||
assert.isTrue(stubDispatch.calledWithMatch(sinon.match(
|
||||
function(e) {
|
||||
return 'system-dialog-show' === e.type;
|
||||
})),
|
||||
'the event has not been fired');
|
||||
});
|
||||
|
||||
test('Hide system dialog would trigger events', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
fxAccountsDialog.hide();
|
||||
assert.isTrue(stubDispatch.calledWithMatch(sinon.match(
|
||||
function(e) {
|
||||
return 'system-dialog-hide' === e.type;
|
||||
})),
|
||||
'the event has not been fired');
|
||||
});
|
||||
|
||||
test('The attribute "onShow" should be called with reason ' +
|
||||
'after system dialog is shown.', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
var stubOnShowCallback = this.sinon.stub(fxAccountsDialog.options,
|
||||
'onShow');
|
||||
var fakeReason = null;
|
||||
fxAccountsDialog.onShow(fakeReason);
|
||||
assert.isTrue(stubOnShowCallback.calledWith(null));
|
||||
});
|
||||
|
||||
test('The attribute "onHide" should be called with reason ' +
|
||||
'after system dialog is hidden.', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
var stubOnHideCallback = this.sinon.stub(fxAccountsDialog.options,
|
||||
'onHide');
|
||||
var fakeReason = 'home';
|
||||
fxAccountsDialog.onHide(fakeReason);
|
||||
assert.isTrue(stubOnHideCallback.calledWith('home'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Create instance ID', function() {
|
||||
test('Create system Firefox accounts dialog ' +
|
||||
'would create instanceID = "fxa-dialog"', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
assert.equal('fxa-dialog', fxAccountsDialog.instanceID);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Get element', function() {
|
||||
test('Return element while called getView() function', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
var stubGetView = this.sinon.stub(fxAccountsDialog, 'getView');
|
||||
fxAccountsDialog.getView();
|
||||
assert.isTrue(stubGetView.called);
|
||||
});
|
||||
|
||||
test('Create system Firefox accounts dialog ' +
|
||||
'would get dialog element.', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
assert.isNotNull(fxAccountsDialog.element);
|
||||
});
|
||||
|
||||
test('Created system dialog should be hidden', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
assert.isTrue(fxAccountsDialog.element.hidden,
|
||||
'Element is created hidden.');
|
||||
});
|
||||
});
|
||||
|
||||
suite('Resize functions', function() {
|
||||
var isCalled;
|
||||
|
||||
setup(function(done) {
|
||||
isCalled = false;
|
||||
Object.defineProperty(FxAccountsDialog.prototype.containerElement.style,
|
||||
'height', {
|
||||
configurable: true,
|
||||
set: function() {
|
||||
isCalled = true;
|
||||
}
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete FxAccountsDialog.prototype.containerElement.style.height;
|
||||
});
|
||||
|
||||
test('The dialog height should be updated ' +
|
||||
'while "updateHeight()" called.', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
fxAccountsDialog.updateHeight();
|
||||
assert.isTrue(isCalled);
|
||||
});
|
||||
|
||||
test('The dialog height should be updated ' +
|
||||
'while resize request is coming.', function() {
|
||||
var fxAccountsDialog = new window.FxAccountsDialog(fakeOptions);
|
||||
fxAccountsDialog.resize();
|
||||
assert.isTrue(isCalled);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
326
gaia/apps/system/test/unit/fxa_iac_client_test.js
Executable file
326
gaia/apps/system/test/unit/fxa_iac_client_test.js
Executable file
|
|
@ -0,0 +1,326 @@
|
|||
/* global FxAccountsIACHelper, MockApp, MockAppsMgmt */
|
||||
'use strict';
|
||||
|
||||
requireApp('system/test/unit/mock_apps_mgmt.js');
|
||||
requireApp('system/test/unit/mock_app.js');
|
||||
// XXX consider moving this to a separate file if it gets much more complex
|
||||
|
||||
// arthurcc's suggested replacement:
|
||||
var port = {
|
||||
postMessage: function(message) {
|
||||
var msg = {
|
||||
data: {
|
||||
data: {},
|
||||
methodName: message.name
|
||||
}
|
||||
};
|
||||
setTimeout(function() {
|
||||
port._onmessage(msg);
|
||||
});
|
||||
},
|
||||
_onmessage: null,
|
||||
set onmessage(cb) {
|
||||
port._onmessage = cb;
|
||||
}
|
||||
};
|
||||
|
||||
suite('FirefoxOS Accounts IAC Client Suite', function() {
|
||||
var realMozApps;
|
||||
|
||||
var postMessageSpy;
|
||||
|
||||
suiteSetup(function() {
|
||||
realMozApps = navigator.mozApps;
|
||||
navigator.mozApps = MockAppsMgmt;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozApps = realMozApps;
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
// For each test, setup the 'self' app, able to
|
||||
// do IAC
|
||||
var app = new MockApp({
|
||||
'connect': function(keyword) {
|
||||
var future = {
|
||||
'then': function(cb) {}
|
||||
};
|
||||
sinon.stub(future, 'then', function(cb) {
|
||||
cb([port]);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
});
|
||||
navigator.mozApps.setSelf(app);
|
||||
// XXX we have to require() the system under test *after* we define the
|
||||
// MockApp, because the code calls app.connect() as soon as it is loaded
|
||||
require('/shared/js/fxa_iac_client.js', done);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
if (postMessageSpy && postMessageSpy.restore) {
|
||||
postMessageSpy.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('Library integrity', function() {
|
||||
assert.isNotNull(FxAccountsIACHelper);
|
||||
assert.equal(Object.keys(FxAccountsIACHelper).length, 9);
|
||||
});
|
||||
|
||||
['getAccount', 'openFlow', 'logout'].forEach(function(method) {
|
||||
suite(method + ' suite', function() {
|
||||
setup(function() {
|
||||
postMessageSpy = sinon.spy(port, 'postMessage');
|
||||
});
|
||||
|
||||
test('Check that we send the ' + method + ' message', function(done) {
|
||||
this.timeout(20000);
|
||||
port.methodName = method;
|
||||
FxAccountsIACHelper[method](
|
||||
function() {
|
||||
assert.ok(postMessageSpy.called);
|
||||
var arg = postMessageSpy.args[0][0];
|
||||
// We do have an id for this message
|
||||
assert.isNotNull(arg.id);
|
||||
assert.isNotNull(arg);
|
||||
// Remove the id, as it's automatically generated
|
||||
delete arg.id;
|
||||
|
||||
assert.deepEqual(arg, {
|
||||
'name': method
|
||||
});
|
||||
done();
|
||||
},
|
||||
function() {
|
||||
// Break if we are called.
|
||||
assert.ok(false);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
postMessageSpy.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('refreshAuthentication suite', function() {
|
||||
setup(function() {
|
||||
postMessageSpy = sinon.spy(port, 'postMessage');
|
||||
});
|
||||
|
||||
test('Check that we send the refreshAuth message', function(done) {
|
||||
this.timeout(20000);
|
||||
port.methodName = 'refreshAuthentication';
|
||||
FxAccountsIACHelper.refreshAuthentication('dummy@domain.org',
|
||||
function() {
|
||||
assert.ok(postMessageSpy.called);
|
||||
var arg = postMessageSpy.args[0][0];
|
||||
// We do have an id for this message
|
||||
assert.isNotNull(arg.id);
|
||||
assert.isNotNull(arg);
|
||||
// Remove the id, as it's automatically generated
|
||||
delete arg.id;
|
||||
|
||||
assert.deepEqual(arg, {
|
||||
'name': 'refreshAuthentication',
|
||||
'email': 'dummy@domain.org'
|
||||
});
|
||||
done();
|
||||
},
|
||||
function() {
|
||||
// Break if we are called.
|
||||
assert.ok(false);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
postMessageSpy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('resendVerificationEmail suite', function() {
|
||||
setup(function() {
|
||||
postMessageSpy = sinon.spy(port, 'postMessage');
|
||||
});
|
||||
|
||||
test('Check that we send the resend message', function(done) {
|
||||
this.timeout(20000);
|
||||
port.methodName = 'resendVerificationEmail';
|
||||
FxAccountsIACHelper.resendVerificationEmail('dummy@domain.org',
|
||||
function() {
|
||||
assert.ok(postMessageSpy.called);
|
||||
var arg = postMessageSpy.args[0][0];
|
||||
// We do have an id for this message
|
||||
assert.isNotNull(arg.id);
|
||||
assert.isNotNull(arg);
|
||||
// Remove the id, as it's automatically generated
|
||||
delete arg.id;
|
||||
|
||||
assert.deepEqual(arg, {
|
||||
'name': 'resendVerificationEmail',
|
||||
'email': 'dummy@domain.org'
|
||||
});
|
||||
done();
|
||||
},
|
||||
function() {
|
||||
// Break if we are called.
|
||||
assert.ok(false);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
postMessageSpy.restore();
|
||||
});
|
||||
});
|
||||
|
||||
suite('addEventListener tests', function() {
|
||||
var callbackCalled = false;
|
||||
var otherCallbackCalled = false;
|
||||
|
||||
var listener = function() {
|
||||
callbackCalled = true;
|
||||
};
|
||||
|
||||
var otherListener = function() {
|
||||
otherCallbackCalled = true;
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
FxAccountsIACHelper.addEventListener('myEvent', listener);
|
||||
FxAccountsIACHelper.addEventListener('myOtherEvent', otherListener);
|
||||
|
||||
port._onmessage({
|
||||
data: {
|
||||
data: {},
|
||||
eventName: 'myEvent'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Check that we trigger the appropriate callback', function() {
|
||||
assert.ok(callbackCalled);
|
||||
assert.ok(!otherCallbackCalled);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxAccountsIACHelper.removeEventListener('myEvent', listener);
|
||||
FxAccountsIACHelper.removeEventListener('myOtherEvent', otherListener);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
suite('removeEventListener tests', function() {
|
||||
var callbackCalled = false;
|
||||
var otherCallbackCalled = false;
|
||||
|
||||
var listener = function() {
|
||||
callbackCalled = true;
|
||||
};
|
||||
|
||||
var otherListener = function() {
|
||||
otherCallbackCalled = true;
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
FxAccountsIACHelper.addEventListener('myEvent', listener);
|
||||
FxAccountsIACHelper.addEventListener('myOtherEvent', otherListener);
|
||||
FxAccountsIACHelper.removeEventListener('myEvent', listener);
|
||||
|
||||
port._onmessage({
|
||||
data: {
|
||||
data: {},
|
||||
eventName: 'myEvent'
|
||||
}
|
||||
});
|
||||
|
||||
port._onmessage({
|
||||
data: {
|
||||
data: {},
|
||||
eventName: 'myOtherEvent'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Check that we trigger the appropriate callback', function() {
|
||||
assert.ok(!callbackCalled);
|
||||
assert.ok(otherCallbackCalled);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
suite('Startup race condition tests - bug 974108', function() {
|
||||
var callbackCalled, otherCallbackCalled;
|
||||
|
||||
var listener = function() {
|
||||
callbackCalled = true;
|
||||
};
|
||||
|
||||
var otherListener = function() {
|
||||
otherCallbackCalled = true;
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
this.clock = sinon.useFakeTimers();
|
||||
callbackCalled = false;
|
||||
otherCallbackCalled = false;
|
||||
// we are testing that postmessage requests are queued, not overwritten,
|
||||
// during the period between starting the Helper and the port being open.
|
||||
// we need to clear out the port, add 2 new subscribers, then check both
|
||||
// are called.
|
||||
var app = new MockApp({
|
||||
'connect': function(keyword) {
|
||||
var future = {
|
||||
'then': function(cb) {}
|
||||
};
|
||||
sinon.stub(future, 'then', function(cb) {
|
||||
// wait a turn so that we can queue up multiple requests
|
||||
setTimeout(function() {
|
||||
cb([port]);
|
||||
}, 0);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
});
|
||||
navigator.mozApps.setSelf(app);
|
||||
FxAccountsIACHelper.reset();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.clock.restore();
|
||||
});
|
||||
|
||||
test('Should queue multiple requests until port is opened', function() {
|
||||
callbackCalled = false;
|
||||
otherCallbackCalled = false;
|
||||
// reset() will destroy the existing port, forcing message requests
|
||||
// to be queued up.
|
||||
FxAccountsIACHelper.reset();
|
||||
// two requests -- one to be sent as soon as the connection's ready,
|
||||
// the other after that.
|
||||
FxAccountsIACHelper.logout(otherListener);
|
||||
FxAccountsIACHelper.getAccount(listener);
|
||||
this.clock.tick(1000);
|
||||
assert.isTrue(callbackCalled);
|
||||
assert.isTrue(otherCallbackCalled);
|
||||
});
|
||||
|
||||
test('Should queue multiple callbacks for one request', function() {
|
||||
callbackCalled = false;
|
||||
otherCallbackCalled = false;
|
||||
FxAccountsIACHelper.reset();
|
||||
FxAccountsIACHelper.getAccount(listener);
|
||||
FxAccountsIACHelper.getAccount(otherListener);
|
||||
this.clock.tick(1000);
|
||||
assert.isTrue(callbackCalled);
|
||||
assert.isTrue(otherCallbackCalled);
|
||||
});
|
||||
});
|
||||
});
|
||||
38
gaia/apps/system/test/unit/fxa_test/fxa_error_overlay_test.js
Executable file
38
gaia/apps/system/test/unit/fxa_test/fxa_error_overlay_test.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
/* global FxaModuleErrorOverlay */
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/utilities.js');
|
||||
requireApp('system/fxa/js/fxam_error_overlay.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
suite('FxA Module Error Overlay', function() {
|
||||
var overlay, title, message;
|
||||
suiteSetup(function() {
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
overlay = document.querySelector('#fxa-error-overlay');
|
||||
title = document.querySelector('#fxa-error-title');
|
||||
message = document.querySelector('#fxa-error-msg');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
overlay = null;
|
||||
title = null;
|
||||
message = null;
|
||||
});
|
||||
|
||||
test('show', function() {
|
||||
var customTitleL10nId = 'l10nId1';
|
||||
var customTextL10nId = 'l10nId2';
|
||||
FxaModuleErrorOverlay.show(customTitleL10nId, customTextL10nId);
|
||||
|
||||
assert.equal(title.getAttribute('data-l10n-id'), customTitleL10nId);
|
||||
assert.equal(message.getAttribute('data-l10n-id'), customTextL10nId);
|
||||
assert.ok(overlay.classList.contains('show'));
|
||||
});
|
||||
|
||||
test('hide', function() {
|
||||
FxaModuleErrorOverlay.hide();
|
||||
assert.isFalse(overlay.classList.contains('show'));
|
||||
});
|
||||
});
|
||||
76
gaia/apps/system/test/unit/fxa_test/fxam_errors_test.js
Executable file
76
gaia/apps/system/test/unit/fxa_test/fxam_errors_test.js
Executable file
|
|
@ -0,0 +1,76 @@
|
|||
/* global FxaModuleErrors, MockL10n */
|
||||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('system/fxa/js/fxam_errors.js');
|
||||
|
||||
suite('Error manager', function() {
|
||||
var errorsObject = {
|
||||
CONNECTION_ERROR: {
|
||||
title: 'fxa-connection-error-title',
|
||||
message: 'fxa-connection-error-message'
|
||||
},
|
||||
RESET_PASSWORD_ERROR: {
|
||||
title: 'fxa-reset-password-error-title',
|
||||
message: 'fxa-reset-password-error-message'
|
||||
},
|
||||
INVALID_EMAIL: {
|
||||
title: 'fxa-invalid-email-title',
|
||||
message: 'fxa-invalid-email-message'
|
||||
},
|
||||
INVALID_PASSWORD: {
|
||||
title: 'fxa-invalid-password-title',
|
||||
message: 'fxa-invalid-password-message'
|
||||
},
|
||||
COPPA_ERROR: {
|
||||
title: 'fxa-coppa-failure-error-title',
|
||||
message: 'fxa-coppa-failure-error-message3'
|
||||
},
|
||||
COPPA_FTU_ERROR: {
|
||||
title: 'fxa-coppa-failure-error-title',
|
||||
message: 'fxa-coppa-ftu-error-message'
|
||||
},
|
||||
OFFLINE: {
|
||||
title: 'fxa-offline-error-title',
|
||||
message: 'fxa-offline-error-message'
|
||||
},
|
||||
UNKNOWN: {
|
||||
title: 'fxa-unknown-error-title',
|
||||
message: 'fxa-unknown-error-message'
|
||||
}
|
||||
};
|
||||
var response;
|
||||
var realL10n;
|
||||
suiteSetup(function() {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
|
||||
setup(function() {
|
||||
response = {};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
response = null;
|
||||
});
|
||||
|
||||
Object.keys(errorsObject).forEach(function(key) {
|
||||
test('Test ' + key, function() {
|
||||
response.error = key;
|
||||
var resp = FxaModuleErrors.responseToParams(response);
|
||||
|
||||
var message = errorsObject[key].message;
|
||||
|
||||
assert.deepEqual(resp, {
|
||||
title: errorsObject[key].title,
|
||||
message: message
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
34
gaia/apps/system/test/unit/fxa_test/fxam_overlay_test.js
Executable file
34
gaia/apps/system/test/unit/fxa_test/fxam_overlay_test.js
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
/* global FxaModuleOverlay */
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/utilities.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_module.js');
|
||||
requireApp('system/fxa/js/fxam_overlay.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
suite('FxA Module overlay', function() {
|
||||
var overlay;
|
||||
suiteSetup(function() {
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
overlay = document.querySelector('#fxa-overlay');
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
overlay = null;
|
||||
});
|
||||
|
||||
test('show', function() {
|
||||
var customL10nId = 'l10nId1';
|
||||
FxaModuleOverlay.show(customL10nId);
|
||||
var messageContainer = document.querySelector('#fxa-overlay-msg');
|
||||
assert.equal(messageContainer.getAttribute('data-l10n-id'), customL10nId);
|
||||
assert.ok(overlay.classList.contains('show'));
|
||||
});
|
||||
|
||||
test('hide', function() {
|
||||
FxaModuleOverlay.hide();
|
||||
assert.isFalse(overlay.classList.contains('show'));
|
||||
});
|
||||
});
|
||||
14
gaia/apps/system/test/unit/fxa_test/load_element_helper.js
Executable file
14
gaia/apps/system/test/unit/fxa_test/load_element_helper.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
/* exported LoadElementHelper */
|
||||
|
||||
require('/shared/js/html_imports.js');
|
||||
|
||||
var LoadElementHelper = {
|
||||
load: function(element) {
|
||||
var importHook = document.createElement('link');
|
||||
importHook.setAttribute('rel', 'import');
|
||||
importHook.setAttribute('href', '/fxa/elements/' + element);
|
||||
document.head.appendChild(importHook);
|
||||
}
|
||||
};
|
||||
|
||||
11
gaia/apps/system/test/unit/fxa_test/mock_fxam_errors.js
Executable file
11
gaia/apps/system/test/unit/fxa_test/mock_fxam_errors.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
/* exported MockFxaModuleErrors */
|
||||
|
||||
var MockFxaModuleErrors = {
|
||||
responseToParams: function(response) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
61
gaia/apps/system/test/unit/fxa_test/mock_fxam_server_request.js
Executable file
61
gaia/apps/system/test/unit/fxa_test/mock_fxam_server_request.js
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
/* exported MockFxModuleServerRequest */
|
||||
|
||||
var MockFxModuleServerRequest = {
|
||||
error: false,
|
||||
registered: false,
|
||||
authenticated: false,
|
||||
accountCreated: false,
|
||||
resetSuccess: false,
|
||||
checkEmail: function(email, onsuccess, onerror) {
|
||||
if (!this.error) {
|
||||
setTimeout(function() {
|
||||
var params = {
|
||||
registered: this.registered
|
||||
};
|
||||
onsuccess && onsuccess(params);
|
||||
}.bind(this));
|
||||
} else {
|
||||
onerror && onerror();
|
||||
}
|
||||
},
|
||||
signIn: function(email, password, onsuccess, onerror) {
|
||||
if (!this.error) {
|
||||
setTimeout(function() {
|
||||
var params = {
|
||||
authenticated: this.authenticated
|
||||
};
|
||||
onsuccess && onsuccess(params);
|
||||
}.bind(this));
|
||||
} else {
|
||||
onerror && onerror();
|
||||
}
|
||||
},
|
||||
signUp: function(email, password, onsuccess, onerror) {
|
||||
if (!this.error) {
|
||||
setTimeout(function() {
|
||||
var params = {
|
||||
accountCreated: this.accountCreated
|
||||
};
|
||||
onsuccess && onsuccess(params);
|
||||
}.bind(this));
|
||||
} else {
|
||||
onerror && onerror();
|
||||
}
|
||||
},
|
||||
requestPasswordReset: function(email, onsuccess, onerror) {
|
||||
if (!this.error) {
|
||||
setTimeout(function() {
|
||||
var params = {
|
||||
success: this.resetSuccess
|
||||
};
|
||||
onsuccess && onsuccess(params);
|
||||
}.bind(this));
|
||||
} else {
|
||||
onerror && onerror();
|
||||
}
|
||||
}
|
||||
};
|
||||
42
gaia/apps/system/test/unit/fxa_test/mock_fxam_ui.js
Executable file
42
gaia/apps/system/test/unit/fxa_test/mock_fxam_ui.js
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
/* exported MockFxaModuleUI */
|
||||
|
||||
var MockFxaModuleUI = {
|
||||
maxSteps: null,
|
||||
init: function(flow) {
|
||||
|
||||
},
|
||||
setMaxSteps: function(num) {
|
||||
|
||||
},
|
||||
increaseMaxStepsBy: function(num) {
|
||||
},
|
||||
loadScreen: function(params) {
|
||||
|
||||
},
|
||||
_animate: function(from, to, back, callback) {
|
||||
|
||||
},
|
||||
_inTransition: function(elem) {
|
||||
|
||||
},
|
||||
progress: function(value) {
|
||||
|
||||
},
|
||||
setNextText: function(l10n) {
|
||||
|
||||
},
|
||||
disableNextButton: function() {
|
||||
|
||||
},
|
||||
enableNextButton: function() {
|
||||
|
||||
},
|
||||
disableDoneButton: function() {
|
||||
},
|
||||
enableDoneButton: function() {
|
||||
}
|
||||
};
|
||||
155
gaia/apps/system/test/unit/fxa_test/screens/fxam_coppa_test.js
Executable file
155
gaia/apps/system/test/unit/fxa_test/screens/fxam_coppa_test.js
Executable file
|
|
@ -0,0 +1,155 @@
|
|||
'use strict';
|
||||
|
||||
/* global MocksHelper, MockL10n, LoadElementHelper, HtmlImports, FxaModuleUI,
|
||||
FxaModuleCoppa, FxaModuleErrorOverlay, FxaModuleStates */
|
||||
|
||||
// Helper for loading the elements
|
||||
requireApp('/system/test/unit/fxa_test/load_element_helper.js');
|
||||
|
||||
// Real code
|
||||
require('/shared/js/utilities.js');
|
||||
requireApp('system/fxa/js/fxam_module.js');
|
||||
requireApp('system/fxa/js/fxam_states.js');
|
||||
requireApp('system/fxa/js/fxam_manager.js');
|
||||
requireApp('system/fxa/js/fxam_navigation.js');
|
||||
requireApp('system/fxa/js/fxam_overlay.js');
|
||||
requireApp('system/fxa/js/fxam_error_overlay.js');
|
||||
|
||||
// Mockuped code
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_ui.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_server_request.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_errors.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
// Code to test
|
||||
requireApp('system/fxa/js/screens/fxam_coppa.js');
|
||||
|
||||
var mocksHelperForCoppaModule = new MocksHelper([
|
||||
'FxaModuleUI',
|
||||
'FxModuleServerRequest',
|
||||
'FxaModuleErrors',
|
||||
'LazyLoader'
|
||||
]);
|
||||
|
||||
suite('Screen: COPPA', function() {
|
||||
var realL10n;
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
mocksHelperForCoppaModule.suiteSetup();
|
||||
// Load real HTML
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
// Load element to test
|
||||
LoadElementHelper.load('fxa-coppa.html');
|
||||
// Import the element and execute the right init
|
||||
HtmlImports.populate(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
document.body.innerHTML = '';
|
||||
mocksHelperForCoppaModule.suiteTeardown();
|
||||
});
|
||||
|
||||
suite(' > Initial state', function() {
|
||||
var fxamUIEnableSpy;
|
||||
var fxamUIIncStepsSpy;
|
||||
setup(function() {
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableNextButton');
|
||||
fxamUIIncStepsSpy = this.sinon.spy(FxaModuleUI, 'increaseMaxStepsBy');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fxamUIEnableSpy = null;
|
||||
fxamUIIncStepsSpy = null;
|
||||
});
|
||||
|
||||
test(' > FxaModuleUI not called', function(done) {
|
||||
assert.isFalse(fxamUIEnableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIIncStepsSpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > Initiated state', function() {
|
||||
var fxamUIEnableSpy;
|
||||
var fxamUIIncStepsSpy;
|
||||
setup(function() {
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableNextButton');
|
||||
fxamUIIncStepsSpy = this.sinon.spy(FxaModuleUI, 'increaseMaxStepsBy');
|
||||
FxaModuleCoppa.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fxamUIEnableSpy = null;
|
||||
fxamUIIncStepsSpy = null;
|
||||
});
|
||||
|
||||
test(' > FxaModuleUI called', function(done) {
|
||||
assert.isFalse(fxamUIEnableSpy.calledOnce);
|
||||
assert.ok(fxamUIIncStepsSpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
|
||||
test(' > We only populate the age selection element once', function() {
|
||||
var fxaAgeSelect = document.getElementById('fxa-age-select');
|
||||
var selectLength = fxaAgeSelect.length;
|
||||
FxaModuleCoppa.init();
|
||||
assert.equal(selectLength, fxaAgeSelect.length);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > COPPA error', function() {
|
||||
var fxaAgeSelect;
|
||||
var showErrorOverlaySpy;
|
||||
var showErrorResponse;
|
||||
setup(function() {
|
||||
fxaAgeSelect = document.getElementById('fxa-age-select');
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
showErrorResponse = this.sinon.spy(FxaModuleCoppa, 'showErrorResponse');
|
||||
fxaAgeSelect.value = new Date().getFullYear();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fxaAgeSelect = null;
|
||||
showErrorOverlaySpy = null;
|
||||
showErrorResponse = null;
|
||||
});
|
||||
|
||||
test(' > COPPA error shown', function(done) {
|
||||
FxaModuleCoppa.onNext(function() { });
|
||||
setTimeout(function() {
|
||||
assert.ok(showErrorOverlaySpy.calledOnce);
|
||||
assert.ok(showErrorResponse.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > COPPA success', function() {
|
||||
var fxaAgeSelect;
|
||||
var MINIMUM_AGE = 13;
|
||||
setup(function() {
|
||||
fxaAgeSelect = document.getElementById('fxa-age-select');
|
||||
fxaAgeSelect.value = new Date().getFullYear() - MINIMUM_AGE;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fxaAgeSelect = null;
|
||||
});
|
||||
|
||||
test(' > COPPA success', function(done) {
|
||||
FxaModuleCoppa.onNext(function(a) {
|
||||
assert.deepEqual(a, FxaModuleStates.SET_PASSWORD);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
305
gaia/apps/system/test/unit/fxa_test/screens/fxam_enter_email_test.js
Executable file
305
gaia/apps/system/test/unit/fxa_test/screens/fxam_enter_email_test.js
Executable file
|
|
@ -0,0 +1,305 @@
|
|||
/* global FxaModuleEnterEmail, FxaModuleErrorOverlay, FxaModuleOverlay,
|
||||
FxModuleServerRequest, FxaModuleStates, FxaModuleUI,
|
||||
HtmlImports, LoadElementHelper, MocksHelper, MockL10n */
|
||||
'use strict';
|
||||
|
||||
// Helper for loading the elements
|
||||
requireApp('/system/test/unit/fxa_test/load_element_helper.js');
|
||||
|
||||
// Real code
|
||||
require('/shared/js/utilities.js');
|
||||
requireApp('system/fxa/js/fxam_module.js');
|
||||
requireApp('system/fxa/js/fxam_states.js');
|
||||
requireApp('system/fxa/js/fxam_manager.js');
|
||||
requireApp('system/fxa/js/fxam_overlay.js');
|
||||
requireApp('system/js/browser_frame.js');
|
||||
requireApp('system/js/entry_sheet.js');
|
||||
requireApp('system/fxa/js/fxam_error_overlay.js');
|
||||
|
||||
// Mockuped code
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_ui.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_ui.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_server_request.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_server_request.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_errors.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_errors.js');
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
// Code to test
|
||||
requireApp('system/fxa/js/screens/fxam_enter_email.js');
|
||||
|
||||
var mocksHelperForEmailModule = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'FxaModuleUI',
|
||||
'FxModuleServerRequest',
|
||||
'FxaModuleErrors'
|
||||
]);
|
||||
|
||||
suite('Screen: Enter email', function() {
|
||||
var realL10n;
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
// we have to special-case the l10n stub for the fxa-notice element
|
||||
var l10nStub = sinon.stub(navigator.mozL10n, 'get');
|
||||
var noticeStr = 'By proceeding, I agree to the {{ tos }} and {{ pn }} ' +
|
||||
'Firefox cloud services';
|
||||
l10nStub.withArgs('fxa-notice')
|
||||
.returns(noticeStr);
|
||||
|
||||
mocksHelperForEmailModule.suiteSetup();
|
||||
// Load real HTML
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
// Load element to test
|
||||
LoadElementHelper.load('fxa-email.html');
|
||||
// Import the element and execute the right init
|
||||
HtmlImports.populate(function() {
|
||||
FxaModuleEnterEmail.init();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
document.body.innerHTML = '';
|
||||
mocksHelperForEmailModule.suiteTeardown();
|
||||
});
|
||||
|
||||
suite(' > External links EntrySheet ', function() {
|
||||
var privacyLink, termsLink, showErrorOverlaySpy, clickEvent,
|
||||
closeEntrySheetSpy, mockEntrySheet;
|
||||
|
||||
setup(function() {
|
||||
privacyLink = document.getElementById('fxa-privacy');
|
||||
termsLink = document.getElementById('fxa-terms');
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
clickEvent = new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
view: window
|
||||
});
|
||||
closeEntrySheetSpy = sinon.spy();
|
||||
mockEntrySheet = {close: closeEntrySheetSpy};
|
||||
FxaModuleEnterEmail.entrySheet = mockEntrySheet;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
FxaModuleErrorOverlay.show.restore();
|
||||
privacyLink = termsLink = showErrorOverlaySpy = clickEvent = null;
|
||||
FxaModuleEnterEmail.entrySheet = null;
|
||||
});
|
||||
|
||||
test(' > Should not be shown if navigator.onLine is false', function() {
|
||||
var realOnLine = Object.getOwnPropertyDescriptor(navigator, 'onLine');
|
||||
Object.defineProperty(navigator, 'onLine', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return false;
|
||||
},
|
||||
set: function() {}
|
||||
});
|
||||
var showErrorSpy = this.sinon.spy(FxaModuleEnterEmail,
|
||||
'showErrorResponse');
|
||||
privacyLink.dispatchEvent(clickEvent);
|
||||
termsLink.dispatchEvent(clickEvent);
|
||||
assert.ok(showErrorSpy.calledTwice);
|
||||
FxaModuleEnterEmail.showErrorResponse.restore();
|
||||
realOnLine ? Object.defineProperty(navigator, 'onLine', realOnLine) :
|
||||
delete navigator.onLine;
|
||||
});
|
||||
|
||||
test(' > Should be dismissed on "home" event', function() {
|
||||
window.dispatchEvent(new CustomEvent('home'));
|
||||
assert.ok(closeEntrySheetSpy.calledOnce);
|
||||
assert.isNull(FxaModuleEnterEmail.entrySheet);
|
||||
});
|
||||
|
||||
test(' > Should be dismissed on "holdhome" event', function() {
|
||||
window.dispatchEvent(new CustomEvent('holdhome'));
|
||||
assert.ok(closeEntrySheetSpy.calledOnce);
|
||||
assert.isNull(FxaModuleEnterEmail.entrySheet);
|
||||
});
|
||||
|
||||
test(' > Should be dismissed on "activityrequesting" event', function() {
|
||||
window.dispatchEvent(new CustomEvent('activityrequesting'));
|
||||
assert.ok(closeEntrySheetSpy.calledOnce);
|
||||
assert.isNull(FxaModuleEnterEmail.entrySheet);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > email input ', function() {
|
||||
var emailInput;
|
||||
var fxamUIDisableSpy, fxamUIEnableSpy;
|
||||
var inputEvent;
|
||||
setup(function() {
|
||||
emailInput = document.getElementById('fxa-email-input');
|
||||
fxamUIDisableSpy = this.sinon.spy(FxaModuleUI, 'disableNextButton');
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableNextButton');
|
||||
inputEvent = new CustomEvent(
|
||||
'input',
|
||||
{
|
||||
bubbles: true
|
||||
}
|
||||
);
|
||||
mocksHelperForEmailModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
emailInput = null;
|
||||
fxamUIDisableSpy = null;
|
||||
fxamUIEnableSpy = null;
|
||||
mocksHelperForEmailModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Disabled button at the beginning', function() {
|
||||
emailInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIDisableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIEnableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Enable when ready', function() {
|
||||
emailInput.value = 'validemail@mozilla.es';
|
||||
emailInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Changes in the email input is tracked properly', function() {
|
||||
emailInput.value = 'validemail@mozilla.es';
|
||||
emailInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.called);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
|
||||
// Change the value on the fly
|
||||
emailInput.value = 'validemailmozilla.es';
|
||||
emailInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.ok(fxamUIDisableSpy.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > onNext ', function() {
|
||||
var showOverlaySpy, showErrorOverlaySpy, hideOverlaySpy;
|
||||
setup(function() {
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
showOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'show');
|
||||
hideOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'hide');
|
||||
mocksHelperForEmailModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
showErrorOverlaySpy = null;
|
||||
showOverlaySpy = null;
|
||||
hideOverlaySpy = null;
|
||||
mocksHelperForEmailModule.teardown();
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = false;
|
||||
});
|
||||
|
||||
test(' > Overlay shown', function(done) {
|
||||
FxaModuleEnterEmail.onNext(function() {
|
||||
assert.ok(showOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > checkEmail called', function() {
|
||||
var checkEmailSpy;
|
||||
setup(function() {
|
||||
checkEmailSpy = this.sinon.spy(FxModuleServerRequest, 'checkEmail');
|
||||
mocksHelperForEmailModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
checkEmailSpy = null;
|
||||
mocksHelperForEmailModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Check email', function(done) {
|
||||
FxaModuleEnterEmail.onNext(function() {
|
||||
assert.ok(checkEmailSpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test(' > Network error', function() {
|
||||
FxModuleServerRequest.error = true;
|
||||
FxaModuleEnterEmail.onNext(function() {});
|
||||
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.ok(showErrorOverlaySpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Email registered (Sign IN)', function(done) {
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = true;
|
||||
FxaModuleEnterEmail.onNext(function(params) {
|
||||
assert.equal(params, FxaModuleStates.ENTER_PASSWORD);
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.isFalse(showErrorOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test(' > Email NOT registered (Sign UP)', function(done) {
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = false;
|
||||
FxaModuleEnterEmail.onNext(function(params) {
|
||||
assert.equal(params, FxaModuleStates.COPPA);
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.isFalse(showErrorOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test(' > Email NOT registered inside FTU (Sign UP)', function(done) {
|
||||
FxaModuleEnterEmail.isFTU = true;
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = false;
|
||||
FxaModuleEnterEmail.onNext(function(params) {
|
||||
assert.equal(params, FxaModuleStates.SET_PASSWORD);
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.isFalse(showErrorOverlaySpy.calledOnce);
|
||||
FxaModuleEnterEmail.isFTU = null;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
suite(' > onBack ', function() {
|
||||
var fxamUIEnableSpy;
|
||||
setup(function() {
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableNextButton');
|
||||
mocksHelperForEmailModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
fxamUIEnableSpy = null;
|
||||
mocksHelperForEmailModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Enable "next" button when going back', function() {
|
||||
FxaModuleEnterEmail.onBack();
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
246
gaia/apps/system/test/unit/fxa_test/screens/fxam_enter_password_test.js
Executable file
246
gaia/apps/system/test/unit/fxa_test/screens/fxam_enter_password_test.js
Executable file
|
|
@ -0,0 +1,246 @@
|
|||
/* global FxaModuleEnterPassword, FxaModuleErrorOverlay, FxaModuleOverlay,
|
||||
FxaModuleUI, FxModuleServerRequest, FxaModuleStates,
|
||||
HtmlImports, LoadElementHelper, MocksHelper, MockL10n */
|
||||
'use strict';
|
||||
|
||||
// Helper for loading the elements
|
||||
requireApp('/system/test/unit/fxa_test/load_element_helper.js');
|
||||
|
||||
// Real code
|
||||
require('/shared/js/utilities.js');
|
||||
requireApp('system/fxa/js/fxam_module.js');
|
||||
requireApp('system/fxa/js/fxam_states.js');
|
||||
requireApp('system/fxa/js/fxam_manager.js');
|
||||
requireApp('system/fxa/js/fxam_overlay.js');
|
||||
requireApp('system/fxa/js/fxam_error_overlay.js');
|
||||
|
||||
// Mockuped code
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_ui.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_ui.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_server_request.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_server_request.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_errors.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_errors.js');
|
||||
|
||||
requireApp('/system/test/unit/mock_ftu_launcher.js');
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
// Code to test
|
||||
requireApp('system/fxa/js/screens/fxam_enter_password.js');
|
||||
|
||||
var mocksHelperForEnterPasswordModule = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'FxaModuleUI',
|
||||
'FxModuleServerRequest',
|
||||
'FxaModuleErrors',
|
||||
'FtuLauncher'
|
||||
]);
|
||||
|
||||
suite('Screen: Enter password', function() {
|
||||
var realL10n;
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
mocksHelperForEnterPasswordModule.suiteSetup();
|
||||
// Load real HTML
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
// Load element to test
|
||||
LoadElementHelper.load('fxa-enter-password.html');
|
||||
// Import the element
|
||||
HtmlImports.populate(done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
document.body.innerHTML = '';
|
||||
mocksHelperForEnterPasswordModule.suiteTeardown();
|
||||
});
|
||||
|
||||
// extracted to allow isFTU option to be passed into Module.init
|
||||
var passwordInput, forgotPasswordEl;
|
||||
var fxamUIDisableSpy, fxamUIEnableSpy, showErrorOverlaySpy, resetSpy;
|
||||
var inputEvent, clickEvent;
|
||||
function initFixtures(options) {
|
||||
/* jshint validthis: true */
|
||||
FxaModuleEnterPassword.init(options);
|
||||
passwordInput = document.getElementById('fxa-pw-input');
|
||||
fxamUIDisableSpy = this.sinon.spy(FxaModuleUI, 'disableNextButton');
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableNextButton');
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
resetSpy = this.sinon.spy(FxModuleServerRequest, 'requestPasswordReset');
|
||||
forgotPasswordEl = document.getElementById('fxa-forgot-password');
|
||||
inputEvent = new CustomEvent(
|
||||
'input',
|
||||
{
|
||||
bubbles: true
|
||||
}
|
||||
);
|
||||
clickEvent = new CustomEvent(
|
||||
'click',
|
||||
{
|
||||
bubbles: true
|
||||
}
|
||||
);
|
||||
mocksHelperForEnterPasswordModule.setup();
|
||||
}
|
||||
|
||||
function destroyFixtures() {
|
||||
passwordInput = null;
|
||||
forgotPasswordEl = null;
|
||||
fxamUIDisableSpy = null;
|
||||
fxamUIEnableSpy = null;
|
||||
showErrorOverlaySpy = null;
|
||||
resetSpy = null;
|
||||
mocksHelperForEnterPasswordModule.teardown();
|
||||
FxModuleServerRequest.resetSuccess = false;
|
||||
}
|
||||
|
||||
suite(' > FTU password input ', function() {
|
||||
setup(function() {
|
||||
initFixtures.call(this, {
|
||||
isftu: true,
|
||||
email: 'dummy@account'
|
||||
});
|
||||
});
|
||||
teardown(destroyFixtures);
|
||||
|
||||
test(' > Forgot password link shows error overlay when in FTU', function() {
|
||||
forgotPasswordEl.dispatchEvent(clickEvent);
|
||||
assert.ok(showErrorOverlaySpy.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > password input ', function() {
|
||||
|
||||
setup(function() {
|
||||
initFixtures.call(this, {
|
||||
email: 'dummy@account'
|
||||
});
|
||||
});
|
||||
teardown(destroyFixtures);
|
||||
|
||||
test(' > Disabled button at the beginning', function() {
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIDisableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIEnableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Enable when ready', function() {
|
||||
passwordInput.value = 'myawesomepassword';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Forgot password link opens web flow when not in FTU', function() {
|
||||
FxModuleServerRequest.resetSuccess = true;
|
||||
forgotPasswordEl.dispatchEvent(clickEvent);
|
||||
assert.ok(resetSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Changes in the password input are tracked properly', function() {
|
||||
passwordInput.value = 'longpassword';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.called);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
|
||||
// Change the value on the fly
|
||||
passwordInput.value = 'short';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.ok(fxamUIDisableSpy.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > onNext ', function() {
|
||||
var showOverlaySpy, showErrorOverlaySpy, hideOverlaySpy;
|
||||
setup(function() {
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
showOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'show');
|
||||
hideOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'hide');
|
||||
mocksHelperForEnterPasswordModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
showErrorOverlaySpy = null;
|
||||
showOverlaySpy = null;
|
||||
hideOverlaySpy = null;
|
||||
mocksHelperForEnterPasswordModule.teardown();
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = false;
|
||||
});
|
||||
|
||||
test(' > Overlay shown', function(done) {
|
||||
FxaModuleEnterPassword.onNext(function() {
|
||||
assert.ok(showOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > signIn called', function() {
|
||||
var signInSpy;
|
||||
setup(function() {
|
||||
signInSpy =
|
||||
this.sinon.spy(FxModuleServerRequest, 'signIn');
|
||||
mocksHelperForEnterPasswordModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
signInSpy = null;
|
||||
mocksHelperForEnterPasswordModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Check password', function(done) {
|
||||
FxaModuleEnterPassword.onNext(function() {
|
||||
assert.ok(signInSpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test(' > Sign in error', function() {
|
||||
FxModuleServerRequest.error = true;
|
||||
FxaModuleEnterPassword.onNext(function() {});
|
||||
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.ok(showErrorOverlaySpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Existing user confirmed', function(done) {
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.authenticated = true;
|
||||
FxaModuleEnterPassword.onNext(function(params) {
|
||||
assert.equal(params, FxaModuleStates.SIGNIN_SUCCESS);
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.isFalse(showErrorOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test(' > Existing user, but not confirmed', function(done) {
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.authenticated = false;
|
||||
FxaModuleEnterPassword.onNext(function(params) {
|
||||
assert.equal(params, FxaModuleStates.SIGNUP_SUCCESS);
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.isFalse(showErrorOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
182
gaia/apps/system/test/unit/fxa_test/screens/fxam_refresh_auth_test.js
Executable file
182
gaia/apps/system/test/unit/fxa_test/screens/fxam_refresh_auth_test.js
Executable file
|
|
@ -0,0 +1,182 @@
|
|||
/* global FxaModuleErrorOverlay, FxaModuleOverlay, FxaModuleRefreshAuth,
|
||||
FxModuleServerRequest, FxaModuleUI, HtmlImports, LoadElementHelper,
|
||||
MocksHelper, MockL10n */
|
||||
'use strict';
|
||||
|
||||
// Helper for loading the elements
|
||||
requireApp('/system/test/unit/fxa_test/load_element_helper.js');
|
||||
|
||||
// Real code
|
||||
require('/shared/js/utilities.js');
|
||||
requireApp('system/fxa/js/fxam_module.js');
|
||||
requireApp('system/fxa/js/fxam_states.js');
|
||||
requireApp('system/fxa/js/fxam_manager.js');
|
||||
requireApp('system/fxa/js/fxam_overlay.js');
|
||||
requireApp('system/fxa/js/fxam_error_overlay.js');
|
||||
|
||||
// Mockuped code
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_ui.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_ui.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_server_request.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_server_request.js');
|
||||
|
||||
requireApp('system/fxa/js/fxam_errors.js');
|
||||
requireApp('/system/test/unit/fxa_test/mock_fxam_errors.js');
|
||||
|
||||
require('/shared/js/lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
|
||||
// Code to test
|
||||
requireApp('system/fxa/js/screens/fxam_refresh_auth.js');
|
||||
|
||||
var mocksHelperForRefreshAuthModule = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'FxaModuleUI',
|
||||
'FxModuleServerRequest',
|
||||
'FxaModuleErrors'
|
||||
]);
|
||||
|
||||
suite('Screen: Enter password', function() {
|
||||
var realL10n;
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
|
||||
mocksHelperForRefreshAuthModule.suiteSetup();
|
||||
// Load real HTML
|
||||
loadBodyHTML('/fxa/fxa_module.html');
|
||||
// Load element to test
|
||||
LoadElementHelper.load('fxa-refresh-auth.html');
|
||||
// Import the element and execute the right init
|
||||
HtmlImports.populate(function() {
|
||||
FxaModuleRefreshAuth.init();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
document.body.innerHTML = '';
|
||||
mocksHelperForRefreshAuthModule.suiteTeardown();
|
||||
});
|
||||
|
||||
suite(' > password input ', function() {
|
||||
var passwordInput;
|
||||
var fxamUIDisableSpy, fxamUIEnableSpy;
|
||||
var inputEvent;
|
||||
setup(function() {
|
||||
passwordInput = document.getElementById('fxa-pw-input-refresh');
|
||||
fxamUIDisableSpy = this.sinon.spy(FxaModuleUI, 'disableDoneButton');
|
||||
fxamUIEnableSpy = this.sinon.spy(FxaModuleUI, 'enableDoneButton');
|
||||
inputEvent = new CustomEvent('input', {
|
||||
bubbles: true
|
||||
});
|
||||
mocksHelperForRefreshAuthModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
passwordInput = null;
|
||||
fxamUIDisableSpy = null;
|
||||
fxamUIEnableSpy = null;
|
||||
mocksHelperForRefreshAuthModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Disabled button at the beginning', function() {
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIDisableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIEnableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Enable when ready', function() {
|
||||
passwordInput.value = 'myawesomepassword';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Changes in the password input are tracked properly', function() {
|
||||
passwordInput.value = 'longpassword';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.called);
|
||||
assert.isFalse(fxamUIDisableSpy.calledOnce);
|
||||
|
||||
// Change the value on the fly
|
||||
passwordInput.value = 'short';
|
||||
passwordInput.dispatchEvent(inputEvent);
|
||||
|
||||
assert.ok(fxamUIEnableSpy.calledOnce);
|
||||
assert.ok(fxamUIDisableSpy.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > onDone ', function() {
|
||||
var showOverlaySpy, showErrorOverlaySpy, hideOverlaySpy;
|
||||
setup(function() {
|
||||
showErrorOverlaySpy = this.sinon.spy(FxaModuleErrorOverlay, 'show');
|
||||
showOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'show');
|
||||
hideOverlaySpy = this.sinon.spy(FxaModuleOverlay, 'hide');
|
||||
mocksHelperForRefreshAuthModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
showErrorOverlaySpy = null;
|
||||
showOverlaySpy = null;
|
||||
hideOverlaySpy = null;
|
||||
mocksHelperForRefreshAuthModule.teardown();
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.registered = false;
|
||||
});
|
||||
|
||||
test(' > Overlay shown', function(done) {
|
||||
FxaModuleRefreshAuth.onDone(function() {
|
||||
assert.ok(showOverlaySpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suite(' > signIn called', function() {
|
||||
var signInSpy;
|
||||
setup(function() {
|
||||
signInSpy =
|
||||
this.sinon.spy(FxModuleServerRequest, 'signIn');
|
||||
mocksHelperForRefreshAuthModule.setup();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
signInSpy = null;
|
||||
mocksHelperForRefreshAuthModule.teardown();
|
||||
});
|
||||
|
||||
test(' > Check password', function(done) {
|
||||
FxaModuleRefreshAuth.onDone(function() {
|
||||
assert.ok(signInSpy.calledOnce);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test(' > Sign in error', function() {
|
||||
FxModuleServerRequest.error = true;
|
||||
FxaModuleRefreshAuth.onDone(function() {});
|
||||
|
||||
assert.ok(hideOverlaySpy.calledOnce);
|
||||
assert.ok(showErrorOverlaySpy.calledOnce);
|
||||
});
|
||||
|
||||
test(' > Existing user confirmed', function(done) {
|
||||
FxModuleServerRequest.error = false;
|
||||
FxModuleServerRequest.authenticated = true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue