Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,17 @@
{
"extends": "../../../../.jshintrc",
"predef": [
"assert",
"suite",
"test",
"setup",
"teardown",
"suiteSetup",
"suiteTeardown",
"require",
"requireApp",
"sinon",
"mocha",
"loadBodyHTML"
]
}

View file

@ -0,0 +1,65 @@
/* global Captions */
'use strict';
requireApp('/video/js/captions.js');
suite('captions.js unit tests', function() {
var player, captions, realGetDeviceStorage;
var mockVTTFile = new Blob(['fake vtt file'], { type: 'text/vtt' });
var mockGetRequest;
function mockGetDeviceStorage(type) {
return {
get: function(filename) {
mockGetRequest.requestedFilename = filename;
return mockGetRequest;
}
};
}
setup(function() {
player = document.createElement('video');
captions = new Captions(player);
realGetDeviceStorage = navigator.getDeviceStorage;
navigator.getDeviceStorage = mockGetDeviceStorage;
mockGetRequest = { result: mockVTTFile };
});
teardown(function() {
navigator.getDeviceStorage = realGetDeviceStorage;
});
test('remove() removes track elements from player', function() {
player.appendChild(document.createElement('track'));
player.appendChild(document.createElement('track'));
assert.equal(player.querySelectorAll('track').length, 2);
captions.remove();
assert.equal(player.querySelectorAll('track').length, 0);
});
test('findAndDisplay() looks for a .vtt file', function() {
captions.findAndDisplay('foo/bar.mp4');
assert.equal(mockGetRequest.requestedFilename, 'foo/bar.vtt');
});
test('findAndDisplay() adds a track element if captions exist', function() {
captions.findAndDisplay('foo.mp4');
mockGetRequest.onsuccess(); // A captions file was found
assert.equal(player.querySelectorAll('track').length, 1);
});
test('findAndDisplay() adds a showing track element', function() {
captions.findAndDisplay('foo.mp4');
mockGetRequest.onsuccess(); // A captions file was found
assert.equal(player.querySelector('track').track.mode, 'showing');
});
test('findAndDisplay() adds no track element if no captions', function() {
captions.findAndDisplay('foo.mp4');
if (mockGetRequest.onerror) {
mockGetRequest.onerror(); // No captions file was found
}
assert.equal(player.querySelectorAll('track').length, 0);
});
});

Binary file not shown.

View file

@ -0,0 +1,15 @@
/* exported MockForwardRewindController */
'use strict';
var MockForwardRewindController = (function() {
function init(video, forward, backward) {}
function uninit(video, forward, backward) {}
return {
init: init,
uninit: uninit
};
}());

View file

@ -0,0 +1,32 @@
/* exported MockMediaDB, MediaDB */
'use strict';
var MediaDB;
var MockMediaDB = (function() {
function MockMediaDB(blob) {
this.blob = blob;
this.OPENING = 'opening'; // this is initializing itself
this.UPGRADING = 'upgrading'; // this is upgrading database
this.READY = 'ready'; // this is available and ready for use
this.NOCARD = 'nocard'; // Unavailable because there is no sd card
this.UNMOUNTED = 'unmounted'; // Unavailable because card unmounted
this.CLOSED = 'closed'; // Unavailable because closed() was called
}
MockMediaDB.prototype = {
getFile: function getFile(filename, callback) {
this.blob.name = filename;
callback(this.blob);
},
updateMetadata: function updateMetadata() {
}
};
return MockMediaDB;
}());

View file

@ -0,0 +1,19 @@
/* exported startParsingMetadata, stopParsingMetadata */
/* exported metadataQueue, processingQueue, captureFrame */
'use strict';
var metadataQueue;
var processingQueue;
function startParsingMetadata() {
}
function stopParsingMetadata() {
}
// We need a mock captureFrame function as opposed to simply
// using a spy because the function needs to have an implementation,
// it needs to invoke the callback function.
function captureFrame(player, metadata, callback) {
callback();
}

View file

@ -0,0 +1,48 @@
'use strict';
var MockThumbnailGroup = function(item) {
var counter = 0;
var dummyNode = document.createElement('div');
dummyNode.textContent = MockThumbnailGroup._GroupID;
dummyNode.htmlNode = dummyNode;
dummyNode.updateTitleText = function() {};
function addItem() {
counter++;
return dummyNode;
}
function removeItem() {
counter--;
}
function localize() {}
MockThumbnailGroup._GroupMap[MockThumbnailGroup._GroupID] = {
// api
addItem: addItem,
getCount: function() {return counter;},
removeItem: removeItem,
localize: localize,
// properties.
groupID: MockThumbnailGroup._GroupID,
htmlNode: dummyNode
};
return MockThumbnailGroup._GroupMap[MockThumbnailGroup._GroupID];
};
MockThumbnailGroup.getGroupID = function(video) {
return MockThumbnailGroup._GroupID;
};
MockThumbnailGroup.compareGroupID = function(id1, id2) {
return id1 > id2 ? 1 : (id1 < id2 ? -1 : 0);
};
MockThumbnailGroup._GroupMap = {};
MockThumbnailGroup.reset = function() {
MockThumbnailGroup._GroupMap = {};
delete MockThumbnailGroup._GroupID;
};

