278 lines
7.7 KiB
JavaScript
278 lines
7.7 KiB
JavaScript
/**
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* 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.
|
|
*
|
|
* @fileoverview Mocks for testing cast components.
|
|
*/
|
|
|
|
goog.module('exoplayer.cast.test.mocks');
|
|
goog.setTestOnly();
|
|
|
|
const NetworkingEngine = goog.require('shaka.net.NetworkingEngine');
|
|
|
|
let mockState;
|
|
let manifest;
|
|
|
|
/**
|
|
* Initializes the state of the mocks. Needs to be called in the setUp method of
|
|
* the unit test.
|
|
*/
|
|
const setUp = function() {
|
|
mockState = {
|
|
outputMessages: {},
|
|
listeners: {},
|
|
loadedUri: null,
|
|
preferredTextLanguage: '',
|
|
preferredAudioLanguage: '',
|
|
configuration: null,
|
|
responseFilter: null,
|
|
isSilent: false,
|
|
customMessageListener: undefined,
|
|
mediaElementState: {
|
|
removedAttributes: [],
|
|
},
|
|
manifestState: {
|
|
isLive: false,
|
|
windowDuration: 20,
|
|
startTime: 0,
|
|
delay: 10,
|
|
},
|
|
getManifest: () => manifest,
|
|
setManifest: (m) => {
|
|
manifest = m;
|
|
},
|
|
shakaError: {
|
|
severity: /** CRITICAL */ 2,
|
|
code: /** not 7000 (LOAD_INTERUPTED) */ 3,
|
|
category: /** any */ 1,
|
|
},
|
|
simulateLoad: simulateLoadSuccess,
|
|
/** @type {function(boolean)} */
|
|
setShakaThrowsOnLoad: (doThrow) => {
|
|
mockState.simulateLoad = doThrow ? throwShakaError : simulateLoadSuccess;
|
|
},
|
|
simulateUnload: simulateUnloadSuccess,
|
|
/** @type {function(boolean)} */
|
|
setShakaThrowsOnUnload: (doThrow) => {
|
|
mockState.simulateUnload =
|
|
doThrow ? throwShakaError : simulateUnloadSuccess;
|
|
},
|
|
onSenderConnected: undefined,
|
|
onSenderDisconnected: undefined,
|
|
};
|
|
manifest = {
|
|
periods: [{startTime: mockState.manifestState.startTime}],
|
|
presentationTimeline: {
|
|
getDuration: () => mockState.manifestState.windowDuration,
|
|
isLive: () => mockState.manifestState.isLive,
|
|
getSegmentAvailabilityStart: () => 0,
|
|
getSegmentAvailabilityEnd: () => mockState.manifestState.windowDuration,
|
|
getSeekRangeStart: () => 0,
|
|
getSeekRangeEnd: () => mockState.manifestState.windowDuration -
|
|
mockState.manifestState.delay,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Simulates a successful `shakaPlayer.load` call.
|
|
*
|
|
* @param {string} uri The uri to load.
|
|
*/
|
|
const simulateLoadSuccess = (uri) => {
|
|
mockState.loadedUri = uri;
|
|
notifyListeners('streaming');
|
|
};
|
|
|
|
/** Simulates a successful `shakaPlayer.unload` call. */
|
|
const simulateUnloadSuccess = () => {
|
|
mockState.loadedUri = undefined;
|
|
notifyListeners('unloading');
|
|
};
|
|
|
|
/** @throws {!ShakaError} Thrown in any case. */
|
|
const throwShakaError = () => {
|
|
throw mockState.shakaError;
|
|
};
|
|
|
|
|
|
/**
|
|
* Adds a fake event listener.
|
|
*
|
|
* @param {string} type The type of the listener.
|
|
* @param {function(!Object)} listener The callback listener.
|
|
*/
|
|
const addEventListener = function(type, listener) {
|
|
mockState.listeners[type] = mockState.listeners[type] || [];
|
|
mockState.listeners[type].push(listener);
|
|
};
|
|
|
|
/**
|
|
* Notifies the fake listeners of the given type.
|
|
*
|
|
* @param {string} type The type of the listener to notify.
|
|
*/
|
|
const notifyListeners = function(type) {
|
|
if (mockState.isSilent || !mockState.listeners[type]) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < mockState.listeners[type].length; i++) {
|
|
mockState.listeners[type][i]({
|
|
type: type
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Creates an observable for which listeners can be added.
|
|
*
|
|
* @return {!Object} An observable object.
|
|
*/
|
|
const createObservable = () => {
|
|
return {
|
|
addEventListener: (type, listener) => {
|
|
addEventListener(type, listener);
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a fake for the shaka player.
|
|
*
|
|
* @return {!shaka.Player} A shaka player mock object.
|
|
*/
|
|
const createShakaFake = () => {
|
|
const shakaFake = /** @type {!shaka.Player} */(createObservable());
|
|
const mediaElement = createMediaElementFake();
|
|
/**
|
|
* @return {!HTMLMediaElement} A media element.
|
|
*/
|
|
shakaFake.getMediaElement = () => mediaElement;
|
|
shakaFake.getAudioLanguages = () => [];
|
|
shakaFake.getVariantTracks = () => [];
|
|
shakaFake.configure = (configuration) => {
|
|
mockState.configuration = configuration;
|
|
return true;
|
|
};
|
|
shakaFake.selectTextLanguage = (language) => {
|
|
mockState.preferredTextLanguage = language;
|
|
};
|
|
shakaFake.selectAudioLanguage = (language) => {
|
|
mockState.preferredAudioLanguage = language;
|
|
};
|
|
shakaFake.getManifest = () => manifest;
|
|
shakaFake.unload = async () => mockState.simulateUnload();
|
|
shakaFake.load = async (uri) => mockState.simulateLoad(uri);
|
|
shakaFake.getNetworkingEngine = () => {
|
|
return /** @type {!NetworkingEngine} */ ({
|
|
registerResponseFilter: (responseFilter) => {
|
|
mockState.responseFilter = responseFilter;
|
|
},
|
|
unregisterResponseFilter: (responseFilter) => {
|
|
if (mockState.responseFilter !== responseFilter) {
|
|
throw new Error('unregistering invalid response filter');
|
|
} else {
|
|
mockState.responseFilter = null;
|
|
}
|
|
},
|
|
});
|
|
};
|
|
return shakaFake;
|
|
};
|
|
|
|
/**
|
|
* Creates a fake for a media element.
|
|
*
|
|
* @return {!HTMLMediaElement} A media element fake.
|
|
*/
|
|
const createMediaElementFake = () => {
|
|
const mediaElementFake = /** @type {!HTMLMediaElement} */(createObservable());
|
|
mediaElementFake.load = () => {
|
|
// Do nothing.
|
|
};
|
|
mediaElementFake.play = () => {
|
|
mediaElementFake.paused = false;
|
|
notifyListeners('playing');
|
|
return Promise.resolve();
|
|
};
|
|
mediaElementFake.pause = () => {
|
|
mediaElementFake.paused = true;
|
|
notifyListeners('pause');
|
|
};
|
|
mediaElementFake.seekable = /** @type {!TimeRanges} */({
|
|
length: 1,
|
|
start: (index) => mockState.manifestState.startTime,
|
|
end: (index) => mockState.manifestState.windowDuration,
|
|
});
|
|
mediaElementFake.removeAttribute = (name) => {
|
|
mockState.mediaElementState.removedAttributes.push(name);
|
|
if (name === 'src') {
|
|
mockState.loadedUri = null;
|
|
}
|
|
};
|
|
mediaElementFake.hasAttribute = (name) => {
|
|
return name === 'src' && !!mockState.loadedUri;
|
|
};
|
|
mediaElementFake.buffered = /** @type {!TimeRanges} */ ({
|
|
length: 0,
|
|
start: (index) => null,
|
|
end: (index) => null,
|
|
});
|
|
mediaElementFake.paused = true;
|
|
return mediaElementFake;
|
|
};
|
|
|
|
/**
|
|
* Creates a cast receiver manager fake.
|
|
*
|
|
* @return {!Object} A cast receiver manager fake.
|
|
*/
|
|
const createCastReceiverContextFake = () => {
|
|
return {
|
|
addCustomMessageListener: (namespace, listener) => {
|
|
mockState.customMessageListener = listener;
|
|
},
|
|
sendCustomMessage: (namespace, senderId, message) => {
|
|
mockState.outputMessages[senderId] =
|
|
mockState.outputMessages[senderId] || [];
|
|
mockState.outputMessages[senderId].push(message);
|
|
},
|
|
addEventListener: (eventName, listener) => {
|
|
switch (eventName) {
|
|
case 'sender_connected':
|
|
mockState.onSenderConnected = listener;
|
|
break;
|
|
case 'sender_disconnected':
|
|
mockState.onSenderDisconnected = listener;
|
|
break;
|
|
}
|
|
},
|
|
getSenders: () => [{id: 'sender0'}],
|
|
start: () => {},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Returns the state of the mocks.
|
|
*
|
|
* @return {?Object}
|
|
*/
|
|
const state = () => mockState;
|
|
|
|
exports.createCastReceiverContextFake = createCastReceiverContextFake;
|
|
exports.createShakaFake = createShakaFake;
|
|
exports.notifyListeners = notifyListeners;
|
|
exports.setUp = setUp;
|
|
exports.state = state;
|