2017-05-25 20:09:00 +02:00
|
|
|
/* eslint-env qunit */
|
|
|
|
import Html5 from '../../../src/js/tech/html5.js';
|
2018-06-21 20:20:12 +02:00
|
|
|
import { constructColor } from '../../../src/js/tracks/text-track-display.js';
|
2017-05-25 20:09:00 +02:00
|
|
|
import Component from '../../../src/js/component.js';
|
|
|
|
|
|
|
|
import * as browser from '../../../src/js/utils/browser.js';
|
|
|
|
import TestHelpers from '../test-helpers.js';
|
|
|
|
import document from 'global/document';
|
|
|
|
import sinon from 'sinon';
|
|
|
|
|
|
|
|
QUnit.module('Text Track Display', {
|
|
|
|
beforeEach(assert) {
|
|
|
|
this.clock = sinon.useFakeTimers();
|
|
|
|
},
|
|
|
|
afterEach(assert) {
|
|
|
|
this.clock.restore();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const getMenuItemByLanguage = function(items, language) {
|
|
|
|
for (let i = items.length - 1; i > 0; i--) {
|
|
|
|
const captionMenuItem = items[i];
|
|
|
|
const trackLanguage = captionMenuItem.track.language;
|
|
|
|
|
|
|
|
if (trackLanguage && trackLanguage === language) {
|
|
|
|
return captionMenuItem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
QUnit.test('if native text tracks are not supported, create a texttrackdisplay', function(assert) {
|
|
|
|
const oldTestVid = Html5.TEST_VID;
|
|
|
|
const oldIsFirefox = browser.IS_FIREFOX;
|
|
|
|
const oldTextTrackDisplay = Component.getComponent('TextTrackDisplay');
|
|
|
|
const tag = document.createElement('video');
|
|
|
|
const track1 = document.createElement('track');
|
|
|
|
const track2 = document.createElement('track');
|
|
|
|
|
|
|
|
track1.kind = 'captions';
|
|
|
|
track1.label = 'en';
|
|
|
|
track1.language = 'English';
|
|
|
|
track1.src = 'en.vtt';
|
|
|
|
tag.appendChild(track1);
|
|
|
|
|
|
|
|
track2.kind = 'captions';
|
|
|
|
track2.label = 'es';
|
|
|
|
track2.language = 'Spanish';
|
|
|
|
track2.src = 'es.vtt';
|
|
|
|
tag.appendChild(track2);
|
|
|
|
|
|
|
|
Html5.TEST_VID = {
|
|
|
|
textTracks: []
|
|
|
|
};
|
|
|
|
|
|
|
|
browser.IS_FIREFOX = true;
|
|
|
|
|
|
|
|
const fakeTTDSpy = sinon.spy();
|
|
|
|
|
|
|
|
class FakeTTD extends Component {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
fakeTTDSpy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.registerComponent('TextTrackDisplay', FakeTTD);
|
|
|
|
|
|
|
|
const player = TestHelpers.makePlayer({}, tag);
|
|
|
|
|
|
|
|
assert.strictEqual(fakeTTDSpy.callCount, 1, 'text track display was created');
|
|
|
|
|
|
|
|
Html5.TEST_VID = oldTestVid;
|
|
|
|
browser.IS_FIREFOX = oldIsFirefox;
|
|
|
|
Component.registerComponent('TextTrackDisplay', oldTextTrackDisplay);
|
|
|
|
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('shows the default caption track first', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt',
|
|
|
|
default: true
|
|
|
|
};
|
|
|
|
const track2 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'Spanish',
|
|
|
|
language: 'es',
|
|
|
|
src: 'es.vtt'
|
|
|
|
};
|
|
|
|
|
|
|
|
// Add the text tracks
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
|
|
|
const spanishTrack = player.addRemoteTextTrack(track2, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Make sure the ready handler runs
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.ok(englishTrack.mode === 'showing', 'English track should be showing');
|
|
|
|
assert.ok(spanishTrack.mode === 'disabled', 'Spanish track should not be showing');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!Html5.supportsNativeTextTracks()) {
|
|
|
|
QUnit.test('selectedlanguagechange is triggered by a track mode change', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
const spy = sinon.spy();
|
|
|
|
const selectedLanguageHandler = function(event) {
|
|
|
|
spy();
|
|
|
|
};
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
player.textTracks().addEventListener('selectedlanguagechange', selectedLanguageHandler);
|
|
|
|
englishTrack.mode = 'showing';
|
|
|
|
|
|
|
|
assert.strictEqual(spy.callCount, 1, 'selectedlanguagechange event was fired');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test("if user-selected language is unavailable, don't pick a track to show", function(assert) {
|
|
|
|
// The video has no default language but has ‘English’ captions only
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
|
|
|
|
|
|
|
player.src({type: 'video/mp4', src: 'http://google.com'});
|
|
|
|
// manualCleanUp = true by default
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Force 'es' as user-selected track
|
|
|
|
player.cache_.selectedLanguage = { language: 'es', kind: 'captions' };
|
|
|
|
|
|
|
|
this.clock.tick(1);
|
|
|
|
player.play();
|
|
|
|
|
|
|
|
assert.ok(!captionsButton.hasClass('vjs-hidden'), 'The captions button is shown');
|
|
|
|
assert.ok(englishTrack.mode === 'disabled', 'English track should be disabled');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('the user-selected language takes priority over default language', function(assert) {
|
|
|
|
// The video has ‘English’ captions as default, but has ‘Spanish’ captions also
|
2017-05-26 00:05:45 +02:00
|
|
|
const player = TestHelpers.makePlayer();
|
2017-05-25 20:09:00 +02:00
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt',
|
|
|
|
default: true
|
|
|
|
};
|
|
|
|
const track2 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'Spanish',
|
|
|
|
language: 'es',
|
|
|
|
src: 'es.vtt'
|
|
|
|
};
|
|
|
|
|
|
|
|
player.src({type: 'video/mp4', src: 'http://google.com'});
|
|
|
|
// manualCleanUp = true by default
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
|
|
|
const spanishTrack = player.addRemoteTextTrack(track2, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Force 'es' as user-selected track
|
|
|
|
player.cache_.selectedLanguage = { enabled: true, language: 'es', kind: 'captions' };
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.ok(spanishTrack.mode === 'showing', 'Spanish captions should be shown');
|
|
|
|
assert.ok(englishTrack.mode === 'disabled', 'English captions should be hidden');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test("matching both the selectedLanguage's language and kind takes priority over just matching the language", function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
const track2 = {
|
|
|
|
kind: 'subtitles',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
|
|
|
|
player.src({type: 'video/mp4', src: 'http://google.com'});
|
|
|
|
// manualCleanUp = true by default
|
2017-10-23 20:26:18 +02:00
|
|
|
const captionTrack = player.addRemoteTextTrack(track1, true).track;
|
|
|
|
const subsTrack = player.addRemoteTextTrack(track2, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Force English captions as user-selected track
|
|
|
|
player.cache_.selectedLanguage = { enabled: true, language: 'en', kind: 'captions' };
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
assert.ok(captionTrack.mode === 'showing', 'Captions track should be preselected');
|
|
|
|
assert.ok(subsTrack.mode === 'disabled', 'Subtitles track should remain disabled');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('the user-selected language is used for subsequent source changes', function(assert) {
|
|
|
|
// Start with two captions tracks: English and Spanish
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
const track2 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'Spanish',
|
|
|
|
language: 'es',
|
|
|
|
src: 'es.vtt'
|
|
|
|
};
|
|
|
|
const tracks = player.tech_.remoteTextTracks();
|
|
|
|
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
|
|
|
let esCaptionMenuItem;
|
|
|
|
let enCaptionMenuItem;
|
|
|
|
|
|
|
|
player.src({type: 'video/mp4', src: 'http://google.com'});
|
|
|
|
// manualCleanUp = true by default
|
2017-10-23 20:26:18 +02:00
|
|
|
player.addRemoteTextTrack(track1, true);
|
|
|
|
player.addRemoteTextTrack(track2, true);
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Keep track of menu items
|
|
|
|
esCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'es');
|
|
|
|
enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
|
|
|
|
|
|
|
// The user chooses Spanish
|
|
|
|
player.play();
|
|
|
|
esCaptionMenuItem.trigger('click');
|
|
|
|
|
|
|
|
// Track mode changes on user-selection
|
|
|
|
assert.ok(esCaptionMenuItem.track.mode === 'showing',
|
|
|
|
'Spanish should be showing after selection');
|
|
|
|
assert.ok(enCaptionMenuItem.track.mode === 'disabled',
|
|
|
|
'English should be disabled after selecting Spanish');
|
|
|
|
assert.deepEqual(player.cache_.selectedLanguage,
|
|
|
|
{ enabled: true, language: 'es', kind: 'captions' });
|
|
|
|
|
|
|
|
// Switch source and remove old tracks
|
|
|
|
player.tech_.src({type: 'video/mp4', src: 'http://example.com'});
|
|
|
|
while (tracks.length > 0) {
|
|
|
|
player.removeRemoteTextTrack(tracks[0]);
|
|
|
|
}
|
|
|
|
// Add tracks for the new source
|
|
|
|
// change the kind of track to subtitles
|
|
|
|
track1.kind = 'subtitles';
|
|
|
|
track2.kind = 'subtitles';
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
|
|
|
const spanishTrack = player.addRemoteTextTrack(track2, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Make sure player ready handler runs
|
|
|
|
this.clock.tick(1);
|
|
|
|
|
|
|
|
// Keep track of menu items
|
|
|
|
esCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'es');
|
|
|
|
enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
|
|
|
|
|
|
|
// The user-selection should have persisted
|
|
|
|
assert.ok(esCaptionMenuItem.track.mode === 'showing',
|
|
|
|
'Spanish should remain showing');
|
|
|
|
assert.ok(enCaptionMenuItem.track.mode === 'disabled',
|
|
|
|
'English should remain disabled');
|
|
|
|
assert.deepEqual(player.cache_.selectedLanguage,
|
|
|
|
{ enabled: true, language: 'es', kind: 'captions' });
|
|
|
|
|
|
|
|
assert.ok(spanishTrack.mode === 'showing', 'Spanish track remains showing');
|
|
|
|
assert.ok(englishTrack.mode === 'disabled', 'English track remains disabled');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('the user-selected language is cleared on turning off captions', function(assert) {
|
|
|
|
const player = TestHelpers.makePlayer();
|
|
|
|
const track1 = {
|
|
|
|
kind: 'captions',
|
|
|
|
label: 'English',
|
|
|
|
language: 'en',
|
|
|
|
src: 'en.vtt'
|
|
|
|
};
|
|
|
|
const captionsButton = player.controlBar.getChild('SubsCapsButton');
|
|
|
|
|
|
|
|
player.src({type: 'video/mp4', src: 'http://google.com'});
|
|
|
|
// manualCleanUp = true by default
|
2017-10-23 20:26:18 +02:00
|
|
|
const englishTrack = player.addRemoteTextTrack(track1, true).track;
|
2017-05-25 20:09:00 +02:00
|
|
|
// Keep track of menu items
|
|
|
|
const enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
2017-11-16 18:19:47 +02:00
|
|
|
// we know the postition of the OffTextTrackMenuItem
|
|
|
|
const offMenuItem = captionsButton.items[1];
|
2017-05-25 20:09:00 +02:00
|
|
|
|
|
|
|
// Select English initially
|
|
|
|
player.play();
|
|
|
|
enCaptionMenuItem.trigger('click');
|
|
|
|
|
|
|
|
assert.deepEqual(player.cache_.selectedLanguage,
|
|
|
|
{ enabled: true, language: 'en', kind: 'captions' }, 'English track is selected');
|
|
|
|
assert.ok(englishTrack.mode === 'showing', 'English track should be showing');
|
|
|
|
|
|
|
|
// Select the off button
|
|
|
|
offMenuItem.trigger('click');
|
|
|
|
|
|
|
|
assert.deepEqual(player.cache_.selectedLanguage,
|
|
|
|
{ enabled: false }, 'selectedLanguage is cleared');
|
|
|
|
assert.ok(englishTrack.mode === 'disabled', 'English track is disabled');
|
|
|
|
player.dispose();
|
|
|
|
});
|
|
|
|
|
2018-06-21 20:20:12 +02:00
|
|
|
QUnit.test('a color can be constructed from a three digit hex code', function(assert) {
|
|
|
|
const hex = '#f0e';
|
|
|
|
|
|
|
|
// f gets mapped to ff -> 255 in decimal,
|
|
|
|
// 0 gets mapped to 00 -> 0 in decimal,
|
|
|
|
// e gets mapped to ee -> 238 in decimal.
|
|
|
|
assert.equal(constructColor(hex, 1), 'rgba(255,0,238,1)');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('a color can be constructed from a six digit hex code', function(assert) {
|
|
|
|
const hex = '#f604e2';
|
|
|
|
|
|
|
|
// f6 -> 246 in decimal,
|
|
|
|
// 04 -> 4 in decimal,
|
|
|
|
// e2 -> 226 in decimal.
|
|
|
|
assert.equal(constructColor(hex, 1), 'rgba(246,4,226,1)');
|
|
|
|
});
|
|
|
|
|
|
|
|
QUnit.test('an invalid hex code will throw an error', function(assert) {
|
|
|
|
const hex = '#f';
|
|
|
|
|
|
|
|
assert.throws(
|
|
|
|
function() {
|
|
|
|
constructColor(hex, 1);
|
|
|
|
},
|
|
|
|
new Error('Invalid color code provided, #f; must be formatted as e.g. #f0e or #f604e2.'),
|
|
|
|
'colors must be valid hex codes.'
|
|
|
|
);
|
|
|
|
});
|
2017-05-25 20:09:00 +02:00
|
|
|
}
|