View file

@ -0,0 +1,15 @@
/* exported MockThumbnailItem */
'use strict';
var MockThumbnailItem = function(video) {
var dummyNode = document.createElement('div');
dummyNode.textContent = video.date;
var titleMaxLines;
return {
htmlNode: dummyNode,
data: video,
titleMaxLines: titleMaxLines,
updateTitleText: function() {}
};
};

View file

@ -0,0 +1,27 @@
'use strict';
function VideoLoadingChecker(player, overlay, overlayTitle, overlayText) {
this.player = player;
this.overlay = overlay;
this.overlayTitle = overlayTitle;
this.overlayText = overlayText;
this.callback = null;
}
VideoLoadingChecker.prototype = {
ensureVideoLoads: function vpc_ensureVideoLoads(callback) {
this.callback = callback;
},
invokeLoadedMetadataCallback: function vpc_invokeLoadedMetadataCallback() {
if (this.callback) {
this.callback();
}
},
resetLoadedMetadataCallback: function vpc_resetLoadedMetadataCallback() {
this.callback = null;
},
ensureVideoPlays: function() {},
cancelEnsureVideoPlays: function() {},
};

View file

@ -0,0 +1,70 @@
'use strict';
function MockVideoPlayer() {
MockVideoPlayer.instances.push(this);
this.src = null;
this.readyState = 0;
this.seeking = false;
this.duration = 0;
this.currentTime = 0;
this.classList = [];
}
MockVideoPlayer.instances = [];
MockVideoPlayer.mSetup = function() {
MockVideoPlayer.instances = [];
};
MockVideoPlayer.mTeardown = function() {
MockVideoPlayer.instances = [];
};
MockVideoPlayer.prototype.play = function() {
};
MockVideoPlayer.prototype.pause = function() {
};
MockVideoPlayer.prototype.load = function() {
};
MockVideoPlayer.prototype.setSeeking = function(seeking) {
this.seeking = seeking;
};
MockVideoPlayer.prototype.setDuration = function(duration) {
this.duration = duration;
};
MockVideoPlayer.prototype.hasAttribute = function(attr) {
if (attr === 'src') {
return (this.src !== undefined && this.src !== null);
}
return (this.classList.indexOf(attr) !== -1);
};
MockVideoPlayer.prototype.removeAttribute = function(attr) {
if (attr === 'src') {
this.src = null;
}
else {
var index = this.classList.indexOf(attr);
if (index >= 0) {
this.classList.splice(index, 1);
}
}
};
MockVideoPlayer.prototype.fastSeek = function(seekTime) {
this.currentTime = seekTime;
};
MockVideoPlayer.prototype.cloneNode = function() {
return this;
};
MockVideoPlayer.prototype.querySelectorAll = function(selector) {
return [];
};

View file

@ -0,0 +1,136 @@
/* global Seeker, performance */
'use strict';
requireApp('/video/js/seeker.js');
// We need a simple mock <video> element for these testsx
function MockVideo() {
this.fastSeek = sinon.spy();
this.seekedHandlers = [];
this.addEventListener = function(type, handler) {
if (type === 'seeked') {
this.seekedHandlers.push(handler);
}
};
this._fireSeekedEvent = function() {
this.seekedHandlers.forEach((f) => {
typeof f === 'object' ? f.handleEvent() : f();
});
};
}
suite('seeker.js unit tests', function() {
var player, seeker;
setup(function() {
player = new MockVideo();
seeker = new Seeker(player);
});
test('it calls fastSeek()', function() {
seeker.seekTo(1);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
});
test('it doesn\'t seek twice to same spot', function() {
seeker.seekTo(1);
seeker.seekTo(1);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
});
test('it defers rapidly repeated seeks', function() {
seeker.seekTo(1);
seeker.seekTo(2);
seeker.seekTo(3);
seeker.seekTo(4);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(4));
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledTwice);
});
test('it does not defer seeks if previous seek has ended', function() {
seeker.seekTo(1);
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
seeker.seekTo(2);
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(2));
player._fireSeekedEvent();
seeker.seekTo(3);
assert.ok(player.fastSeek.calledThrice);
assert.ok(player.fastSeek.calledWith(3));
});
test('it does not defer seeks to 0', function() {
seeker.seekTo(4);
seeker.seekTo(3);
seeker.seekTo(2);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(4));
seeker.seekTo(0);
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(0));
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledTwice);
});
test('it does not defer long-distance seeks', function() {
seeker.seekTo(1);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
Seeker.SEEK_DISTANCE = 5;
seeker.seekTo(7);
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(7));
Seeker.SEEK_DISTANCE = 50;
seeker.seekTo(17); // not far enough, it gets deferred
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(7));
seeker.seekTo(58);
assert.ok(player.fastSeek.calledThrice);
assert.ok(player.fastSeek.calledWith(58));
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledThrice);
});
test('it does not defer infrequent seeks', function() {
// We need to fake out performance.now() for this test
var realPerformanceNow = performance.now;
var time = 0;
performance.now = function() { return time; };
try {
seeker.seekTo(1);
assert.ok(player.fastSeek.calledOnce);
assert.ok(player.fastSeek.calledWith(1));
Seeker.SEEK_INTERVAL = 10;
time = 12;
seeker.seekTo(2);
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(2));
Seeker.SEEK_INTERVAL = 100;
time = 50;
seeker.seekTo(3); // not enough fake time has passed, this is deferred
assert.ok(player.fastSeek.calledTwice);
assert.ok(player.fastSeek.calledWith(2));
time = 113;
seeker.seekTo(4);
assert.ok(player.fastSeek.calledThrice);
assert.ok(player.fastSeek.calledWith(4));
player._fireSeekedEvent();
assert.ok(player.fastSeek.calledThrice);
}
finally {
performance.now = realPerformanceNow;
}
});
});

