mirror of
https://github.com/videojs/video.js.git
synced 2024-12-25 02:42:10 +02:00
feat: Persist caption/description choice over source changes in emulated tracks (#4295)
This commit is contained in:
parent
8f67b4fc54
commit
188ead1c81
@ -70,6 +70,26 @@ class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
this.selected(selected);
|
||||
}
|
||||
|
||||
handleSelectedLanguageChange(event) {
|
||||
const tracks = this.player().textTracks();
|
||||
let allHidden = true;
|
||||
|
||||
for (let i = 0, l = tracks.length; i < l; i++) {
|
||||
const track = tracks[i];
|
||||
|
||||
if ((['captions', 'descriptions', 'subtitles'].indexOf(track.kind) > -1) && track.mode === 'showing') {
|
||||
allHidden = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allHidden) {
|
||||
this.player_.cache_.selectedLanguage = {
|
||||
enabled: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem);
|
||||
|
@ -66,6 +66,7 @@ class TextTrackButton extends TrackButton {
|
||||
|
||||
// only add tracks that are of an appropriate kind and have a label
|
||||
if (this.kinds_.indexOf(track.kind) > -1) {
|
||||
|
||||
const item = new TrackMenuItem(this.player_, {
|
||||
track,
|
||||
// MenuItem is selectable
|
||||
|
@ -29,17 +29,20 @@ class TextTrackMenuItem extends MenuItem {
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
options.label = track.label || track.language || 'Unknown';
|
||||
options.selected = track.default || track.mode === 'showing';
|
||||
options.selected = track.mode === 'showing';
|
||||
|
||||
super(player, options);
|
||||
|
||||
this.track = track;
|
||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||
const selectedLanguageChangeHandler = Fn.bind(this, this.handleSelectedLanguageChange);
|
||||
|
||||
player.on(['loadstart', 'texttrackchange'], changeHandler);
|
||||
tracks.addEventListener('change', changeHandler);
|
||||
tracks.addEventListener('selectedlanguagechange', selectedLanguageChangeHandler);
|
||||
this.on('dispose', function() {
|
||||
tracks.removeEventListener('change', changeHandler);
|
||||
tracks.removeEventListener('selectedlanguagechange', selectedLanguageChangeHandler);
|
||||
});
|
||||
|
||||
// iOS7 doesn't dispatch change events to TextTrackLists when an
|
||||
@ -122,6 +125,25 @@ class TextTrackMenuItem extends MenuItem {
|
||||
this.selected(this.track.mode === 'showing');
|
||||
}
|
||||
|
||||
handleSelectedLanguageChange(event) {
|
||||
if (this.track.mode === 'showing') {
|
||||
const selectedLanguage = this.player_.cache_.selectedLanguage;
|
||||
|
||||
// Don't replace the kind of track across the same language
|
||||
if (selectedLanguage && selectedLanguage.enabled &&
|
||||
selectedLanguage.language === this.track.language &&
|
||||
selectedLanguage.kind !== this.track.kind) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.player_.cache_.selectedLanguage = {
|
||||
enabled: true,
|
||||
language: this.track.language,
|
||||
kind: this.track.kind
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('TextTrackMenuItem', TextTrackMenuItem);
|
||||
|
@ -92,6 +92,7 @@ class TextTrackDisplay extends Component {
|
||||
|
||||
player.on('loadstart', Fn.bind(this, this.toggleDisplay));
|
||||
player.on('texttrackchange', Fn.bind(this, this.updateDisplay));
|
||||
player.on('loadstart', Fn.bind(this, this.preselectTrack));
|
||||
|
||||
// This used to be called during player init, but was causing an error
|
||||
// if a track should show by default and the display hadn't loaded yet.
|
||||
@ -111,33 +112,66 @@ class TextTrackDisplay extends Component {
|
||||
this.player_.addRemoteTextTrack(tracks[i], true);
|
||||
}
|
||||
|
||||
const modes = {captions: 1, subtitles: 1};
|
||||
const trackList = this.player_.textTracks();
|
||||
let firstDesc;
|
||||
let firstCaptions;
|
||||
this.preselectTrack();
|
||||
}));
|
||||
}
|
||||
|
||||
for (let i = 0; i < trackList.length; i++) {
|
||||
const track = trackList[i];
|
||||
/**
|
||||
* Preselect a track following this precedence:
|
||||
* - matches the previously selected {@link TextTrack}'s language and kind
|
||||
* - matches the previously selected {@link TextTrack}'s language only
|
||||
* - is the first default captions track
|
||||
* - is the first default descriptions track
|
||||
*
|
||||
* @listens Player#loadstart
|
||||
*/
|
||||
preselectTrack() {
|
||||
const modes = {captions: 1, subtitles: 1};
|
||||
const trackList = this.player_.textTracks();
|
||||
const userPref = this.player_.cache_.selectedLanguage;
|
||||
let firstDesc;
|
||||
let firstCaptions;
|
||||
let preferredTrack;
|
||||
|
||||
if (track.default) {
|
||||
if (track.kind === 'descriptions' && !firstDesc) {
|
||||
firstDesc = track;
|
||||
} else if (track.kind in modes && !firstCaptions) {
|
||||
firstCaptions = track;
|
||||
}
|
||||
for (let i = 0; i < trackList.length; i++) {
|
||||
const track = trackList[i];
|
||||
|
||||
if (userPref && userPref.enabled &&
|
||||
userPref.language === track.language) {
|
||||
// Always choose the track that matches both language and kind
|
||||
if (track.kind === userPref.kind) {
|
||||
preferredTrack = track;
|
||||
// or choose the first track that matches language
|
||||
} else if (!preferredTrack) {
|
||||
preferredTrack = track;
|
||||
}
|
||||
|
||||
// clear everything if offTextTrackMenuItem was clicked
|
||||
} else if (userPref && !userPref.enabled) {
|
||||
preferredTrack = null;
|
||||
firstDesc = null;
|
||||
firstCaptions = null;
|
||||
|
||||
} else if (track.default) {
|
||||
if (track.kind === 'descriptions' && !firstDesc) {
|
||||
firstDesc = track;
|
||||
} else if (track.kind in modes && !firstCaptions) {
|
||||
firstCaptions = track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We want to show the first default track but captions and subtitles
|
||||
// take precedence over descriptions.
|
||||
// So, display the first default captions or subtitles track
|
||||
// and otherwise the first default descriptions track.
|
||||
if (firstCaptions) {
|
||||
firstCaptions.mode = 'showing';
|
||||
} else if (firstDesc) {
|
||||
firstDesc.mode = 'showing';
|
||||
}
|
||||
}));
|
||||
// The preferredTrack matches the user preference and takes
|
||||
// precendence over all the other tracks.
|
||||
// So, display the preferredTrack before the first default track
|
||||
// and the subtitles/captions track before the descriptions track
|
||||
if (preferredTrack) {
|
||||
preferredTrack.mode = 'showing';
|
||||
} else if (firstCaptions) {
|
||||
firstCaptions.mode = 'showing';
|
||||
} else if (firstDesc) {
|
||||
firstDesc.mode = 'showing';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,6 +61,14 @@ class TextTrackList extends TrackList {
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('change');
|
||||
}));
|
||||
|
||||
const nonLanguageTextTrackKind = ['metadata', 'chapters'];
|
||||
|
||||
if (nonLanguageTextTrackKind.indexOf(track.kind) === -1) {
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('selectedlanguagechange');
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
export default TextTrackList;
|
||||
|
@ -253,6 +253,7 @@ class TextTrack extends Track {
|
||||
* @type {EventTarget~Event}
|
||||
*/
|
||||
this.trigger('modechange');
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
322
test/unit/tracks/text-track-display.test.js
Normal file
322
test/unit/tracks/text-track-display.test.js
Normal file
@ -0,0 +1,322 @@
|
||||
/* eslint-env qunit */
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
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
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// 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();
|
||||
};
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
|
||||
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
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
|
||||
// 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
|
||||
const player = TestHelpers.makePlayer({techOrder: ['html5']});
|
||||
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
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// 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
|
||||
const captionTrack = player.addRemoteTextTrack(track1).track;
|
||||
const subsTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// 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
|
||||
player.addRemoteTextTrack(track1);
|
||||
player.addRemoteTextTrack(track2);
|
||||
|
||||
// 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';
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
const spanishTrack = player.addRemoteTextTrack(track2).track;
|
||||
|
||||
// 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');
|
||||
// we know the postition of the OffTextTrackMenuItem
|
||||
const offMenuItem = captionsButton.items[1];
|
||||
|
||||
player.src({type: 'video/mp4', src: 'http://google.com'});
|
||||
// manualCleanUp = true by default
|
||||
const englishTrack = player.addRemoteTextTrack(track1).track;
|
||||
// Keep track of menu items
|
||||
const enCaptionMenuItem = getMenuItemByLanguage(captionsButton.items, 'en');
|
||||
|
||||
// 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();
|
||||
});
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import TextTrackDisplay from '../../../src/js/tracks/text-track-display.js';
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
import Tech from '../../../src/js/tech/tech.js';
|
||||
import Component from '../../../src/js/component.js';
|
||||
|
||||
import * as browser from '../../../src/js/utils/browser.js';
|
||||
import TestHelpers from '../test-helpers.js';
|
||||
@ -221,54 +220,6 @@ QUnit.test('update texttrack buttons on removetrack or addtrack', function(asser
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
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('emulated tracks are always used, except in safari', function(assert) {
|
||||
const oldTestVid = Html5.TEST_VID;
|
||||
const oldIsAnySafari = browser.IS_ANY_SAFARI;
|
||||
|
Loading…
Reference in New Issue
Block a user