mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-24 17:35:10 +03:00
064089152b
This is an automated fix to be inline with Google style guides, this was created with eslint's --fix option. Change-Id: I860eecbc8152603e730aa17a1393f16d26b3b6fc
421 lines
12 KiB
JavaScript
421 lines
12 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
describe('SimpleTextDisplayer', function() {
|
|
const originalVTTCue = window.VTTCue;
|
|
const originalVTTRegion = window.VTTRegion;
|
|
const Cue = shaka.text.Cue;
|
|
const CueRegion = shaka.text.CueRegion;
|
|
const SimpleTextDisplayer = shaka.text.SimpleTextDisplayer;
|
|
|
|
/** @type {!shaka.test.FakeVideo} */
|
|
let video;
|
|
/** @type {!shaka.test.FakeTextTrack} */
|
|
let mockTrack;
|
|
/** @type {!shaka.text.SimpleTextDisplayer} */
|
|
let displayer;
|
|
|
|
beforeEach(function() {
|
|
video = new shaka.test.FakeVideo();
|
|
displayer = new SimpleTextDisplayer(video);
|
|
|
|
expect(video.textTracks.length).toBe(1);
|
|
mockTrack = /** @type {!shaka.test.FakeTextTrack} */ (video.textTracks[0]);
|
|
expect(mockTrack).toBeTruthy();
|
|
|
|
/**
|
|
* @constructor
|
|
* @param {number} start
|
|
* @param {number} end
|
|
* @param {string} text
|
|
*/
|
|
function FakeVTTCue(start, end, text) {
|
|
this.startTime = start;
|
|
this.endTime = end;
|
|
this.text = text;
|
|
}
|
|
window.VTTCue = /** @type {?} */(FakeVTTCue);
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function FakeVTTRegion() {}
|
|
window.VTTRegion = /** @type {?} */(FakeVTTRegion);
|
|
});
|
|
|
|
afterAll(function() {
|
|
window.VTTCue = originalVTTCue;
|
|
window.VTTRegion = originalVTTRegion;
|
|
});
|
|
|
|
describe('append', function() {
|
|
it('sorts cues before inserting', function() {
|
|
// See: https://goo.gl/BirBy9
|
|
verifyHelper(
|
|
[
|
|
{start: 10, end: 20, text: 'Test1'},
|
|
{start: 20, end: 30, text: 'Test2'},
|
|
{start: 30, end: 40, text: 'Test3'}
|
|
],
|
|
[
|
|
new shaka.text.Cue(20, 30, 'Test2'),
|
|
new shaka.text.Cue(30, 40, 'Test3'),
|
|
new shaka.text.Cue(10, 20, 'Test1')
|
|
]);
|
|
});
|
|
|
|
it('appends equal time cues in reverse order', function() {
|
|
// Regression test for https://github.com/google/shaka-player/issues/848
|
|
verifyHelper(
|
|
[
|
|
{start: 20, end: 40, text: 'Test1'},
|
|
{start: 20, end: 40, text: 'Test2'},
|
|
{start: 20, end: 40, text: 'Test3'}
|
|
],
|
|
[
|
|
new shaka.text.Cue(20, 40, 'Test3'),
|
|
new shaka.text.Cue(20, 40, 'Test2'),
|
|
new shaka.text.Cue(20, 40, 'Test1')
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('remove', function() {
|
|
it('removes cues which overlap the range', function() {
|
|
let cue1 = new shaka.text.Cue(0, 1, 'Test');
|
|
let cue2 = new shaka.text.Cue(1, 2, 'Test');
|
|
let cue3 = new shaka.text.Cue(2, 3, 'Test');
|
|
displayer.append([cue1, cue2, cue3]);
|
|
|
|
displayer.remove(0, 1);
|
|
expect(mockTrack.removeCue.calls.count()).toBe(1);
|
|
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({startTime: 0, endTime: 1}));
|
|
mockTrack.removeCue.calls.reset();
|
|
|
|
displayer.remove(0.5, 1.001);
|
|
expect(mockTrack.removeCue.calls.count()).toBe(1);
|
|
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({startTime: 1, endTime: 2}));
|
|
mockTrack.removeCue.calls.reset();
|
|
|
|
displayer.remove(3, 5);
|
|
expect(mockTrack.removeCue).not.toHaveBeenCalled();
|
|
mockTrack.removeCue.calls.reset();
|
|
|
|
displayer.remove(2.9999, Infinity);
|
|
expect(mockTrack.removeCue.calls.count()).toBe(1);
|
|
expect(mockTrack.removeCue).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({startTime: 2, endTime: 3}));
|
|
mockTrack.removeCue.calls.reset();
|
|
});
|
|
|
|
it('does nothing when nothing is buffered', function() {
|
|
displayer.remove(0, 1);
|
|
expect(mockTrack.removeCue).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('convertToTextTrackCue', function() {
|
|
it('converts shaka.text.Cues to VttCues', function() {
|
|
verifyHelper(
|
|
[
|
|
{start: 20, end: 40, text: 'Test'}
|
|
],
|
|
[
|
|
new shaka.text.Cue(20, 40, 'Test')
|
|
]);
|
|
|
|
let cue1 = new shaka.text.Cue(20, 40, 'Test');
|
|
cue1.positionAlign = Cue.positionAlign.LEFT;
|
|
cue1.lineAlign = Cue.lineAlign.START;
|
|
cue1.size = 80;
|
|
cue1.textAlign = Cue.textAlign.LEFT;
|
|
cue1.writingDirection = Cue.writingDirection.VERTICAL_LEFT_TO_RIGHT;
|
|
cue1.lineInterpretation = Cue.lineInterpretation.LINE_NUMBER;
|
|
cue1.line = 5;
|
|
cue1.position = 10;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 20,
|
|
end: 40,
|
|
text: 'Test',
|
|
lineAlign: 'start',
|
|
positionAlign: 'line-left',
|
|
size: 80,
|
|
align: 'left',
|
|
vertical: 'lr',
|
|
snapToLines: true,
|
|
line: 5,
|
|
position: 10
|
|
}
|
|
], [cue1]);
|
|
|
|
let cue2 = new shaka.text.Cue(30, 50, 'Test');
|
|
cue2.positionAlign = Cue.positionAlign.RIGHT;
|
|
cue2.lineAlign = Cue.lineAlign.END;
|
|
cue2.textAlign = Cue.textAlign.RIGHT;
|
|
cue2.writingDirection = Cue.writingDirection.VERTICAL_RIGHT_TO_LEFT;
|
|
cue2.lineInterpretation = Cue.lineInterpretation.PERCENTAGE;
|
|
cue2.line = 5;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 30,
|
|
end: 50,
|
|
text: 'Test',
|
|
lineAlign: 'end',
|
|
positionAlign: 'line-right',
|
|
align: 'right',
|
|
vertical: 'rl',
|
|
snapToLines: false,
|
|
line: 5
|
|
}
|
|
], [cue2]);
|
|
|
|
let cue3 = new shaka.text.Cue(40, 60, 'Test');
|
|
cue3.positionAlign = Cue.positionAlign.CENTER;
|
|
cue3.lineAlign = Cue.lineAlign.CENTER;
|
|
cue3.textAlign = Cue.textAlign.START;
|
|
cue3.writingDirection = Cue.writingDirection.HORIZONTAL_LEFT_TO_RIGHT;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 40,
|
|
end: 60,
|
|
text: 'Test',
|
|
lineAlign: 'center',
|
|
positionAlign: 'center',
|
|
align: 'start',
|
|
vertical: undefined
|
|
}
|
|
], [cue3]);
|
|
|
|
let cue4 = new shaka.text.Cue(40, 60, 'Test');
|
|
cue4.line = null;
|
|
cue4.position = null;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 40,
|
|
end: 60,
|
|
text: 'Test',
|
|
// In a real VTTCue, these would be the default of "auto".
|
|
// With our mock, we leave them unset and they are undefined.
|
|
line: undefined,
|
|
position: undefined
|
|
}
|
|
], [cue4]);
|
|
|
|
let cue5 = new shaka.text.Cue(40, 60, 'Test');
|
|
cue5.line = 0;
|
|
cue5.position = 0;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 40,
|
|
end: 60,
|
|
text: 'Test',
|
|
line: 0,
|
|
position: 0
|
|
}
|
|
], [cue5]);
|
|
});
|
|
|
|
it('works around browsers not supporting align=center', function() {
|
|
/**
|
|
* @constructor
|
|
* @param {number} start
|
|
* @param {number} end
|
|
* @param {string} text
|
|
*/
|
|
function FakeVTTCueWithoutAlignCenter(start, end, text) {
|
|
let align = 'middle';
|
|
Object.defineProperty(this, 'align', {
|
|
get: function() { return align; },
|
|
set: function(newValue) {
|
|
if (newValue != 'center') align = newValue;
|
|
}
|
|
});
|
|
this.startTime = start;
|
|
this.endTime = end;
|
|
this.text = text;
|
|
}
|
|
window.VTTCue = /** @type {?} */(FakeVTTCueWithoutAlignCenter);
|
|
|
|
let cue1 = new shaka.text.Cue(20, 40, 'Test');
|
|
cue1.textAlign = Cue.textAlign.CENTER;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 20,
|
|
end: 40,
|
|
text: 'Test',
|
|
align: 'middle'
|
|
}
|
|
],
|
|
[cue1]);
|
|
});
|
|
|
|
it('ignores cues with startTime >= endTime', function() {
|
|
let cue1 = new shaka.text.Cue(60, 40, 'Test');
|
|
let cue2 = new shaka.text.Cue(40, 40, 'Test');
|
|
displayer.append([cue1, cue2]);
|
|
expect(mockTrack.addCue).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('ConvertToVttRegion', function() {
|
|
it('converts shaka.text.CueRegions to VTTRegions', function() {
|
|
let region1 = new shaka.text.CueRegion();
|
|
region1.id = 'reg1';
|
|
region1.width = 50;
|
|
region1.scroll = CueRegion.scrollMode.UP;
|
|
region1.height = 3;
|
|
region1.heightUnits = CueRegion.units.LINES;
|
|
|
|
let cue1 = new shaka.text.Cue(20, 40, 'Test');
|
|
cue1.region = region1;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 20,
|
|
end: 40,
|
|
text: 'Test',
|
|
region: {
|
|
viewportAnchorX: 0,
|
|
viewportAnchorY: 0,
|
|
regionAnchorX: 0,
|
|
regionAnchorY: 0,
|
|
width: 50,
|
|
lines: 3,
|
|
scroll: 'up'
|
|
}
|
|
}
|
|
], [cue1]);
|
|
});
|
|
|
|
it('converts pixel values to percentage', function() {
|
|
let region1 = new shaka.text.CueRegion();
|
|
region1.id = 'reg1';
|
|
region1.width = 500;
|
|
region1.widthUnits = CueRegion.units.PX;
|
|
region1.viewportAnchorX = 100;
|
|
region1.viewportAnchorY = 100;
|
|
region1.viewportAnchorUnits = CueRegion.units.PX;
|
|
|
|
let cue1 = new shaka.text.Cue(20, 40, 'Test');
|
|
cue1.region = region1;
|
|
|
|
verifyHelper(
|
|
[
|
|
{
|
|
start: 20,
|
|
end: 40,
|
|
text: 'Test',
|
|
region: {
|
|
viewportAnchorX: 10,
|
|
viewportAnchorY: 10,
|
|
width: 50
|
|
}
|
|
}
|
|
], [cue1]);
|
|
});
|
|
});
|
|
|
|
function createFakeCue(startTime, endTime) {
|
|
return {startTime: startTime, endTime: endTime};
|
|
}
|
|
|
|
/**
|
|
* @param {!Array} vttCues
|
|
* @param {!Array.<!shaka.text.Cue>} shakaCues
|
|
*/
|
|
function verifyHelper(vttCues, shakaCues) {
|
|
mockTrack.addCue.calls.reset();
|
|
displayer.append(shakaCues);
|
|
let result = mockTrack.addCue.calls.allArgs().reduce(
|
|
shaka.util.Functional.collapseArrays, []);
|
|
expect(result).toBeTruthy();
|
|
expect(result.length).toBe(vttCues.length);
|
|
|
|
for (let i = 0; i < vttCues.length; i++) {
|
|
expect(result[i].startTime).toBe(vttCues[i].start);
|
|
expect(result[i].endTime).toBe(vttCues[i].end);
|
|
expect(result[i].text).toBe(vttCues[i].text);
|
|
|
|
if ('id' in vttCues[i]) {
|
|
expect(result[i].id).toBe(vttCues[i].id);
|
|
}
|
|
if ('vertical' in vttCues[i]) {
|
|
expect(result[i].vertical).toBe(vttCues[i].vertical);
|
|
}
|
|
if ('line' in vttCues[i]) {
|
|
expect(result[i].line).toBe(vttCues[i].line);
|
|
}
|
|
if ('align' in vttCues[i]) {
|
|
expect(result[i].align).toBe(vttCues[i].align);
|
|
}
|
|
if ('size' in vttCues[i]) {
|
|
expect(result[i].size).toBe(vttCues[i].size);
|
|
}
|
|
if ('position' in vttCues[i]) {
|
|
expect(result[i].position).toBe(vttCues[i].position);
|
|
}
|
|
if ('region' in vttCues[i]) {
|
|
verifyRegion(result[i].region, vttCues[i].region);
|
|
}
|
|
}
|
|
}
|
|
|
|
function verifyRegion(actual, expected) {
|
|
if ('id' in expected) {
|
|
expect(actual.id).toBe(expected.id);
|
|
}
|
|
if ('width' in expected) {
|
|
expect(actual.width).toBe(expected.width);
|
|
}
|
|
if ('lines' in expected) {
|
|
expect(actual.lines).toBe(expected.lines);
|
|
}
|
|
if ('regionAnchorX' in expected) {
|
|
expect(actual.regionAnchorX).toBe(expected.regionAnchorX);
|
|
}
|
|
if ('regionAnchorY' in expected) {
|
|
expect(actual.regionAnchorY).toBe(expected.regionAnchorY);
|
|
}
|
|
if ('viewportAnchorX' in expected) {
|
|
expect(actual.viewportAnchorX).toBe(expected.viewportAnchorX);
|
|
}
|
|
if ('viewportAnchorY' in expected) {
|
|
expect(actual.viewportAnchorY).toBe(expected.viewportAnchorY);
|
|
}
|
|
if ('scroll' in expected) {
|
|
expect(actual.scroll).toBe(expected.scroll);
|
|
}
|
|
}
|
|
});
|