View file

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

View file

@ -0,0 +1,181 @@
/* global ThumbnailItem: true,MockThumbnailItem,MockL10n,
ThumbnailDateGroup,MockIntlHelper */
/*
* Thumbnail Date Group tests
*/
'use strict';
require('/shared/js/sanitizer.js');
require('/shared/js/media/media_utils.js');
require('/shared/test/unit/mocks/mock_l20n.js');
require('/shared/test/unit/mocks/mock_intl_helper.js');
requireApp('/video/test/unit/mock_thumbnail_item.js');
requireApp('/video/js/thumbnail_date_group.js');
requireApp('/video/js/thumbnail_item.js');
suite('Thumbnail Date Group Unit Tests', function() {
var nativeMozL10n;
var nativeThumbnailItem;
var nativeIntlHelper;
suiteSetup(function() {
nativeThumbnailItem = ThumbnailItem;
nativeMozL10n = document.l10n;
document.l10n = MockL10n;
nativeIntlHelper = window.IntlHelper;
window.IntlHelper = MockIntlHelper;
ThumbnailItem = MockThumbnailItem;
window.IntlHelper.define('date-group', 'datetime', {
month: 'long',
year: 'numeric',
});
});
suiteTeardown(function() {
document.l10n = nativeMozL10n;
window.IntlHelper = nativeIntlHelper;
ThumbnailItem = nativeThumbnailItem;
});
suite('#static functions', function() {
test('#getGroupID', function() {
assert.equal(ThumbnailDateGroup.getGroupID({date: 1375873140000}),
'group_2013-08');
assert.equal(ThumbnailDateGroup.getGroupID({date: 1381967318275}),
'group_2013-10');
});
test('#compareGroupID', function() {
assert.equal(ThumbnailDateGroup.compareGroupID('group_2013-08',
'group_2013-08'),
0);
assert.equal(ThumbnailDateGroup.compareGroupID('group_2013-08',
'group_2013-07'),
1);
assert.equal(ThumbnailDateGroup.compareGroupID('group_2013-08',
'group_2013-09'),
-1);
assert.equal(ThumbnailDateGroup.compareGroupID('group_2013-09',
'group_2013-10'),
-1);
});
});
suite('#test object creation', function() {
test('#empty video object', function() {
try {
new ThumbnailDateGroup(); // jshint ignore:line
assert.fail('undefined or null videoitem should not be ok.');
} catch (ex) {
assert.ok('correct behavior caught');
}
});
});
suite('#rendering', function() {
var dateGroup;
var videoData;
var domNode;
suiteSetup(function() {
videoData = {date: 1375873140000};
dateGroup = new ThumbnailDateGroup(videoData, 'test-id');
domNode = dateGroup.htmlNode;
});
test('#normal', function() {
assert.equal(domNode.firstElementChild.textContent, 'August 2013');
});
});
suite('#API', function() {
var dateGroup;
var videoData;
var domNode;
var groupContainerNode;
setup(function() {
videoData = {date: 1375873140000};
dateGroup = new ThumbnailDateGroup(videoData);
domNode = dateGroup.htmlNode;
groupContainerNode = domNode.querySelector('.thumbnail-group-container');
});
test('#addItem, simple', function() {
assert.isUndefined(dateGroup.addItem());
var thumbnail = dateGroup.addItem({date: 1375873140005});
assert.isDefined(thumbnail);
assert.equal(dateGroup.getCount(), 1);
assert.equal(groupContainerNode.children[0], thumbnail.htmlNode);
});
test('#addItem, first, middle, last', function() {
// addItem, to empty
var thumbnail2 = dateGroup.addItem({date: 1375873140003});
assert.equal(dateGroup.getCount(), 1);
assert.equal(groupContainerNode.children[0], thumbnail2.htmlNode);
// addItem, to first
var thumbnail1 = dateGroup.addItem({date: 1375873140004});
assert.equal(dateGroup.getCount(), 2);
assert.equal(groupContainerNode.children[0], thumbnail1.htmlNode);
assert.equal(groupContainerNode.children[1], thumbnail2.htmlNode);
// addItem, to last
var thumbnail4 = dateGroup.addItem({date: 1375873140001});
assert.equal(dateGroup.getCount(), 3);
assert.isNull(thumbnail4.htmlNode.nextSibling);
assert.equal(groupContainerNode.children[2], thumbnail4.htmlNode);
// addItem to middle
var thumbnail3 = dateGroup.addItem({date: 1375873140002});
assert.equal(dateGroup.getCount(), 4);
assert.equal(groupContainerNode.children[2], thumbnail3.htmlNode);
assert.equal(groupContainerNode.children[3], thumbnail4.htmlNode);
// check from dummyContainer
assert.equal(groupContainerNode.children.length, 4);
});
test('#groupID', function() {
assert.equal(dateGroup.groupID, 'group_2013-08');
});
test('#htmlNode', function() {
assert.equal(dateGroup.htmlNode, domNode);
});
test('#removeItem, unknown thumbnail', function() {
dateGroup.addItem({date: 1375873140004});
dateGroup.addItem({date: 1375873140003});
var dummyThumbnail = new ThumbnailItem({});
dateGroup.removeItem(dummyThumbnail);
assert.equal(dateGroup.getCount(), 2);
});
test('#removeItem, remove all', function() {
var thumbnail1 = dateGroup.addItem({date: 1375873140004});
var thumbnail2 = dateGroup.addItem({date: 1375873140003});
var thumbnail3 = dateGroup.addItem({date: 1375873140002});
var thumbnail4 = dateGroup.addItem({date: 1375873140001});
dateGroup.removeItem(thumbnail1);
assert.equal(dateGroup.getCount(), 3);
assert.equal(groupContainerNode.children[0], thumbnail2.htmlNode);
assert.isUndefined(groupContainerNode.children[3]);
dateGroup.removeItem(thumbnail4);
assert.equal(dateGroup.getCount(), 2);
assert.equal(groupContainerNode.children[1], thumbnail3.htmlNode);
assert.isUndefined(groupContainerNode.children[2]);
dateGroup.removeItem(thumbnail3);
assert.equal(dateGroup.getCount(), 1);
assert.equal(groupContainerNode.children[0], thumbnail2.htmlNode);
assert.isUndefined(groupContainerNode.children[1]);
dateGroup.removeItem(thumbnail2);
assert.equal(dateGroup.getCount(), 0);
assert.isUndefined(groupContainerNode.children[0]);
});
});
});

