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
18
gaia/tv_apps/dashboard/test/unit/.jshintrc
Executable file
18
gaia/tv_apps/dashboard/test/unit/.jshintrc
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"require",
|
||||
"requireApp",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
|
||||
70
gaia/tv_apps/dashboard/test/unit/app_widget_test.js
Executable file
70
gaia/tv_apps/dashboard/test/unit/app_widget_test.js
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
/* globals AppWidget */
|
||||
|
||||
require('/js/app_widget.js');
|
||||
|
||||
|
||||
suite('AppWidget', function() {
|
||||
'use strict';
|
||||
|
||||
var subject;
|
||||
var frameData = {
|
||||
manifestURL: 'url1',
|
||||
widget: 'widgetName1',
|
||||
url: 'about:blank',
|
||||
position: 'up'
|
||||
};
|
||||
var upPanel;
|
||||
|
||||
setup(function() {
|
||||
upPanel = document.createElement('div');
|
||||
upPanel.id = 'up-panel';
|
||||
document.body.appendChild(upPanel);
|
||||
|
||||
subject = new AppWidget(frameData);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
document.body.removeChild(upPanel);
|
||||
});
|
||||
|
||||
suite('creation > ', function() {
|
||||
test('should init frame inside up-panel', function() {
|
||||
assert.equal(upPanel.firstChild, subject.iframe);
|
||||
});
|
||||
|
||||
test('should init frame with appropriate mozapp attributes', function() {
|
||||
var iframe = subject.iframe;
|
||||
assert.equal(iframe.getAttribute('mozbrowser'), 'true');
|
||||
assert.equal(iframe.getAttribute('remote'), 'true');
|
||||
assert.equal(iframe.getAttribute('mozapp'), frameData.manifestURL);
|
||||
assert.equal(iframe.src, frameData.url);
|
||||
});
|
||||
});
|
||||
|
||||
suite('toggleExpand() >', function() {
|
||||
setup(function() {
|
||||
subject.toggleExpand(true);
|
||||
});
|
||||
|
||||
test('should add hash "expand" when expanding', function() {
|
||||
var hash = subject.iframe.src.split('#')[1];
|
||||
assert.equal(hash, 'expand');
|
||||
});
|
||||
|
||||
test('should remove hash "expand" when shrinking', function() {
|
||||
subject.toggleExpand(false);
|
||||
// We have to confirm toggleExpand leaves a '#' in url to prevent reload.
|
||||
// (thus split() shoul return an array of two strings).
|
||||
var hash = subject.iframe.src.split('#')[1];
|
||||
assert.equal(hash, '');
|
||||
});
|
||||
});
|
||||
|
||||
suite('focus() > ', function () {
|
||||
test('should focus its iframe', function() {
|
||||
var spy = this.sinon.spy(subject.iframe, 'focus');
|
||||
subject.focus();
|
||||
assert.isTrue(spy.calledOnce);
|
||||
});
|
||||
});
|
||||
});
|
||||
147
gaia/tv_apps/dashboard/test/unit/dashboard_test.js
Executable file
147
gaia/tv_apps/dashboard/test/unit/dashboard_test.js
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
'use strict';
|
||||
|
||||
/* global Dashboard, MocksHelper */
|
||||
|
||||
require('/bower_components/evt/index.js');
|
||||
require('/shared/js/smart-screen/key_navigation_adapter.js');
|
||||
require('mock_app_widget.js');
|
||||
require('mock_digital_clock.js');
|
||||
require('/js/dashboard.js');
|
||||
|
||||
var MocksHelperForUnitTest = new MocksHelper([
|
||||
'AppWidget',
|
||||
'DigitalClock'
|
||||
]).init();
|
||||
|
||||
suite('Dashboard', function() {
|
||||
var dashboard;
|
||||
var mainSection;
|
||||
var clock;
|
||||
|
||||
MocksHelperForUnitTest.attachTestHelpers();
|
||||
|
||||
setup(function() {
|
||||
clock = this.sinon.useFakeTimers();
|
||||
|
||||
mainSection = document.createElement('div');
|
||||
mainSection.id = 'main-section';
|
||||
document.body.appendChild(mainSection);
|
||||
|
||||
dashboard = new Dashboard();
|
||||
dashboard.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
document.body.removeChild(mainSection);
|
||||
});
|
||||
|
||||
test('should initialize keyNavigationAdapter and digitalClock', function() {
|
||||
assert.isDefined(dashboard.keyNavigationAdapter);
|
||||
assert.isDefined(dashboard.digitalClock);
|
||||
});
|
||||
|
||||
test('should change body dataset.activeDirection ' +
|
||||
'to up when dashboard.onMove is called with up', function() {
|
||||
dashboard.onMove('up');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
dashboard.onMove('down');
|
||||
assert.equal(document.body.dataset.activeDirection, '');
|
||||
});
|
||||
|
||||
test('should change body dataset.activeDirection ' +
|
||||
'to right when dashboard.onMove is called with right', function() {
|
||||
dashboard.onMove('right');
|
||||
assert.equal(document.body.dataset.activeDirection, 'right');
|
||||
dashboard.onMove('left');
|
||||
assert.equal(document.body.dataset.activeDirection, '');
|
||||
});
|
||||
|
||||
test('should change body dataset.activeDirection ' +
|
||||
'to down when dashboard.onMove is called with down', function() {
|
||||
dashboard.onMove('down');
|
||||
assert.equal(document.body.dataset.activeDirection, 'down');
|
||||
dashboard.onMove('up');
|
||||
assert.equal(document.body.dataset.activeDirection, '');
|
||||
});
|
||||
|
||||
test('should change body dataset.activeDirection ' +
|
||||
'to left when dashboard.onMove is called with left', function() {
|
||||
dashboard.onMove('left');
|
||||
assert.equal(document.body.dataset.activeDirection, 'left');
|
||||
dashboard.onMove('right');
|
||||
assert.equal(document.body.dataset.activeDirection, '');
|
||||
});
|
||||
|
||||
test('should not change body dataset.activeDirection ' +
|
||||
'when activeDirection is up and dashboard.onMove is ' +
|
||||
'called with up',function () {
|
||||
dashboard.onMove('up');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
dashboard.onMove('up');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
});
|
||||
|
||||
test('should not change body dataset.activeDirection ' +
|
||||
'when activeDirection is up and dashboard.onMove is ' +
|
||||
'called with right or left',function () {
|
||||
dashboard.onMove('up');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
dashboard.onMove('right');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
dashboard.onMove('left');
|
||||
assert.equal(document.body.dataset.activeDirection, 'up');
|
||||
});
|
||||
|
||||
test('should expand bottom widget when moving down,' +
|
||||
' then shrink when moving back', function() {
|
||||
dashboard.onMove('down');
|
||||
assert.isTrue(
|
||||
dashboard.widgets.down.toggleExpand.withArgs(true).calledOnce);
|
||||
dashboard.onMove('up');
|
||||
assert.isTrue(
|
||||
dashboard.widgets.down.toggleExpand.withArgs(false).calledOnce);
|
||||
});
|
||||
|
||||
test('should focus on bottom widget when moving down', function () {
|
||||
var mainSectionFocusSpy = this.sinon.spy(mainSection, 'focus');
|
||||
dashboard.onMove('down');
|
||||
assert.isTrue(mainSectionFocusSpy.calledOnce);
|
||||
clock.tick();
|
||||
assert.isTrue(dashboard.widgets.down.focus.calledOnce);
|
||||
});
|
||||
|
||||
suite('visibilityChange >', function() {
|
||||
function setFakeVisibility(value) {
|
||||
Object.defineProperty(document, 'visibilityState', {
|
||||
get: function(){
|
||||
return value;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
teardown(function() {
|
||||
delete document.visibilityState;
|
||||
});
|
||||
|
||||
test('should move to center if visibility becomes hidden', function() {
|
||||
dashboard.onMove('down');
|
||||
setFakeVisibility('hidden');
|
||||
var mainSectionFocusSpy = this.sinon.spy(mainSection, 'focus');
|
||||
dashboard.onVisibilityChange();
|
||||
|
||||
assert.equal(document.body.dataset.activeDirection, '');
|
||||
assert.isTrue(mainSectionFocusSpy.calledOnce);
|
||||
});
|
||||
|
||||
test('should toggle body class "expand" with visibility', function() {
|
||||
setFakeVisibility('hidden');
|
||||
dashboard.onVisibilityChange();
|
||||
assert.isFalse(document.body.classList.contains('active'));
|
||||
|
||||
setFakeVisibility('visible');
|
||||
dashboard.onVisibilityChange();
|
||||
assert.isTrue(document.body.classList.contains('active'));
|
||||
});
|
||||
});
|
||||
});
|
||||
111
gaia/tv_apps/dashboard/test/unit/digital_clock_test.js
Executable file
111
gaia/tv_apps/dashboard/test/unit/digital_clock_test.js
Executable file
|
|
@ -0,0 +1,111 @@
|
|||
'use strict';
|
||||
|
||||
/* global DigitalClock, MockL10n */
|
||||
|
||||
// XXX: The mocked formatValue method in mock_l10n.js returns Promise.resolve
|
||||
// instead of a Promise, making it difficult to use the mock_promise.js
|
||||
// to test. So here the test code is commented out
|
||||
// until the mock_l10n.js is changed.
|
||||
//
|
||||
// require('/shared/test/unit/mocks/mock_promise.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/js/digital_clock.js');
|
||||
|
||||
suite('DigitalClock', function() {
|
||||
var clock;
|
||||
var digitalClock;
|
||||
var startDate;
|
||||
var realL10n;
|
||||
|
||||
function createElement(tagName, id) {
|
||||
var element = document.createElement(tagName);
|
||||
element.id = id;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
var elements = {
|
||||
hoursTensDigit: createElement('span', 'hours-tens-digit'),
|
||||
hoursUnitsDigit: createElement('span', 'hours-units-digit'),
|
||||
minutesTensDigit: createElement('span', 'minutes-tens-digit'),
|
||||
minutesUnitsDigit: createElement('span', 'minutes-units-digit'),
|
||||
secondsTensDigit: createElement('span', 'seconds-tens-digit'),
|
||||
secondsUnitsDigit: createElement('span', 'seconds-units-digit'),
|
||||
today: createElement('span', 'today-is'),
|
||||
greeting: createElement('span', 'greeting')
|
||||
};
|
||||
|
||||
suiteSetup(function() {
|
||||
realL10n = window.navigator.mozL10n;
|
||||
window.navigator.mozL10n = MockL10n;
|
||||
|
||||
for (var prop in elements) {
|
||||
document.body.appendChild(elements[prop]);
|
||||
}
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
var elements = document.getElementsByTagName('span');
|
||||
for (var i=0; i < elements.length; i++) {
|
||||
document.body.removeChild(elements[i]);
|
||||
}
|
||||
window.navigator.mozL10n = realL10n;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
// this.sinon.stub(window, 'Promise', MockPromise);
|
||||
// this.sinon.spy(window.Promise, 'resolve');
|
||||
|
||||
startDate = new Date(2015, 4, 31);
|
||||
clock = this.sinon.useFakeTimers(startDate.getTime());
|
||||
digitalClock = new DigitalClock();
|
||||
digitalClock.init();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
// window.Promise.restore();
|
||||
|
||||
digitalClock.stop();
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
test('Should display current date and time once the clock is initialized',
|
||||
function() {
|
||||
clock.tick();
|
||||
assert.equal(digitalClock.date.getTime(), startDate.getTime());
|
||||
assert.equal(elements.hoursTensDigit.textContent, '0');
|
||||
assert.equal(elements.hoursUnitsDigit.textContent, '0');
|
||||
assert.equal(elements.minutesTensDigit.textContent, '0');
|
||||
assert.equal(elements.minutesUnitsDigit.textContent, '0');
|
||||
assert.equal(elements.secondsTensDigit.textContent, '0');
|
||||
assert.equal(elements.secondsUnitsDigit.textContent, '0');
|
||||
// var p0 = window.Promise.resolve.firstCall.args[0];
|
||||
// Using JSON.stringify here to match the result from the mock l10n.
|
||||
// assert.equal(elements.today.dataset.l10nArgs,
|
||||
// JSON.stringify({'date': JSON.stringify(new Date()) + 'dateFormat'}));
|
||||
});
|
||||
|
||||
test('Should clear timers after the clock is stopped', function() {
|
||||
digitalClock.stop();
|
||||
assert.isNull(digitalClock.timeoutId);
|
||||
});
|
||||
|
||||
test('Should update date and time after the clock starts', function() {
|
||||
var now;
|
||||
digitalClock.start();
|
||||
// Set the clock to 1 day, 1 hour, 1 minute and 1 second later
|
||||
// after initial date.
|
||||
clock.tick(86400000);
|
||||
now = new Date();
|
||||
// var p0 = window.Promise.resolve.firstCall.args[0];
|
||||
// assert.equal(elements.today.dataset.l10nArgs,
|
||||
// JSON.stringify({'date': JSON.stringify(now) + 'dateFormat'}));
|
||||
// Set the clock to 1 hour, 1 minute and 1 second later
|
||||
clock.tick(3600000 + 60000 + 1000);
|
||||
now = new Date();
|
||||
assert.equal(digitalClock.date.getTime(), now.getTime());
|
||||
assert.equal(elements.hoursUnitsDigit.textContent, '1');
|
||||
assert.equal(elements.minutesUnitsDigit.textContent, '1');
|
||||
assert.equal(elements.secondsUnitsDigit.textContent, '1');
|
||||
});
|
||||
});
|
||||
10
gaia/tv_apps/dashboard/test/unit/mock_app_widget.js
Executable file
10
gaia/tv_apps/dashboard/test/unit/mock_app_widget.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
/* globals sinon */
|
||||
'use strict';
|
||||
|
||||
|
||||
var MockAppWidget = function(config) {
|
||||
this.toggleExpand = sinon.stub();
|
||||
this.focus = sinon.stub();
|
||||
};
|
||||
MockAppWidget.prototype = {
|
||||
};
|
||||
10
gaia/tv_apps/dashboard/test/unit/mock_digital_clock.js
Executable file
10
gaia/tv_apps/dashboard/test/unit/mock_digital_clock.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var MockDigitalClock = function() {
|
||||
this.init = sinon.stub();
|
||||
this.start = sinon.stub();
|
||||
this.stop = sinon.stub();
|
||||
this.generateGreeting = sinon.stub();
|
||||
};
|
||||
|
||||
MockDigitalClock.prototype = {};
|
||||
3
gaia/tv_apps/dashboard/test/unit/setup.js
Executable file
3
gaia/tv_apps/dashboard/test/unit/setup.js
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
Loading…
Reference in a new issue