forked from openlp/openlp
parent
c8b328c4f5
commit
47261d206b
@ -235,119 +235,6 @@ function _createStyle(selector, rules) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An audio player with a play list
|
||||
*/
|
||||
var AudioPlayer = function (audioElement) {
|
||||
this._audioElement = null;
|
||||
this._eventListeners = {};
|
||||
this._playlist = [];
|
||||
this._currentTrack = null;
|
||||
this._canRepeat = false;
|
||||
this._state = AudioState.Stopped;
|
||||
this.createAudioElement();
|
||||
};
|
||||
|
||||
/**
|
||||
* Call all listeners associated with this event
|
||||
* @private
|
||||
* @param {object} event - The event that was emitted
|
||||
*/
|
||||
AudioPlayer.prototype._callListener = function (event) {
|
||||
if (this._eventListeners.hasOwnProperty(event.type)) {
|
||||
this._eventListeners[event.type].forEach(function (listener) {
|
||||
listener(event);
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.warn("Received unknown event \"" + event.type + "\", doing nothing.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the <audio> element that is used to play the audio
|
||||
*/
|
||||
AudioPlayer.prototype.createAudioElement = function () {
|
||||
this._audioElement = document.createElement("audio");
|
||||
this._audioElement.addEventListener("ended", this.onEnded);
|
||||
this._audioElement.addEventListener("ended", this._callListener);
|
||||
this._audioElement.addEventListener("timeupdate", this._callListener);
|
||||
this._audioElement.addEventListener("volumechange", this._callListener);
|
||||
this._audioElement.addEventListener("durationchange", this._callListener);
|
||||
this._audioElement.addEventListener("loadeddata", this._callListener);
|
||||
document.addEventListener("complete", function(event) {
|
||||
document.body.appendChild(this._audioElement);
|
||||
});
|
||||
};
|
||||
AudioPlayer.prototype.addEventListener = function (eventType, listener) {
|
||||
this._eventListeners[eventType] = this._eventListeners[eventType] || [];
|
||||
this._eventListeners[eventType].push(listener);
|
||||
};
|
||||
AudioPlayer.prototype.onEnded = function (event) {
|
||||
this.nextTrack();
|
||||
};
|
||||
AudioPlayer.prototype.setCanRepeat = function (canRepeat) {
|
||||
this._canRepeat = canRepeat;
|
||||
};
|
||||
AudioPlayer.prototype.clearTracks = function () {
|
||||
this._playlist = [];
|
||||
};
|
||||
AudioPlayer.prototype.addTrack = function (track) {
|
||||
this._playlist.push(track);
|
||||
};
|
||||
AudioPlayer.prototype.nextTrack = function () {
|
||||
if (!!this._currentTrack) {
|
||||
var trackIndex = this._playlist.indexOf(this._currentTrack);
|
||||
if ((trackIndex + 1 >= this._playlist.length) && this._canRepeat) {
|
||||
this.play(this._playlist[0]);
|
||||
}
|
||||
else if (trackIndex + 1 < this._playlist.length) {
|
||||
this.play(this._playlist[trackIndex + 1]);
|
||||
}
|
||||
else {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
else if (this._playlist.length > 0) {
|
||||
this.play(this._playlist[0]);
|
||||
}
|
||||
else {
|
||||
console.warn("No tracks in playlist, doing nothing.");
|
||||
}
|
||||
};
|
||||
AudioPlayer.prototype.play = function () {
|
||||
if (arguments.length > 0) {
|
||||
this._currentTrack = arguments[0];
|
||||
this._audioElement.src = this._currentTrack;
|
||||
this._audioElement.play();
|
||||
this._state = AudioState.Playing;
|
||||
}
|
||||
else if (this._state == AudioState.Paused) {
|
||||
this._audioElement.play();
|
||||
this._state = AudioState.Playing;
|
||||
}
|
||||
else {
|
||||
console.warn("No track currently paused and no track specified, doing nothing.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Pause
|
||||
*/
|
||||
AudioPlayer.prototype.pause = function () {
|
||||
this._audioElement.pause();
|
||||
this._state = AudioState.Paused;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop playing
|
||||
*/
|
||||
AudioPlayer.prototype.stop = function () {
|
||||
this._audioElement.pause();
|
||||
this._audioElement.src = "";
|
||||
this._state = AudioState.Stopped;
|
||||
};
|
||||
|
||||
/**
|
||||
* The Display object is what we use from OpenLP
|
||||
*/
|
||||
@ -392,9 +279,9 @@ var Display = {
|
||||
init: function (options) {
|
||||
// Set defaults for undefined values
|
||||
options = options || {};
|
||||
var isDisplay = options.isDisplay || false;
|
||||
var doItemTransitions = options.doItemTransitions || false;
|
||||
var hideMouse = options.hideMouse || false;
|
||||
let isDisplay = options.isDisplay || false;
|
||||
let doItemTransitions = options.doItemTransitions || false;
|
||||
let hideMouse = options.hideMouse || false;
|
||||
// Now continue to initialisation
|
||||
if (!isDisplay) {
|
||||
document.body.classList.add('checkerboard');
|
||||
@ -1248,9 +1135,26 @@ var Display = {
|
||||
*/
|
||||
setScale: function(scale) {
|
||||
document.body.style.zoom = scale+"%";
|
||||
},
|
||||
/**
|
||||
* In order to check if a font exists, we need a container to do
|
||||
* calculations on. This method creates that container and caches
|
||||
* some width values so that we don't have to do this step every
|
||||
* time we check if a font exists.
|
||||
*/
|
||||
_prepareFontContainer: function() {
|
||||
Display._fontContainer = document.createElement("span");
|
||||
Display._fontContainer.id = "does-font-exist";
|
||||
Display._fontContainer.innerHTML = Array(100).join("wi");
|
||||
Display._fontContainer.style.cssText = [
|
||||
"position: absolute",
|
||||
"width: auto",
|
||||
"font-size: 128px",
|
||||
"left: -999999px"
|
||||
].join(" !important;");
|
||||
document.body.appendChild(Display._fontContainer);
|
||||
}
|
||||
};
|
||||
new QWebChannel(qt.webChannelTransport, function (channel) {
|
||||
window.mediaWatcher = channel.objects.mediaWatcher;
|
||||
window.displayWatcher = channel.objects.displayWatcher;
|
||||
});
|
||||
|
@ -49,6 +49,7 @@ class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
|
||||
"""
|
||||
# The JS log has the entire file location, which we don't really care about
|
||||
app_dir = AppLocation.get_directory(AppLocation.AppDir).parent
|
||||
if str(app_dir) in source_id:
|
||||
source_id = source_id.replace('file://{app_dir}/'.format(app_dir=app_dir), '')
|
||||
# Log the JS messages to the Python logger
|
||||
log.log(LOG_LEVELS[level], '{source_id}:{line_number} {message}'.format(source_id=source_id,
|
||||
|
@ -25,9 +25,11 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import copy
|
||||
import re
|
||||
|
||||
from PyQt5 import QtCore, QtWebChannel, QtWidgets
|
||||
|
||||
from openlp.core.common import is_win
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
from openlp.core.common.enum import ServiceItemType
|
||||
from openlp.core.common.i18n import translate
|
||||
@ -39,70 +41,10 @@ from openlp.core.display.screens import ScreenList
|
||||
from openlp.core.ui import HideMode
|
||||
|
||||
|
||||
FONT_FOUNDRY = re.compile(r'(.*?) \[(.*?)\]')
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaWatcher(QtCore.QObject):
|
||||
"""
|
||||
A class to watch media events in the display and emit signals for OpenLP
|
||||
"""
|
||||
progress = QtCore.pyqtSignal(float)
|
||||
duration = QtCore.pyqtSignal(float)
|
||||
volume = QtCore.pyqtSignal(float)
|
||||
playback_rate = QtCore.pyqtSignal(float)
|
||||
ended = QtCore.pyqtSignal(bool)
|
||||
muted = QtCore.pyqtSignal(bool)
|
||||
|
||||
@QtCore.pyqtSlot(float)
|
||||
def update_progress(self, time):
|
||||
"""
|
||||
Notify about the current position of the media
|
||||
"""
|
||||
log.warning(time)
|
||||
self.progress.emit(time)
|
||||
|
||||
@QtCore.pyqtSlot(float)
|
||||
def update_duration(self, time):
|
||||
"""
|
||||
Notify about the duration of the media
|
||||
"""
|
||||
log.warning(time)
|
||||
self.duration.emit(time)
|
||||
|
||||
@QtCore.pyqtSlot(float)
|
||||
def update_volume(self, level):
|
||||
"""
|
||||
Notify about the volume of the media
|
||||
"""
|
||||
log.warning(level)
|
||||
level = level * 100
|
||||
self.volume.emit(level)
|
||||
|
||||
@QtCore.pyqtSlot(float)
|
||||
def update_playback_rate(self, rate):
|
||||
"""
|
||||
Notify about the playback rate of the media
|
||||
"""
|
||||
log.warning(rate)
|
||||
self.playback_rate.emit(rate)
|
||||
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def has_ended(self, is_ended):
|
||||
"""
|
||||
Notify that the media has ended playing
|
||||
"""
|
||||
log.warning(is_ended)
|
||||
self.ended.emit(is_ended)
|
||||
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def has_muted(self, is_muted):
|
||||
"""
|
||||
Notify that the media has been muted
|
||||
"""
|
||||
log.warning(is_muted)
|
||||
self.muted.emit(is_muted)
|
||||
|
||||
|
||||
class DisplayWatcher(QtCore.QObject):
|
||||
"""
|
||||
This facilitates communication from the Display object in the browser back to the Python
|
||||
@ -153,14 +95,12 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||
self.display_path = display_base_path / 'display.html'
|
||||
self.checkerboard_path = display_base_path / 'checkerboard.png'
|
||||
self.openlp_splash_screen_path = display_base_path / 'openlp-splash-screen.png'
|
||||
self.set_url(QtCore.QUrl.fromLocalFile(path_to_str(self.display_path)))
|
||||
self.channel = QtWebChannel.QWebChannel(self)
|
||||
self.media_watcher = MediaWatcher(self)
|
||||
self.channel.registerObject('mediaWatcher', self.media_watcher)
|
||||
self.display_watcher = DisplayWatcher(self)
|
||||
self.channel.registerObject('displayWatcher', self.display_watcher)
|
||||
self.webview.page().setWebChannel(self.channel)
|
||||
self.display_watcher.initialised.connect(self.on_initialised)
|
||||
self.set_url(QtCore.QUrl.fromLocalFile(path_to_str(self.display_path)))
|
||||
self.is_display = False
|
||||
self.scale = 1
|
||||
self.hide_mode = None
|
||||
@ -175,6 +115,19 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||
if len(ScreenList()) > 1 or self.settings.value('core/display on monitor'):
|
||||
self.show()
|
||||
|
||||
def _fix_font_name(self, font_name):
|
||||
"""
|
||||
Do some font machinations to see if we can fix the font name
|
||||
"""
|
||||
# Some fonts on Windows that end in "Bold" are made into a base font that is bold
|
||||
if is_win() and font_name.endswith(' Bold'):
|
||||
font_name = font_name.split(' Bold')[0]
|
||||
# Some fonts may have the Foundry name in their name. Remove the foundry name
|
||||
match = FONT_FOUNDRY.match(font_name)
|
||||
if match:
|
||||
font_name = match.group(1)
|
||||
return font_name
|
||||
|
||||
def deregister_display(self):
|
||||
"""
|
||||
De-register this displays callbacks in the registry to be able to remove it
|
||||
@ -424,6 +377,9 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||
theme_copy.background_end_color = '#590909'
|
||||
theme_copy.background_main_color = '#090909'
|
||||
theme_copy.background_footer_color = '#090909'
|
||||
# Do some font-checking, see https://gitlab.com/openlp/openlp/-/issues/39
|
||||
theme_copy.font_main_name = self._fix_font_name(theme.font_main_name)
|
||||
theme_copy.font_footer_name = self._fix_font_name(theme.font_footer_name)
|
||||
exported_theme = theme_copy.export_theme(is_js=True)
|
||||
self.run_javascript('Display.setTheme({theme});'.format(theme=exported_theme), is_sync=is_sync)
|
||||
|
||||
|
@ -199,9 +199,12 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
||||
|
||||
:rtype: None
|
||||
"""
|
||||
xml_file_paths = [p for p in AppLocation.get_section_data_path('themes').glob('*/*.xml')]
|
||||
# Exit early if there are no themes to upgrade
|
||||
if not xml_file_paths:
|
||||
return
|
||||
# Wait for 2 seconds to allow some other things to start processing first
|
||||
wait_for(lambda: False, timeout=1)
|
||||
xml_file_paths = AppLocation.get_section_data_path('themes').glob('*/*.xml')
|
||||
for xml_file_path in xml_file_paths:
|
||||
theme_data = get_text_file_string(xml_file_path)
|
||||
theme = self._create_theme_from_xml(theme_data, self.theme_path)
|
||||
|
@ -32,7 +32,7 @@ from PyQt5 import QtCore
|
||||
# Mock QtWebEngineWidgets
|
||||
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
|
||||
|
||||
from openlp.core.display.window import DisplayWindow
|
||||
from openlp.core.display.window import DisplayWindow, DisplayWatcher
|
||||
from openlp.core.common.enum import ServiceItemType
|
||||
from openlp.core.lib.theme import Theme
|
||||
from openlp.core.ui import HideMode
|
||||
@ -220,6 +220,69 @@ def test_run_javascript_sync_no_wait(mock_time, mocked_webengine, mocked_addWidg
|
||||
mock_time.sleep.assert_not_called()
|
||||
|
||||
|
||||
@patch('openlp.core.display.window.QtWidgets.QVBoxLayout')
|
||||
@patch('openlp.core.display.webengine.WebEngineView')
|
||||
@patch('openlp.core.display.window.is_win')
|
||||
def test_fix_font_bold_windows(mocked_is_win, mocked_webengine, mocked_layout, mock_settings):
|
||||
"""
|
||||
Test that on Windows, fonts that end with "Bold" are handled
|
||||
"""
|
||||
# GIVEN: A display window and a font name
|
||||
mocked_is_win.return_value = True
|
||||
display_window = DisplayWindow()
|
||||
display_window.is_display = True
|
||||
display_window.run_javascript = MagicMock()
|
||||
font_name = 'Arial Rounded MT Bold'
|
||||
|
||||
# WHEN: The font is processed
|
||||
result = display_window._fix_font_name(font_name)
|
||||
|
||||
# Then the font name should be fixed
|
||||
assert result == 'Arial Rounded MT'
|
||||
|
||||
|
||||
@patch('openlp.core.display.window.QtWidgets.QVBoxLayout')
|
||||
@patch('openlp.core.display.webengine.WebEngineView')
|
||||
@patch('openlp.core.display.window.is_win')
|
||||
def test_fix_font_bold_not_windows(mocked_is_win, mocked_webengine, mocked_layout, mock_settings):
|
||||
"""
|
||||
Test that on NOT Windows, fonts that end with "Bold" are ignored
|
||||
"""
|
||||
# GIVEN: A display window and a font name
|
||||
mocked_is_win.return_value = False
|
||||
display_window = DisplayWindow()
|
||||
display_window.is_display = True
|
||||
display_window.run_javascript = MagicMock()
|
||||
font_name = 'Arial Rounded MT Bold'
|
||||
|
||||
# WHEN: The font is processed
|
||||
result = display_window._fix_font_name(font_name)
|
||||
|
||||
# Then the font name should be fixed
|
||||
assert result == 'Arial Rounded MT Bold'
|
||||
|
||||
|
||||
@patch('openlp.core.display.window.QtWidgets.QVBoxLayout')
|
||||
@patch('openlp.core.display.webengine.WebEngineView')
|
||||
@patch('openlp.core.display.window.is_win')
|
||||
def test_fix_font_foundry(mocked_is_win, mocked_webengine, mocked_layout, mock_settings):
|
||||
"""
|
||||
Test that a font with a foundry name in it has the foundry removed
|
||||
"""
|
||||
# GIVEN: A display window and a font name
|
||||
mocked_is_win.return_value = False
|
||||
display_window = DisplayWindow()
|
||||
display_window.is_display = True
|
||||
display_window.run_javascript = MagicMock()
|
||||
font_name = 'CMG Sans [Foundry]'
|
||||
|
||||
# WHEN: The font is processed
|
||||
result = display_window._fix_font_name(font_name)
|
||||
|
||||
# Then the font name should be fixed
|
||||
assert result == 'CMG Sans'
|
||||
|
||||
|
||||
@patch('openlp.core.display.window.QtWidgets.QVBoxLayout')
|
||||
@patch('openlp.core.display.webengine.WebEngineView')
|
||||
def test_set_theme_is_display_video(mocked_webengine, mocked_addWidget, mock_settings, mock_geometry):
|
||||
@ -463,3 +526,18 @@ def test_hide_display_no_display(mocked_screenlist, mocked_webengine, mocked_add
|
||||
|
||||
# THEN: Hide mode should still be none
|
||||
assert display_window.hide_mode is None
|
||||
|
||||
|
||||
def test_display_watcher_set_initialised():
|
||||
"""
|
||||
Test that the initialised signal is emitted
|
||||
"""
|
||||
# GIVEN: A DisplayWatcher instance
|
||||
display_watcher = DisplayWatcher(None)
|
||||
|
||||
# WHEN: setInitialised is called
|
||||
with patch.object(display_watcher, 'initialised') as mocked_initialised:
|
||||
display_watcher.setInitialised(True)
|
||||
|
||||
# THEN: initialised should have been emitted
|
||||
mocked_initialised.emit.assert_called_once_with(True)
|
||||
|
@ -960,191 +960,3 @@ describe("Display.toggleVideoMute", function () {
|
||||
expect(mockVideo.muted).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("AudioPlayer", function () {
|
||||
var audioPlayer, audioElement;
|
||||
|
||||
beforeEach(function () {
|
||||
audioElement = {
|
||||
_eventListeners: {},
|
||||
_playing: false,
|
||||
_paused: false,
|
||||
_stopped: false,
|
||||
src: "",
|
||||
addEventListener: function (eventType, listener) {
|
||||
this._eventListeners[eventType] = this._eventListeners[eventType] || [];
|
||||
this._eventListeners[eventType].push(listener);
|
||||
},
|
||||
play: function () {
|
||||
this._playing = true;
|
||||
this._paused = false;
|
||||
this._stopped = false;
|
||||
},
|
||||
pause: function () {
|
||||
this._playing = false;
|
||||
this._paused = true;
|
||||
this._stopped = false;
|
||||
}
|
||||
};
|
||||
spyOn(document, "createElement").and.returnValue(audioElement);
|
||||
audioPlayer = new AudioPlayer();
|
||||
});
|
||||
|
||||
it("should create an object", function () {
|
||||
expect(audioPlayer).toBeDefined();
|
||||
expect(audioPlayer._audioElement).not.toBeNull();
|
||||
expect(audioPlayer._eventListeners).toEqual({});
|
||||
expect(audioPlayer._playlist).toEqual([]);
|
||||
expect(audioPlayer._currentTrack).toEqual(null);
|
||||
expect(audioPlayer._canRepeat).toEqual(false);
|
||||
expect(audioPlayer._state).toEqual(AudioState.Stopped);
|
||||
});
|
||||
|
||||
it("should call the correct method when _callListener is called", function () {
|
||||
var testCalled = false;
|
||||
function test(event) {
|
||||
testCalled = true;
|
||||
}
|
||||
audioPlayer._eventListeners["test"] = [test];
|
||||
audioPlayer._callListener({"type": "test"});
|
||||
expect(testCalled).toEqual(true);
|
||||
});
|
||||
|
||||
it("should log a warning when _callListener is called for an unknown event", function () {
|
||||
spyOn(console, "warn");
|
||||
audioPlayer._callListener({"type": "test"});
|
||||
expect(console.warn).toHaveBeenCalledWith("Received unknown event \"test\", doing nothing.");
|
||||
});
|
||||
|
||||
it("should add all the correct event listeners", function () {
|
||||
expectedListeners = {
|
||||
"ended": [audioPlayer.onEnded, audioPlayer._callListener],
|
||||
"timeupdate": [audioPlayer._callListener],
|
||||
"volumechange": [audioPlayer._callListener],
|
||||
"durationchange": [audioPlayer._callListener],
|
||||
"loadeddata": [audioPlayer._callListener]
|
||||
};
|
||||
expect(audioElement._eventListeners).toEqual(expectedListeners);
|
||||
});
|
||||
|
||||
it("should add the correct event listener when calling addEventListener", function () {
|
||||
function dummy () {};
|
||||
var expectedListeners = {
|
||||
"test": [dummy]
|
||||
};
|
||||
audioPlayer.addEventListener("test", dummy);
|
||||
expect(audioPlayer._eventListeners).toEqual(expectedListeners);
|
||||
});
|
||||
|
||||
it("should set call nextTrack when the onEnded listener is called", function () {
|
||||
spyOn(audioPlayer, "nextTrack");
|
||||
audioPlayer.onEnded({});
|
||||
expect(audioPlayer.nextTrack).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should set the _canRepeat property when calling setCanRepeat", function () {
|
||||
audioPlayer.setCanRepeat(true);
|
||||
expect(audioPlayer._canRepeat).toEqual(true);
|
||||
});
|
||||
|
||||
it("should clear the playlist when clearTracks is called", function () {
|
||||
audioPlayer._playlist = ["one", "two", "three"];
|
||||
audioPlayer.clearTracks();
|
||||
expect(audioPlayer._playlist).toEqual([]);
|
||||
});
|
||||
|
||||
it("should add a track to the playlist when addTrack is called", function () {
|
||||
audioPlayer._playlist = [];
|
||||
audioPlayer.addTrack("one");
|
||||
expect(audioPlayer._playlist).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("should move to the first track when canRepeat is true and nextTrack is called", function () {
|
||||
spyOn(audioPlayer, "play");
|
||||
audioPlayer.addTrack("one");
|
||||
audioPlayer.addTrack("two");
|
||||
audioPlayer.setCanRepeat(true);
|
||||
audioPlayer._currentTrack = "two";
|
||||
|
||||
audioPlayer.nextTrack();
|
||||
|
||||
expect(audioPlayer.play).toHaveBeenCalledWith("one");
|
||||
});
|
||||
|
||||
it("should move to the next track when nextTrack is called", function () {
|
||||
spyOn(audioPlayer, "play");
|
||||
audioPlayer.addTrack("one");
|
||||
audioPlayer.addTrack("two");
|
||||
audioPlayer._currentTrack = "one";
|
||||
|
||||
audioPlayer.nextTrack();
|
||||
|
||||
expect(audioPlayer.play).toHaveBeenCalledWith("two");
|
||||
});
|
||||
|
||||
it("should stop when canRepeat is false and nextTrack is called on the last track in the list", function () {
|
||||
spyOn(audioPlayer, "play");
|
||||
spyOn(audioPlayer, "stop");
|
||||
audioPlayer.addTrack("one");
|
||||
audioPlayer.addTrack("two");
|
||||
audioPlayer.setCanRepeat(false);
|
||||
audioPlayer._currentTrack = "two";
|
||||
|
||||
audioPlayer.nextTrack();
|
||||
|
||||
expect(audioPlayer.play).not.toHaveBeenCalled();
|
||||
expect(audioPlayer.stop).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should play the first track when nextTrack is called when no songs are playing", function () {
|
||||
spyOn(audioPlayer, "play");
|
||||
audioPlayer.addTrack("one");
|
||||
audioPlayer.nextTrack();
|
||||
expect(audioPlayer.play).toHaveBeenCalledWith("one");
|
||||
});
|
||||
|
||||
it("should log a warning when nextTrack is called when no songs are in the playlist", function () {
|
||||
spyOn(console, "warn");
|
||||
audioPlayer.nextTrack();
|
||||
expect(console.warn).toHaveBeenCalledWith("No tracks in playlist, doing nothing.");
|
||||
});
|
||||
|
||||
it("should play the track specified when play is called with a filename", function () {
|
||||
audioPlayer.addTrack("one");
|
||||
audioPlayer.play("one");
|
||||
|
||||
expect(audioPlayer._currentTrack).toEqual("one");
|
||||
expect(audioElement._playing).toEqual(true);
|
||||
expect(audioElement.src).toEqual("one");
|
||||
expect(audioPlayer._state).toEqual(AudioState.Playing);
|
||||
});
|
||||
|
||||
it("should continue playing when play is called without a filename and the player is paused", function () {
|
||||
audioPlayer._state = AudioState.Paused;
|
||||
audioPlayer.play();
|
||||
|
||||
expect(audioElement._playing).toEqual(true);
|
||||
expect(audioPlayer._state).toEqual(AudioState.Playing);
|
||||
});
|
||||
|
||||
it("should do nothing when play is called without a filename and the player is not paused", function () {
|
||||
spyOn(console, "warn");
|
||||
audioPlayer._state = AudioState.Playing;
|
||||
audioPlayer.play();
|
||||
|
||||
expect(console.warn).toHaveBeenCalledWith("No track currently paused and no track specified, doing nothing.");
|
||||
});
|
||||
|
||||
it("should pause the current track when pause is called", function () {
|
||||
audioPlayer.pause();
|
||||
expect(audioPlayer._state).toEqual(AudioState.Paused);
|
||||
expect(audioElement._paused).toEqual(true);
|
||||
});
|
||||
|
||||
it("should stop the current track when stop is called", function () {
|
||||
audioPlayer.stop();
|
||||
expect(audioPlayer._state).toEqual(AudioState.Stopped);
|
||||
expect(audioElement._paused).toEqual(true);
|
||||
expect(audioElement.src).toEqual("");
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user