View file

@ -0,0 +1,212 @@
/* global MockL10n,ThumbnailItem,l10nAssert */
/*
* Thumbnail Item tests
*/
'use strict';
require('/shared/js/sanitizer.js');
require('/shared/js/media/media_utils.js');
require('/shared/test/unit/mocks/mock_l20n.js');
requireApp('/video/js/thumbnail_item.js');
suite('Thumbnail Item Unit Tests', function() {
var nativeMozL10n;
suiteSetup(function() {
nativeMozL10n = document.l10n;
document.l10n = MockL10n;
});
suiteTeardown(function() {
document.l10n = nativeMozL10n;
});
suite('#test object creation', function() {
test('#empty video object', function() {
try {
new ThumbnailItem(); // jshint ignore:line
assert.fail('undefined or null videoitem should not be ok.');
} catch (ex) {
assert.ok('correct behavior caught');
}
});
});
suite('#error handling', function() {
var videodata;
suiteSetup(function() {
videodata = {
metadata: {
title: 'Small webm',
duration: 5.568,
width: 560,
height: 320,
watched: false
},
type: 'video/webm',
date: 1375873140000,
size: 229455,
name: 'dummy-file-name'
};
});
test('#partial fields of template inexistent', function() {
var thumbnail = new ThumbnailItem(videodata);
thumbnail.updatePoster(new Blob(['empty-image'], {'type': 'image/jpeg'}));
assert.ok('it is ok without any fields');
});
});
suite('#rendering', function() {
var videodata;
var thumbnail;
var domNode;
suiteSetup(function() {
videodata = {
metadata: {
title: 'Small webm',
duration: 5.568,
width: 560,
height: 320,
watched: false
},
type: 'video/webm',
date: 1375873140000,
size: 229455,
name: 'dummy-file-name'
};
thumbnail = new ThumbnailItem(videodata);
domNode = thumbnail.htmlNode;
});
test('#unwatched', function() {
assert.isDefined(domNode);
var unwatchedNode = domNode.querySelector('.unwatched');
// it is is unwatched now.
assert.isFalse(unwatchedNode.hidden);
});
test('#title', function() {
var titleNode = domNode.querySelector('.title');
assert.equal(titleNode.textContent, 'Small webm');
});
test('#duration-text', function() {
var durationNode = domNode.querySelector('.duration-text');
assert.equal(durationNode.textContent, '00:06');
});
test('#size-text', function() {
var sizeNode = domNode.querySelector('.size-text');
l10nAssert(
sizeNode,
'fileSize',
{size: 224, unit: 'KB'}
);
});
test('#type-text', function() {
var typeNode = domNode.querySelector('.type-text');
assert.equal(typeNode.textContent, 'webm');
});
});
suite('#api tests', function() {
var videodata;
var thumbnail;
var domNode;
suiteSetup(function() {
videodata = {
metadata: {
title: 'Small webm',
duration: 5.568,
width: 560,
height: 320,
watched: false,
poster: new Blob(['empty-image'], {'type': 'image/jpeg'})
},
type: 'video/webm',
date: 1375873140000,
size: 229455,
name: 'dummy-file-name'
};
thumbnail = new ThumbnailItem(videodata);
domNode = thumbnail.htmlNode;
});
test('#addTapListener and fired', function(done) {
function testFunc(video) {
assert.deepEqual(video, videodata);
thumbnail.removeTapListener(testFunc);
done();
}
thumbnail.addTapListener(testFunc);
domNode.click();
});
test('#removeTapListener and fired', function(done) {
function testFunc(video) {
assert.fail('event should not fired.');
}
thumbnail.addTapListener(testFunc);
thumbnail.removeTapListener(testFunc);
domNode.click();
window.setTimeout(done);
});
test('#addTapListener, empty argument', function() {
thumbnail.addTapListener();
assert.ok('everything should be ok');
});
test('#removeTapListener, empty argument', function() {
thumbnail.removeTapListener();
assert.ok('everything should be ok');
});
test('#addTapListener, object listener', function(done) {
function testFunc(video) {
assert.deepEqual(video, videodata);
thumbnail.removeTapListener(testFunc);
done();
}
thumbnail.addTapListener({handleEvent: testFunc});
domNode.click();
});
test('#overflow', function() {
var evt = new Event('overflow');
thumbnail.detailNode.dispatchEvent(evt);
assert.ok('everything should be ok');
});
test('#htmlNode', function() {
assert.equal(thumbnail.htmlNode, domNode);
});
test('#data', function() {
assert.deepEqual(thumbnail.data, videodata);
});
test('#watched', function() {
thumbnail.setWatched(false);
var node = domNode.querySelector('.unwatched');
assert.isFalse(node.hidden);
thumbnail.setWatched(true);
assert.isTrue(node.hidden);
});
test('#updatePoster', function() {
var blob = new Blob(['empty-image'], {'type': 'image/jpeg'});
thumbnail.updatePoster(blob);
var node = domNode.querySelector('.img');
assert.notEqual(node.src, '');
thumbnail.updatePoster(null);
assert.ok(node.src.endsWith('style/images/default_thumbnail.png'));
});
});
});

View file

@ -0,0 +1,164 @@
/* global MockL10n,MockThumbnailGroup,ThumbnailList */
/*
* Thumbnail List tests
*/
'use strict';
require('/shared/test/unit/mocks/mock_l20n.js');
requireApp('/video/test/unit/mock_thumbnail_group.js');
requireApp('/video/js/thumbnail_list.js');
suite('Thumbnail List Unit Tests', function() {
var realL10n;
suiteSetup(function() {
realL10n = document.l10n;
document.l10n = MockL10n;
});
suiteTeardown(function() {
document.l10n = realL10n;
});
suite('#constructor tests', function() {
var dummyContainer;
suiteSetup(function() {
MockThumbnailGroup.reset();
dummyContainer = document.createElement('div');
});
test('normal', function() {
new ThumbnailList(MockThumbnailGroup, dummyContainer); //jshint ignore:line
assert.ok('everything should be ok');
});
test('missing arguments', function() {
try {
new ThumbnailList(MockThumbnailGroup); //jshint ignore:line
assert.fail('it should throws an error.');
} catch (ex) {
assert.ok('everything should be ok');
}
try {
new ThumbnailList(); //jshint ignore:line
assert.fail('it should throws an error.');
} catch (ex) {
assert.ok('everything should be ok');
}
});
});
suite('#api tests', function() {
var dummyContainer;
var thumbnailList;
suiteSetup(function() {
MockThumbnailGroup.reset();
dummyContainer = document.createElement('div');
// we use mock thumbnail group which will not add any thumbnail item to
// container.
thumbnailList = new ThumbnailList(MockThumbnailGroup, dummyContainer);
});
test('#addItem, simple', function() {
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.addItem({'name': 'dummy-file-name-07.3gp'});
assert.equal(dummyContainer.firstChild.textContent, '2013-07');
assert.equal(thumbnailList.count, 1);
});
test('#addItem, first, middle, last', function() {
// first
MockThumbnailGroup._GroupID = '2013-09';
thumbnailList.addItem({'name': 'dummy-file-name-09.3gp'});
assert.equal(dummyContainer.firstChild.textContent, '2013-09');
assert.equal(thumbnailList.count, 2);
// middle
MockThumbnailGroup._GroupID = '2013-08';
thumbnailList.addItem({'name': 'dummy-file-name-08.3gp'});
assert.equal(dummyContainer.children[1].textContent, '2013-08');
assert.equal(thumbnailList.count, 3);
// last
MockThumbnailGroup._GroupID = '2013-06';
thumbnailList.addItem({'name': 'dummy-file-name-06.3gp'});
assert.equal(dummyContainer.children[3].textContent, '2013-06');
assert.equal(thumbnailList.count, 4);
});
test('#addItem, to existed group', function() {
// first
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.addItem({'name': 'dummy-file-name-07-2.3gp'});
assert.equal(thumbnailList.count, 5);
assert.equal(MockThumbnailGroup._GroupMap['2013-07'].getCount(), 2);
assert.equal(dummyContainer.children.length, 4);
});
test('#addItem, empty', function() {
// first
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.addItem(null);
assert.equal(thumbnailList.count, 5);
assert.equal(MockThumbnailGroup._GroupMap['2013-07'].getCount(), 2);
assert.equal(dummyContainer.children.length, 4);
});
test('#addItem, duplicated', function() {
// first
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.addItem({'name': 'dummy-file-name-07-2.3gp'});
assert.equal(thumbnailList.count, 5);
assert.equal(MockThumbnailGroup._GroupMap['2013-07'].getCount(), 2);
assert.equal(dummyContainer.children.length, 4);
});
test('#removeItem', function() {
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.removeItem('dummy-file-name-07-2.3gp');
assert.equal(thumbnailList.count, 4);
assert.equal(MockThumbnailGroup._GroupMap['2013-07'].getCount(), 1);
thumbnailList.removeItem('dummy-file-name-07.3gp');
assert.equal(thumbnailList.count, 3);
assert.equal(MockThumbnailGroup._GroupMap['2013-07'].getCount(), 0);
assert.equal(dummyContainer.children.length, 3);
});
test('#removeItem, empty', function() {
MockThumbnailGroup._GroupID = '2013-07';
thumbnailList.removeItem(null);
assert.equal(thumbnailList.count, 3);
});
test('#thumbnailMap', function() {
assert.isDefined(thumbnailList.thumbnailMap['dummy-file-name-06.3gp']);
});
test('#pick mode', function() {
thumbnailList.setPickMode(true);
assert.isTrue(thumbnailList.isPickMode());
assert.isTrue(dummyContainer.classList.contains('pick'));
thumbnailList.setPickMode(false);
assert.isFalse(thumbnailList.isPickMode());
assert.isFalse(dummyContainer.classList.contains('pick'));
});
test('#select mode', function() {
thumbnailList.setSelectMode(true);
assert.isTrue(thumbnailList.isSelectMode());
assert.isTrue(dummyContainer.classList.contains('select'));
thumbnailList.setSelectMode(false);
assert.isFalse(thumbnailList.isSelectMode());
assert.isFalse(dummyContainer.classList.contains('select'));
});
test('#reset', function() {
thumbnailList.reset();
assert.equal(thumbnailList.count, 0);
assert.isUndefined(thumbnailList.thumbnailMap['dummy-file-name-06.3gp']);
});
});
});

View file

@ -0,0 +1,143 @@
/* globals MockVideoPlayer, ForwardRewindController:true */
'use strict';
requireApp('/video/test/unit/mock_video_player.js');
requireApp('/video/js/forward_rewind_controller.js');
var pause;
suite('Video forward rewind Unit Tests', function() {
var seekForward;
var seekBackward;
var play;
var videoToolBar;
var player;
var videoDuration = 50;
var pauseSpy;
var fakeTimer;
suiteSetup(function() {
videoToolBar = document.createElement('div');
seekForward = document.createElement('button');
seekBackward = document.createElement('button');
play = document.createElement('button');
videoToolBar.appendChild(seekBackward);
videoToolBar.appendChild(play);
videoToolBar.appendChild(seekForward);
player = new MockVideoPlayer();
player.setDuration(videoDuration);
ForwardRewindController.init(player, seekForward,
seekBackward);
pauseSpy = sinon.spy();
pause = pauseSpy;
fakeTimer = sinon.useFakeTimers();
});
suiteTeardown(function() {
ForwardRewindController.uninit(player, seekForward,
seekBackward);
});
suite('#Video Forward/Rewind Test', function() {
var simulateClick = function(button) {
var evt = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
button.dispatchEvent(evt);
};
var simulateContextMenu = function(button) {
var ev = document.createEvent('MouseEvents');
ev.initMouseEvent('contextmenu', true, false, window, 0, 0, 0, 0, 0,
false, false, false, false, 1, null);
button.dispatchEvent(ev);
};
setup(function() {
pauseSpy.reset();
});
test('#Test Playing Video Forward Button Tap Test', function() {
simulateClick(seekForward);
assert.equal(player.currentTime, 10);
});
test('#Test Playing Video Rewind Button Tap Test', function() {
simulateClick(seekBackward);
assert.equal(player.currentTime, 0);
});
test('#Test Playing Video Play Button Tap Test', function() {
simulateClick(play);
simulateClick(seekForward);
assert.equal(player.currentTime, 10);
simulateClick(seekBackward);
assert.equal(player.currentTime, 0);
});
test('#Test Playing Video Play Button Tap Test, wrap', function() {
player.currentTime = videoDuration - 5;
simulateClick(play);
simulateClick(seekForward);
assert.equal(player.currentTime, videoDuration);
assert.isTrue(pauseSpy.calledOnce);
});
test('#Test Playing Video Rewind Button Tap Test, wrap', function() {
player.currentTime = 5;
simulateClick(play);
simulateClick(seekBackward);
assert.equal(player.currentTime, 0);
assert.equal(pauseSpy.callCount, 0);
});
test('#Test Playing Video Forward Button Hold Test', function() {
var currentTime = player.currentTime;
simulateContextMenu(seekForward);
fakeTimer.tick(1500);
ForwardRewindController.stopFastSeeking();
assert.equal(player.currentTime, currentTime + 10);
assert.equal(pauseSpy.callCount, 0);
});
test('#Test Playing Video Forward Button Hold Test, wrap', function() {
player.currentTime = videoDuration - 5;
simulateContextMenu(seekForward);
fakeTimer.tick(1500);
ForwardRewindController.stopFastSeeking();
assert.equal(player.currentTime, videoDuration);
assert.isTrue(pauseSpy.calledOnce);
});
test('#Test Playing Video Rewind Button Hold Test', function() {
player.currentTime = 20;
simulateContextMenu(seekBackward);
fakeTimer.tick(1500);
ForwardRewindController.stopFastSeeking();
assert.equal(player.currentTime, 10);
assert.equal(pauseSpy.callCount, 0);
});
test('#Test Playing Video Rewind Button Hold Test, wrap', function() {
player.currentTime = 5;
simulateContextMenu(seekBackward);
fakeTimer.tick(1500);
ForwardRewindController.stopFastSeeking();
assert.equal(player.currentTime, 0);
assert.equal(pauseSpy.callCount, 0);
});
});
});

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,303 @@
/* global VideoUtils */
'use strict';
requireApp('/video/js/video_utils.js');
suite('Video Utils Unit Tests', function() {
suite('#fitContiner tests - 4:3 video fit HVGA', function() {
test('fit 640x480 to HVGA, 0deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,120.0000px) scale(0.5000)');
});
test('fit 640x480 to HVGA, 90deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 90);
assert.equal(testPlayer.style.transform,
'translate(320.0000px,26.6667px) rotate(90deg) scale(0.6667)');
});
test('fit 640x480 to HVGA, 180deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 180);
assert.equal(testPlayer.style.transform,
'translate(320.0000px,360.0000px) rotate(180deg) scale(0.5000)');
});
test('fit 640x480 to HVGA, 270deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 270);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,453.3333px) rotate(270deg) scale(0.6667)');
});
test('fit 640x480 to HVGA landscape, 0deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 480, clientHeight: 320},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(26.6667px,0.0000px) scale(0.6667)');
});
test('fit 640x480 to HVGA landscape, 90deg', function() {
var testPlayer = {videoWidth: 640, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 480, clientHeight: 320},
testPlayer, 90);
assert.equal(testPlayer.style.transform,
'translate(360.0000px,0.0000px) rotate(90deg) scale(0.5000)');
});
test('fit 320x240 to HVGA, 0deg, no scale', function() {
var testPlayer = {videoWidth: 320, videoHeight: 240, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,120.0000px) scale(1.0000)');
});
test('fit 240x180 to HVGA, 0deg, scale up', function() {
var testPlayer = {videoWidth: 240, videoHeight: 180, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,120.0000px) scale(1.3333)');
});
test('fit 320x480 to HVGA, 0deg, 100% fit', function() {
var testPlayer = {videoWidth: 320, videoHeight: 480, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,0.0000px) scale(1.0000)');
});
});
suite('#fitContiner tests - 16:9 video fit HVGA', function() {
test('fit 720p to HVGA, 0deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,150.0000px) scale(0.2500)');
});
test('fit 720p to HVGA, 90deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 90);
assert.equal(testPlayer.style.transform,
'translate(295.0000px,0.0000px) rotate(90deg) scale(0.3750)');
});
test('fit 720p to HVGA, 180deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 180);
assert.equal(testPlayer.style.transform,
'translate(320.0000px,330.0000px) rotate(180deg) scale(0.2500)');
});
test('fit 720p to HVGA, 270deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 320, clientHeight: 480},
testPlayer, 270);
assert.equal(testPlayer.style.transform,
'translate(25.0000px,480.0000px) rotate(270deg) scale(0.3750)');
});
test('fit 720p to HVGA landscape, 0deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 480, clientHeight: 320},
testPlayer, 0);
assert.equal(testPlayer.style.transform,
'translate(0.0000px,25.0000px) scale(0.3750)');
});
test('fit 720p to HVGA landscape, 90deg', function() {
var testPlayer = {videoWidth: 1280, videoHeight: 720, style: {}};
VideoUtils.fitContainer({clientWidth: 480, clientHeight: 320},
testPlayer, 90);
assert.equal(testPlayer.style.transform,
'translate(330.0000px,0.0000px) rotate(90deg) scale(0.2500)');
});
});
suite('getTruncated tests', function() {
var _clientHeight;
var titleNode;
var inputTitleText;
suiteSetup(function() {
titleNode = document.createElement('span');
// override native clientHeight
_clientHeight = Object.getOwnPropertyDescriptor(
Element.prototype, 'clientHeight');
Object.defineProperty(Element.prototype, 'clientHeight', {
configurable: true,
enumerable: true,
get: function videoUtilsTestClientHeightStub() {
function getPaddingInt(paddingInput) {
var paddingInt = parseInt(paddingInput, 10);
return Number.isInteger(paddingInt) ? paddingInt : 0;
}
//
// the video_utils getTruncated function uses clientHeight
// to determine the height of the title text. clientHeight
// includes padding, therfore, we have tests that set
// padding on the title node to test that getTruncated
// filters out the padding when determine the line height.
//
var padding = getPaddingInt(this.style.paddingTop) +
getPaddingInt(this.style.paddingBottom);
if (this.textContent.length >= 60) {
return 6 + padding;
}
if (this.textContent.length >= 50) {
return 5 + padding;
}
if (this.textContent.length >= 40) {
return 4 + padding;
}
if (this.textContent.length >= 30) {
return 3 + padding;
}
if (this.textContent.length >= 20) {
return 2 + padding;
}
if (this.textContent === '.') {
return 1 + padding;
}
return 1 + padding;
}
});
});
suiteTeardown(function() {
Object.defineProperty(Element.prototype, 'clientHeight', _clientHeight);
});
setup(function() {
titleNode.style.visibility = 'visible';
titleNode.style.wordBreak = 'normal';
titleNode.style.paddingTop = '';
titleNode.style.paddingBottom = '';
});
test('title fits within max lines, maxLine specified', function() {
inputTitleText = '1111111111222222222233333333334444444444';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode,
maxLine: 4
});
assert.equal(inputTitleText, truncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('title fits within max lines, maxLine specified, padding', function() {
inputTitleText = '1111111111222222222233333333334444444444';
titleNode.style.paddingTop = '4px';
titleNode.style.paddingBottom = '4px';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode,
maxLine: 4
});
assert.equal(inputTitleText, truncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('title fits within max lines, maxLine not specified', function() {
inputTitleText = '11111111112222222222';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode
});
assert.equal(inputTitleText, truncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('title doesnt fit, maxLine not specified', function() {
inputTitleText = '111111111122222222223333333333';
var expectedTruncatedTitle = '11111111112222222222333333...';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode
});
assert.equal(truncatedTitle, expectedTruncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('title doesnt fit, maxLine specified', function() {
inputTitleText = '1111111111222222222233333333334444444444';
var expectedTruncatedTitle = '111111111122222222223333333333444444...';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode,
maxLine: 3
});
assert.equal(truncatedTitle, expectedTruncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('title doesnt fit, maxLine specified, padding', function() {
titleNode.style.paddingTop = '4px';
titleNode.style.paddingBottom = '4px';
inputTitleText = '1111111111222222222233333333334444444444';
var expectedTruncatedTitle = '111111111122222222223333333333444444...';
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: titleNode,
maxLine: 3
});
assert.equal(truncatedTitle, expectedTruncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
test('node is null', function() {
var node = null;
var inputTitleText;
var truncatedTitle = VideoUtils.getTruncated(inputTitleText,
{
node: node,
maxLine: 4,
ellipsisIndex: 0
});
assert.equal(inputTitleText, truncatedTitle);
assert.equal(titleNode.style.visibility, 'visible');
assert.equal(titleNode.style.wordBreak, 'normal');
});
});
});