Adds back scrobbling and loading a track and the queue from localStorage.
- Splits loadTrackPosition into two functions : one for the track (which isn't finished), one for the queue. - Adds main-controller.js' first unit tests for both these functions. - Adds scrobbling functionnality. It is now a part of the Subsonic service, since we it's Subsonic that ultimately does the scroblling. - Adds unit tests for both the service and the directive. The test for updatetime was crazy hard to do because I had to find a way to trigger my own fake event and it wasn't permitted by jplayer. - Adds the load function to the player, it is used only when loading a song from localStorage. - Removes ng-click from play/pause in the player template. jPlayer adds its own handlers on them, no need to do it twice.
This commit is contained in:
parent
59762ae423
commit
834e67946c
10 changed files with 447 additions and 187 deletions
|
@ -443,27 +443,33 @@
|
||||||
return $sce.trustAsHtml(html);
|
return $sce.trustAsHtml(html);
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadTrackPosition() {
|
$scope.loadTrackPosition = function () {
|
||||||
//TODO: HYZ: Unit test
|
|
||||||
if (utils.browserStorageCheck()) {
|
if (utils.browserStorageCheck()) {
|
||||||
// Load Saved Song
|
// Load Saved Song
|
||||||
var song = angular.fromJson(localStorage.getItem('CurrentSong'));
|
var song = angular.fromJson(localStorage.getItem('CurrentSong'));
|
||||||
if (song) {
|
if (song) {
|
||||||
player.load(song);
|
player.load(song);
|
||||||
// Load Saved Queue
|
|
||||||
var items = angular.fromJson(localStorage.getItem('CurrentQueue'));
|
|
||||||
if (items) {
|
|
||||||
player.queue = items;
|
|
||||||
if (player.queue.length > 0) {
|
|
||||||
notifications.updateMessage(player.queue.length + ' Saved Song(s)', true);
|
|
||||||
}
|
|
||||||
if (globals.settings.Debug) { console.log('Play Queue Loaded From localStorage: ' + player.queue.length + ' song(s)'); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (globals.settings.Debug) { console.log('HTML5::loadStorage not supported on your browser'); }
|
if (globals.settings.Debug) { console.log('HTML5::loadStorage not supported on your browser'); }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
$scope.loadQueue = function () {
|
||||||
|
if(utils.browserStorageCheck()) {
|
||||||
|
// load Saved queue
|
||||||
|
var queue = angular.fromJson(localStorage.getItem('CurrentQueue'));
|
||||||
|
if (queue) {
|
||||||
|
player.queue = queue;
|
||||||
|
if (player.queue.length > 0) {
|
||||||
|
notifications.updateMessage(player.queue.length + ' Saved Song(s)', true);
|
||||||
|
}
|
||||||
|
if (globals.settings.Debug) { console.log('Play Queue Loaded From localStorage: ' + player.queue.length + ' song(s)'); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (globals.settings.Debug) { console.log('HTML5::loadStorage not supported on your browser'); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Launch on Startup */
|
/* Launch on Startup */
|
||||||
$scope.loadSettings();
|
$scope.loadSettings();
|
||||||
|
@ -476,7 +482,8 @@
|
||||||
if ($scope.loggedIn()) {
|
if ($scope.loggedIn()) {
|
||||||
//$scope.ping();
|
//$scope.ping();
|
||||||
if (globals.settings.SaveTrackPosition) {
|
if (globals.settings.SaveTrackPosition) {
|
||||||
loadTrackPosition();
|
$scope.loadQueue();
|
||||||
|
$scope.loadTrackPosition();
|
||||||
//FIXME: HYZ: player.startSaveTrackPosition();
|
//FIXME: HYZ: player.startSaveTrackPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,132 @@
|
||||||
describe("Main controller", function() {
|
describe("Main controller", function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe("updateFavorite -", function() {
|
var scope, $rootScope, utils, globals, model, notifications, player;
|
||||||
|
beforeEach(function() {
|
||||||
|
module('JamStash');
|
||||||
|
|
||||||
it("when starring a song, it notifies the user that the star was saved", function() {
|
inject(function ($controller, _$rootScope_, _$document_, _$window_, _$location_, _$cookieStore_, _utils_, _globals_, _model_, _notifications_, _player_) {
|
||||||
|
$rootScope = _$rootScope_;
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
utils = _utils_;
|
||||||
|
globals = _globals_;
|
||||||
|
model = _model_;
|
||||||
|
notifications = _notifications_;
|
||||||
|
player = _player_;
|
||||||
|
|
||||||
|
$controller('AppController', {
|
||||||
|
$scope: scope,
|
||||||
|
$rootScope: $rootScope,
|
||||||
|
$document: _$document_,
|
||||||
|
$window: _$window_,
|
||||||
|
$location: _$location_,
|
||||||
|
$cookieStore: _$cookieStore_,
|
||||||
|
utils: utils,
|
||||||
|
globals: globals,
|
||||||
|
model: model,
|
||||||
|
notifications: notifications,
|
||||||
|
player: player
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xdescribe("updateFavorite -", function() {
|
||||||
|
|
||||||
|
xit("when starring a song, it notifies the user that the star was saved", function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("when starring an album, it notifies the user that the star was saved", function() {
|
xit("when starring an album, it notifies the user that the star was saved", function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("when starring an artist, it notifies the user that the star was saved", function() {
|
xit("when starring an artist, it notifies the user that the star was saved", function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("given that the Subsonic server returns an error, when starring something, it notifies the user with the error message", function() {
|
xit("given that the Subsonic server returns an error, when starring something, it notifies the user with the error message", function() {
|
||||||
//TODO: move to higher level
|
//TODO: move to higher level
|
||||||
});
|
});
|
||||||
|
|
||||||
it("given that the Subsonic server is unreachable, when starring something, it notifies the user with the HTTP error code", function() {
|
xit("given that the Subsonic server is unreachable, when starring something, it notifies the user with the HTTP error code", function() {
|
||||||
//TODO: move to higher level
|
//TODO: move to higher level
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("toggleSetting -", function() {
|
xdescribe("toggleSetting -", function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("load from localStorage -", function() {
|
||||||
|
var fakeStorage;
|
||||||
|
beforeEach(function() {
|
||||||
|
fakeStorage = {};
|
||||||
|
|
||||||
|
spyOn(localStorage, "getItem").and.callFake(function(key) {
|
||||||
|
return fakeStorage[key];
|
||||||
|
});
|
||||||
|
spyOn(utils, "browserStorageCheck").and.returnValue(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("loadTrackPosition -", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(player, "load");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given that we previously saved the current track's position in local Storage, it loads the song we saved into the player", function() {
|
||||||
|
var song = {
|
||||||
|
id: 8626,
|
||||||
|
name: 'Pectinatodenticulate',
|
||||||
|
artist: 'Isiah Hosfield',
|
||||||
|
album: 'Tammanyize'
|
||||||
|
};
|
||||||
|
fakeStorage = {
|
||||||
|
'CurrentSong': song
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.loadTrackPosition();
|
||||||
|
|
||||||
|
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentSong');
|
||||||
|
expect(player.load).toHaveBeenCalledWith(song);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given that we didn't save anything in local Storage, it doesn't load anything", function() {
|
||||||
|
scope.loadTrackPosition();
|
||||||
|
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentSong');
|
||||||
|
expect(player.load).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("loadQueue -", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(notifications, "updateMessage");
|
||||||
|
player.queue = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given that we previously saved the playing queue in local Storage, it fills the player's queue with what we saved and notifies the user", function() {
|
||||||
|
var queue = [
|
||||||
|
{ id: 8705 },
|
||||||
|
{ id: 1617 },
|
||||||
|
{ id: 9812 }
|
||||||
|
];
|
||||||
|
fakeStorage = {
|
||||||
|
'CurrentQueue': queue
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.loadQueue();
|
||||||
|
|
||||||
|
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentQueue');
|
||||||
|
expect(player.queue).toEqual(queue);
|
||||||
|
expect(notifications.updateMessage).toHaveBeenCalledWith('3 Saved Song(s)', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given that we didn't save anything in local Storage, it doesn't load anything", function() {
|
||||||
|
scope.loadQueue();
|
||||||
|
|
||||||
|
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentQueue');
|
||||||
|
expect(player.queue).toEqual([]);
|
||||||
|
expect(notifications.updateMessage).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstash.settings'])
|
/**
|
||||||
|
* jamstash.player.directive module
|
||||||
|
*
|
||||||
|
* Encapsulates the jPlayer plugin. It watches the player service for the song to play, load or restart.
|
||||||
|
* It also enables jPlayer to attach event handlers to our UI through css Selectors.
|
||||||
|
*/
|
||||||
|
angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstash.settings', 'jamstash.subsonic.service'])
|
||||||
|
|
||||||
.directive('jplayer', ['player', 'globals', function(playerService, globals) {
|
.directive('jplayer', ['player', 'globals', 'subsonic', function(playerService, globals, subsonic) {
|
||||||
'use strict';
|
'use strict';
|
||||||
return {
|
return {
|
||||||
restrict: 'EA',
|
restrict: 'EA',
|
||||||
template: '<div></div>',
|
template: '<div></div>',
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element) {
|
||||||
|
|
||||||
var $player = element.children('div');
|
var $player = element.children('div');
|
||||||
console.log($player);
|
|
||||||
var audioSolution = 'html,flash';
|
var audioSolution = 'html,flash';
|
||||||
if (globals.settings.ForceFlash) {
|
if (globals.settings.ForceFlash) {
|
||||||
audioSolution = 'flash,html';
|
audioSolution = 'flash,html';
|
||||||
|
@ -17,7 +22,7 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
||||||
var updatePlayer = function() {
|
var updatePlayer = function() {
|
||||||
$player.jPlayer({
|
$player.jPlayer({
|
||||||
// Flash fallback for outdated browser not supporting HTML5 audio/video tags
|
// Flash fallback for outdated browser not supporting HTML5 audio/video tags
|
||||||
// http://jplayer.org/download/
|
// TODO: Hyz: Replace in Grunt !
|
||||||
swfPath: 'bower_components/jplayer/dist/jplayer/jquery.jplayer.swf',
|
swfPath: 'bower_components/jplayer/dist/jplayer/jquery.jplayer.swf',
|
||||||
wmode: 'window',
|
wmode: 'window',
|
||||||
solution: audioSolution,
|
solution: audioSolution,
|
||||||
|
@ -37,8 +42,8 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
||||||
},
|
},
|
||||||
play: function() {
|
play: function() {
|
||||||
console.log('jplayer play');
|
console.log('jplayer play');
|
||||||
$('#playermiddle').css('visibility', 'visible');
|
scope.revealControls();
|
||||||
$('#songdetails').css('visibility', 'visible');
|
scope.scrobbled = false;
|
||||||
},
|
},
|
||||||
pause: function() {
|
pause: function() {
|
||||||
console.log('jplayer pause');
|
console.log('jplayer pause');
|
||||||
|
@ -47,18 +52,37 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
||||||
console.log('jplayer ended');
|
console.log('jplayer ended');
|
||||||
playerService.nextTrack();
|
playerService.nextTrack();
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
|
},
|
||||||
|
timeupdate: function (event) {
|
||||||
|
// Scrobble song once percentage is reached
|
||||||
|
var p = event.jPlayer.status.currentPercentAbsolute;
|
||||||
|
if (!scope.scrobbled && p > 30) {
|
||||||
|
if (globals.settings.Debug) { console.log('LAST.FM SCROBBLE - Percent Played: ' + p); }
|
||||||
|
subsonic.scrobble(scope.currentSong);
|
||||||
|
scope.scrobbled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
updatePlayer();
|
updatePlayer();
|
||||||
|
|
||||||
|
scope.currentSong = {};
|
||||||
|
scope.scrobbled = false;
|
||||||
|
|
||||||
scope.$watch(function () {
|
scope.$watch(function () {
|
||||||
return playerService.getPlayingSong();
|
return playerService.getPlayingSong();
|
||||||
}, function (newVal) {
|
}, function (newVal) {
|
||||||
console.log('playingSong changed !');
|
console.log('playingSong changed !');
|
||||||
$player.jPlayer('setMedia', {'mp3': newVal.url})
|
scope.currentSong = newVal;
|
||||||
.jPlayer('play');
|
$player.jPlayer('setMedia', {'mp3': newVal.url});
|
||||||
|
if(playerService.loadSong === true) {
|
||||||
|
// Do not play, only load
|
||||||
|
playerService.loadSong = false;
|
||||||
|
scope.revealControls();
|
||||||
|
} else {
|
||||||
|
$player.jPlayer('play');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.$watch(function () {
|
scope.$watch(function () {
|
||||||
|
@ -70,6 +94,12 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
||||||
playerService.restartSong = false;
|
playerService.restartSong = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
scope.revealControls = function () {
|
||||||
|
$('#playermiddle').css('visibility', 'visible');
|
||||||
|
$('#songdetails').css('visibility', 'visible');
|
||||||
|
};
|
||||||
|
|
||||||
} //end link
|
} //end link
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
describe("jplayer directive", function() {
|
describe("jplayer directive", function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var element, scope, playerService, globalsService, $player, playingSong;
|
var element, scope, playerService, globals, subsonic, $player, playingSong;
|
||||||
|
|
||||||
function mockGetPlayingSong() {
|
|
||||||
return playingSong;
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
playingSong = {};
|
playingSong = {};
|
||||||
module('jamstash.player.directive', function($provide) {
|
module('jamstash.player.directive', function($provide) {
|
||||||
// Mock the player service
|
// Mock the player service
|
||||||
$provide.decorator('player', function($delegate) {
|
$provide.decorator('player', function($delegate) {
|
||||||
$delegate.getPlayingSong = jasmine.createSpy('getPlayingSong').and.callFake(mockGetPlayingSong);
|
$delegate.getPlayingSong = jasmine.createSpy('getPlayingSong').and.callFake(function() {
|
||||||
|
return playingSong;
|
||||||
|
});
|
||||||
$delegate.nextTrack = jasmine.createSpy('nextTrack');
|
$delegate.nextTrack = jasmine.createSpy('nextTrack');
|
||||||
|
|
||||||
return $delegate;
|
return $delegate;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
inject(function($rootScope, $compile, _player_, _globals_) {
|
inject(function($rootScope, $compile, _player_, _globals_, _subsonic_) {
|
||||||
playerService = _player_;
|
playerService = _player_;
|
||||||
globalsService = _globals_;
|
globals = _globals_;
|
||||||
|
subsonic = _subsonic_;
|
||||||
// Compile the directive
|
// Compile the directive
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
element = '<div id="playdeck_1" jplayer></div>';
|
element = '<div id="playdeck_1" jplayer></div>';
|
||||||
|
@ -31,14 +30,38 @@ describe("jplayer directive", function() {
|
||||||
$player = element.children('div');
|
$player = element.children('div');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("When the player service's current playing song changes, it sets jplayer's media and plays the song", function() {
|
describe("When the player service's current song changes,", function() {
|
||||||
spyOn($.fn, "jPlayer").and.returnValue($.fn);
|
|
||||||
|
|
||||||
playingSong = {url: 'https://gantry.com/antemarital/vigorless?a=oropharyngeal&b=killcrop#eviscerate'};
|
beforeEach(function() {
|
||||||
scope.$apply();
|
spyOn($.fn, "jPlayer").and.returnValue($.fn);
|
||||||
|
playingSong = {url: 'https://gantry.com/antemarital/vigorless?a=oropharyngeal&b=killcrop#eviscerate'};
|
||||||
|
});
|
||||||
|
|
||||||
expect($player.jPlayer).toHaveBeenCalledWith('setMedia', {'mp3': 'https://gantry.com/antemarital/vigorless?a=oropharyngeal&b=killcrop#eviscerate'});
|
it("it sets jPlayer's media and stores the song for future scrobbling", function() {
|
||||||
expect($player.jPlayer).toHaveBeenCalledWith('play');
|
scope.$apply();
|
||||||
|
|
||||||
|
expect($player.jPlayer).toHaveBeenCalledWith('setMedia', {'mp3': 'https://gantry.com/antemarital/vigorless?a=oropharyngeal&b=killcrop#eviscerate'});
|
||||||
|
expect(scope.currentSong).toEqual(playingSong);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("if the player service's loadSong flag is true, it does not play the song and it displays the player controls", function() {
|
||||||
|
spyOn(scope, "revealControls");
|
||||||
|
|
||||||
|
playerService.loadSong = true;
|
||||||
|
scope.$apply();
|
||||||
|
|
||||||
|
expect($player.jPlayer).not.toHaveBeenCalledWith('play');
|
||||||
|
expect(playerService.loadSong).toBeFalsy();
|
||||||
|
expect(scope.revealControls).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("otherwise, it plays it", function() {
|
||||||
|
playerService.loadSong = false;
|
||||||
|
scope.$apply();
|
||||||
|
|
||||||
|
expect($player.jPlayer).toHaveBeenCalledWith('play');
|
||||||
|
expect(playerService.loadSong).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("When the player service's restartSong flag is true, it restarts the current song and resets the flag to false", function() {
|
it("When the player service's restartSong flag is true, it restarts the current song and resets the flag to false", function() {
|
||||||
|
@ -51,7 +74,7 @@ describe("jplayer directive", function() {
|
||||||
expect(playerService.restartSong).toBeFalsy();
|
expect(playerService.restartSong).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("When jplayer has finished the current song, it plays the next track using the", function() {
|
it("When jplayer has finished the current song, it asks the player service for the next track", function() {
|
||||||
var e = $.jPlayer.event.ended;
|
var e = $.jPlayer.event.ended;
|
||||||
$player.trigger(e);
|
$player.trigger(e);
|
||||||
|
|
||||||
|
@ -59,12 +82,67 @@ describe("jplayer directive", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("When jPlayer starts to play the current song, it displays the player controls", function() {
|
it("When jPlayer starts to play the current song, it displays the player controls", function() {
|
||||||
affix('#playermiddle').css('visibility', 'hidden');
|
spyOn(scope, "revealControls");
|
||||||
affix('#songdetails').css('visibility', 'hidden');
|
|
||||||
var e = $.jPlayer.event.play;
|
var e = $.jPlayer.event.play;
|
||||||
$player.trigger(e);
|
$player.trigger(e);
|
||||||
|
|
||||||
|
expect(scope.revealControls).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("When jPlayer starts to play the current song, it resets the scrobbled flag to false", function() {
|
||||||
|
scope.scrobbled = true;
|
||||||
|
|
||||||
|
var e = $.jPlayer.event.play;
|
||||||
|
$player.trigger(e);
|
||||||
|
|
||||||
|
expect(scope.scrobbled).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("revealControls - it displays the song details and the player controls", function() {
|
||||||
|
affix('#playermiddle').css('visibility', 'hidden');
|
||||||
|
affix('#songdetails').css('visibility', 'hidden');
|
||||||
|
|
||||||
|
scope.revealControls();
|
||||||
|
|
||||||
expect($('#playermiddle').css('visibility')).toEqual('visible');
|
expect($('#playermiddle').css('visibility')).toEqual('visible');
|
||||||
expect($('#songdetails').css('visibility')).toEqual('visible');
|
expect($('#songdetails').css('visibility')).toEqual('visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Scrobbling -", function() {
|
||||||
|
var fakejPlayer, timeUpdate;
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(subsonic, "scrobble");
|
||||||
|
scope.currentSong = {
|
||||||
|
id: 5375
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fake jPlayer's internal _trigger event because I can't trigger a manual timeupdate
|
||||||
|
fakejPlayer = {
|
||||||
|
element: $player,
|
||||||
|
status: { currentPercentAbsolute: 31 }
|
||||||
|
};
|
||||||
|
timeUpdate = $.jPlayer.event.timeupdate;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given a song that hasn't been scrobbled yet, When jPlayer reaches 30 percent of it, it scrobbles to last.fm using the subsonic service and sets the flag to true", function() {
|
||||||
|
scope.scrobbled = false;
|
||||||
|
|
||||||
|
// Trigger our fake timeupdate
|
||||||
|
$.jPlayer.prototype._trigger.call(fakejPlayer, timeUpdate);
|
||||||
|
|
||||||
|
expect(subsonic.scrobble).toHaveBeenCalledWith(scope.currentSong);
|
||||||
|
expect(scope.scrobbled).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given a song that has already been scrobbled, when jPlayer reaches 30 percent of it, it does not scrobble again and leaves the flag to true", function() {
|
||||||
|
scope.scrobbled = true;
|
||||||
|
|
||||||
|
// Trigger our fake timeupdate
|
||||||
|
$.jPlayer.prototype._trigger.call(fakejPlayer, timeUpdate);
|
||||||
|
|
||||||
|
expect(subsonic.scrobble).not.toHaveBeenCalled();
|
||||||
|
expect(scope.scrobbled).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* jamstash.player.service Module
|
* jamstash.player.service Module
|
||||||
*
|
*
|
||||||
* Enables app-wide control of the behavior of the player directive.
|
* Manages the player and playing queue. Use it to play a song, go to next track or add songs to the queue.
|
||||||
*/
|
*/
|
||||||
angular.module('jamstash.player.service', ['jamstash.settings', 'angular-underscore/utils'])
|
angular.module('jamstash.player.service', ['jamstash.settings', 'angular-underscore/utils'])
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
||||||
playingIndex: -1,
|
playingIndex: -1,
|
||||||
playingSong: {},
|
playingSong: {},
|
||||||
restartSong: false,
|
restartSong: false,
|
||||||
|
loadSong: false,
|
||||||
|
|
||||||
play: function(song) {
|
play: function(song) {
|
||||||
console.log('player service - play()', song);
|
|
||||||
var songIndexInQueue;
|
var songIndexInQueue;
|
||||||
// Find the song's index in the queue, if it's in there
|
// Find the song's index in the queue, if it's in there
|
||||||
songIndexInQueue = player.queue.indexOf(song);
|
songIndexInQueue = player.queue.indexOf(song);
|
||||||
|
@ -31,22 +31,20 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
||||||
},
|
},
|
||||||
|
|
||||||
playFirstSong: function() {
|
playFirstSong: function() {
|
||||||
console.log('player service - playFirstSong()');
|
|
||||||
player.playingIndex = 0;
|
player.playingIndex = 0;
|
||||||
player.play(player.queue[0]);
|
player.play(player.queue[0]);
|
||||||
},
|
},
|
||||||
|
|
||||||
load: function(song) {
|
load: function(song) {
|
||||||
console.log('player service - load()');
|
player.loadSong = true;
|
||||||
|
player.play(song);
|
||||||
},
|
},
|
||||||
|
|
||||||
restart: function() {
|
restart: function() {
|
||||||
console.log('player service - restart()');
|
|
||||||
player.restartSong = true;
|
player.restartSong = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
nextTrack: function() {
|
nextTrack: function() {
|
||||||
console.log('player service - nextTrack()');
|
|
||||||
if((player.playingIndex + 1) < player.queue.length) {
|
if((player.playingIndex + 1) < player.queue.length) {
|
||||||
var nextTrack = player.queue[player.playingIndex + 1];
|
var nextTrack = player.queue[player.playingIndex + 1];
|
||||||
player.playingIndex++;
|
player.playingIndex++;
|
||||||
|
@ -55,7 +53,6 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
||||||
},
|
},
|
||||||
|
|
||||||
previousTrack: function() {
|
previousTrack: function() {
|
||||||
console.log(('player service - previousTrack()'));
|
|
||||||
if((player.playingIndex - 1) > 0) {
|
if((player.playingIndex - 1) > 0) {
|
||||||
var previousTrack = player.queue[player.playingIndex - 1];
|
var previousTrack = player.queue[player.playingIndex - 1];
|
||||||
player.playingIndex--;
|
player.playingIndex--;
|
||||||
|
@ -66,22 +63,18 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
||||||
},
|
},
|
||||||
|
|
||||||
emptyQueue: function() {
|
emptyQueue: function() {
|
||||||
console.log('player service - emptyQueue()');
|
|
||||||
player.queue = [];
|
player.queue = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
shuffleQueue: function() {
|
shuffleQueue: function() {
|
||||||
console.log('player service - shuffleQueue()');
|
|
||||||
player.queue = _.shuffle(player.queue);
|
player.queue = _.shuffle(player.queue);
|
||||||
},
|
},
|
||||||
|
|
||||||
addSong: function(song) {
|
addSong: function(song) {
|
||||||
console.log('player service - addSong()');
|
|
||||||
player.queue.push(song);
|
player.queue.push(song);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeSong: function(song) {
|
removeSong: function(song) {
|
||||||
console.log('player service - removeSong()');
|
|
||||||
var index = player.queue.indexOf(song);
|
var index = player.queue.indexOf(song);
|
||||||
player.queue.splice(index, 1);
|
player.queue.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
|
@ -180,9 +180,18 @@ describe("Player service -", function() {
|
||||||
player.restart();
|
player.restart();
|
||||||
expect(player.restartSong).toBeTruthy();
|
expect(player.restartSong).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("When I load the song, the flag for the directive is set", function() {
|
||||||
|
spyOn(player, "play");
|
||||||
|
|
||||||
|
player.load(song);
|
||||||
|
|
||||||
|
expect(player.loadSong).toBeTruthy();
|
||||||
|
expect(player.play).toHaveBeenCalledWith(song);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Given that there is no song in my playing queue", function() {
|
describe("Given that my playing queue is empty", function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
player.queue = [];
|
player.queue = [];
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
<a class="hover" id="PreviousTrack" title="Previous Track" ng-click="player.previousTrack()">
|
<a class="hover" id="PreviousTrack" title="Previous Track" ng-click="player.previousTrack()">
|
||||||
<img src="images/first_alt_24x24.png" height="24" width="24" alt="Previous track" />
|
<img src="images/first_alt_24x24.png" height="24" width="24" alt="Previous track" />
|
||||||
</a>
|
</a>
|
||||||
<a class="hover PlayTrack" title="Play/Pause" ng-click="player.play()">
|
<a class="hover PlayTrack" title="Play/Pause">
|
||||||
<img src="images/play_alt_24x24.png" height="24" width="24" alt="Play" />
|
<img src="images/play_alt_24x24.png" height="24" width="24" alt="Play" />
|
||||||
</a>
|
</a>
|
||||||
<a class="hover PauseTrack" title="Play/Pause" ng-click="player.pause()" style="display: none;">
|
<a class="hover PauseTrack" title="Play/Pause" style="display: none;">
|
||||||
<img src="images/pause_alt_24x24.png" height="24" width="24" alt="Pause" />
|
<img src="images/pause_alt_24x24.png" height="24" width="24" alt="Pause" />
|
||||||
</a>
|
</a>
|
||||||
<a class="hover" id="NextTrack" title="Next Track" ng-click="player.nextTrack()">
|
<a class="hover" id="NextTrack" title="Next Track" ng-click="player.nextTrack()">
|
||||||
|
|
|
@ -8,7 +8,6 @@ angular.module('jamstash.queue.controller', ['jamstash.player.service'])
|
||||||
$scope.itemType = 'pl'; // TODO: Hyz: What is this ?
|
$scope.itemType = 'pl'; // TODO: Hyz: What is this ?
|
||||||
|
|
||||||
$scope.playSong = function (song) {
|
$scope.playSong = function (song) {
|
||||||
console.log('Queue Controller - playSong()', song);
|
|
||||||
player.play(song);
|
player.play(song);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -793,7 +793,35 @@ angular.module('jamstash.subsonic.service', ['jamstash.settings', 'jamstash.util
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
},
|
||||||
|
scrobble: function (song) {
|
||||||
|
var id = song.id;
|
||||||
|
//TODO: Hyz: Refactor all this boilerplate into an http interceptor ? or something higher level than this
|
||||||
|
var exception = {reason: 'Error when contacting the Subsonic server.'};
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var httpPromise;
|
||||||
|
if (globals.settings.Debug) { console.log('Scrobble Song: ' + id); }
|
||||||
|
if(globals.settings.Protocol === 'jsonp') {
|
||||||
|
httpPromise = $http.jsonp(globals.BaseURL() + '/scrobble.view?callback=JSON_CALLBACK&' + globals.BaseParams() + '&id=' + id + '&submission=true',
|
||||||
|
{
|
||||||
|
timeout: globals.settings.Timeout
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
httpPromise = $http.get(globals.BaseURL() + '/scrobble.view?' + globals.BaseParams() + '&id=' + id + '&submission=true',
|
||||||
|
{
|
||||||
|
timeout: globals.settings.Timeout
|
||||||
|
});
|
||||||
|
}
|
||||||
|
httpPromise.success(function (data, status) {
|
||||||
|
console.log(data);
|
||||||
|
if(globals.settings.Debug) { console.log('Successfully scrobbled song: ' + id); }
|
||||||
|
}).error(function(data, status) {
|
||||||
|
exception.httpError = status;
|
||||||
|
deferred.reject(exception);
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// End subsonic
|
// End subsonic
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -1,160 +1,174 @@
|
||||||
describe("Subsonic service -", function() {
|
describe("Subsonic service -", function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var subsonic, mockBackend, mockGlobals, response;
|
var subsonic, mockBackend, mockGlobals, response;
|
||||||
|
beforeEach(function() {
|
||||||
|
// We redefine it because in some tests we need to alter the settings
|
||||||
|
mockGlobals = {
|
||||||
|
settings: {
|
||||||
|
AutoPlaylistSize: 3,
|
||||||
|
Protocol: 'jsonp'
|
||||||
|
},
|
||||||
|
BaseURL: function () {
|
||||||
|
return 'http://demo.subsonic.com/rest';
|
||||||
|
},
|
||||||
|
BaseParams: function () {
|
||||||
|
return 'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var url = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
module('jamstash.subsonic.service', function ($provide) {
|
||||||
'callback=JSON_CALLBACK&u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
$provide.value('globals', mockGlobals);
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
inject(function (_subsonic_, $httpBackend) {
|
||||||
// We redefine it because in some tests we need to alter the settings
|
subsonic = _subsonic_;
|
||||||
mockGlobals = {
|
mockBackend = $httpBackend;
|
||||||
settings: {
|
});
|
||||||
AutoPlaylistSize: 3,
|
response = {"subsonic-response": {status: "ok", version: "1.10.2"}};
|
||||||
Protocol: 'jsonp'
|
});
|
||||||
},
|
|
||||||
BaseURL: function () {
|
|
||||||
return 'http://demo.subsonic.com/rest';
|
|
||||||
},
|
|
||||||
BaseParams: function () {
|
|
||||||
return 'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module('jamstash.subsonic.service', function ($provide) {
|
afterEach(function() {
|
||||||
$provide.value('globals', mockGlobals);
|
mockBackend.verifyNoOutstandingExpectation();
|
||||||
});
|
mockBackend.verifyNoOutstandingRequest();
|
||||||
|
});
|
||||||
|
|
||||||
inject(function (_subsonic_, $httpBackend) {
|
it("scrobble - Given a song, when I scrobble it, it returns true if there was no error", function() {
|
||||||
subsonic = _subsonic_;
|
var song = { id: 45872 };
|
||||||
mockBackend = $httpBackend;
|
var url = 'http://demo.subsonic.com/rest/scrobble.view?' +
|
||||||
});
|
'callback=JSON_CALLBACK&u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp&id=45872&submission=true';
|
||||||
response = {"subsonic-response": {status: "ok", version: "1.10.2"}};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function() {
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
mockBackend.verifyNoOutstandingExpectation();
|
|
||||||
mockBackend.verifyNoOutstandingRequest();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("getStarred -", function() {
|
var promise = subsonic.scrobble(song);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
it("Given that I have 2 starred albums, 1 starred artist and 3 starred songs in my library, when getting everything starred, it returns them all", function() {
|
expect(promise).toBeResolved();
|
||||||
response["subsonic-response"].starred = {artist: [{id: 2245}], album: [{id: 1799},{id: 20987}], song: [{id: 2478},{id: 14726},{id: 742}]};
|
});
|
||||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getStarred();
|
describe("getStarred -", function() {
|
||||||
mockBackend.flush();
|
var url = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
||||||
|
'callback=JSON_CALLBACK&u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
||||||
|
|
||||||
expect(promise).toBeResolvedWith({artist: [
|
it("Given that I have 2 starred albums, 1 starred artist and 3 starred songs in my library, when getting everything starred, it returns them all", function() {
|
||||||
{id: 2245}
|
response["subsonic-response"].starred = {artist: [{id: 2245}], album: [{id: 1799},{id: 20987}], song: [{id: 2478},{id: 14726},{id: 742}]};
|
||||||
], album: [
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
{id: 1799},{id: 20987}
|
|
||||||
], song: [
|
|
||||||
{id: 2478},{id: 14726},{id: 742}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Given that the global protocol setting is 'json' and given that I have 3 starred songs in my library, when getting everything starred, it uses GET and returns 3 starred songs", function() {
|
var promise = subsonic.getStarred();
|
||||||
mockGlobals.settings.Protocol = 'json';
|
mockBackend.flush();
|
||||||
mockGlobals.BaseParams = function() { return 'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=json'; };
|
|
||||||
var getUrl = 'http://demo.subsonic.com/rest/getStarred.view?' +
|
|
||||||
'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=json';
|
|
||||||
response["subsonic-response"].starred = {song: [
|
|
||||||
{id: "2147"},{id:"9847"},{id:"214"}
|
|
||||||
]};
|
|
||||||
mockBackend.expectGET(getUrl).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getStarred();
|
expect(promise).toBeResolvedWith({artist: [
|
||||||
mockBackend.flush();
|
{id: 2245}
|
||||||
|
], album: [
|
||||||
|
{id: 1799},{id: 20987}
|
||||||
|
], song: [
|
||||||
|
{id: 2478},{id: 14726},{id: 742}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
expect(promise).toBeResolvedWith({song: [
|
it("Given that the global protocol setting is 'json' and given that I have 3 starred songs in my library, when getting everything starred, it uses GET and returns 3 starred songs", function() {
|
||||||
{id: "2147"},{id:"9847"},{id:"214"}]
|
mockGlobals.settings.Protocol = 'json';
|
||||||
});
|
mockGlobals.BaseParams = function() { return 'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=json'; };
|
||||||
});
|
var getUrl = 'http://demo.subsonic.com/rest/getStarred.view?' +
|
||||||
|
'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=json';
|
||||||
|
response["subsonic-response"].starred = {song: [
|
||||||
|
{id: "2147"},{id:"9847"},{id:"214"}
|
||||||
|
]};
|
||||||
|
mockBackend.expectGET(getUrl).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
it("Given that there is absolutely nothing starred in my library, when getting everything starred, it returns an error object with a message", function() {
|
var promise = subsonic.getStarred();
|
||||||
response["subsonic-response"].starred = {};
|
mockBackend.flush();
|
||||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getStarred();
|
expect(promise).toBeResolvedWith({song: [
|
||||||
mockBackend.flush();
|
{id: "2147"},{id:"9847"},{id:"214"}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
expect(promise).toBeRejectedWith({reason: 'Nothing is starred on the Subsonic server.'});
|
it("Given that there is absolutely nothing starred in my library, when getting everything starred, it returns an error object with a message", function() {
|
||||||
});
|
response["subsonic-response"].starred = {};
|
||||||
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
it("Given that the Subsonic server is not responding, when getting everything starred, it returns an error object with a message", function() {
|
var promise = subsonic.getStarred();
|
||||||
mockBackend.whenJSONP(url).respond(503, 'Service Unavailable');
|
mockBackend.flush();
|
||||||
|
|
||||||
var promise = subsonic.getStarred();
|
expect(promise).toBeRejectedWith({reason: 'Nothing is starred on the Subsonic server.'});
|
||||||
mockBackend.flush();
|
});
|
||||||
|
// TODO: Hyz: Those tests should be at a higher level, we are repeating them for everything...
|
||||||
|
it("Given that the Subsonic server is not responding, when getting everything starred, it returns an error object with a message", function() {
|
||||||
|
mockBackend.whenJSONP(url).respond(503, 'Service Unavailable');
|
||||||
|
|
||||||
expect(promise).toBeRejectedWith({reason: 'Error when contacting the Subsonic server.', httpError: 503});
|
var promise = subsonic.getStarred();
|
||||||
});
|
mockBackend.flush();
|
||||||
|
|
||||||
it("Given a missing parameter, when getting the starred songs, it returns an error object with a message", function() {
|
expect(promise).toBeRejectedWith({reason: 'Error when contacting the Subsonic server.', httpError: 503});
|
||||||
mockGlobals.BaseParams = function() { return 'u=Hyzual&v=1.10.2&c=Jamstash&f=jsonp';};
|
});
|
||||||
var missingPasswordUrl = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
|
||||||
'callback=JSON_CALLBACK&u=Hyzual&v=1.10.2&c=Jamstash&f=jsonp';
|
|
||||||
var errorResponse = {"subsonic-response" : {
|
|
||||||
"status" : "failed",
|
|
||||||
"version" : "1.10.2",
|
|
||||||
"error" : {"code" : 10,"message" : "Required parameter is missing."}
|
|
||||||
}};
|
|
||||||
mockBackend.whenJSONP(missingPasswordUrl).respond(200, errorResponse);
|
|
||||||
|
|
||||||
var promise = subsonic.getStarred();
|
it("Given a missing parameter, when getting the starred songs, it returns an error object with a message", function() {
|
||||||
mockBackend.flush();
|
mockGlobals.BaseParams = function() { return 'u=Hyzual&v=1.10.2&c=Jamstash&f=jsonp';};
|
||||||
|
var missingPasswordUrl = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
||||||
|
'callback=JSON_CALLBACK&u=Hyzual&v=1.10.2&c=Jamstash&f=jsonp';
|
||||||
|
var errorResponse = {"subsonic-response" : {
|
||||||
|
"status" : "failed",
|
||||||
|
"version" : "1.10.2",
|
||||||
|
"error" : {"code" : 10,"message" : "Required parameter is missing."}
|
||||||
|
}};
|
||||||
|
mockBackend.whenJSONP(missingPasswordUrl).respond(200, errorResponse);
|
||||||
|
|
||||||
expect(promise).toBeRejectedWith({reason: 'Error when contacting the Subsonic server.', subsonicError: {code: 10, message:'Required parameter is missing.'}});
|
var promise = subsonic.getStarred();
|
||||||
});
|
mockBackend.flush();
|
||||||
}); //end getStarred
|
|
||||||
|
|
||||||
describe("getRandomStarredSongs -", function() {
|
expect(promise).toBeRejectedWith({reason: 'Error when contacting the Subsonic server.', subsonicError: {code: 10, message:'Required parameter is missing.'}});
|
||||||
describe("Given that the global setting AutoPlaylist Size is 3", function() {
|
});
|
||||||
|
}); //end getStarred
|
||||||
|
|
||||||
it("and given that I have more than 3 starred songs in my library, when getting random starred songs, the result should be limited to 3 starred songs", function() {
|
describe("getRandomStarredSongs -", function() {
|
||||||
var library = [
|
var url = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
||||||
{id: "11841"},{id: "12061"},{id: "17322"},{id: "1547"},{id: "14785"}
|
'callback=JSON_CALLBACK&u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
||||||
];
|
|
||||||
response["subsonic-response"].starred = {song: library};
|
|
||||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getRandomStarredSongs();
|
describe("Given that the global setting AutoPlaylist Size is 3", function() {
|
||||||
// We create a spy in order to get the results of the promise
|
|
||||||
var success = jasmine.createSpy("success");
|
|
||||||
promise.then(success);
|
|
||||||
|
|
||||||
mockBackend.flush();
|
it("and given that I have more than 3 starred songs in my library, when getting random starred songs, the result should be limited to 3 starred songs", function() {
|
||||||
|
var library = [
|
||||||
|
{id: "11841"},{id: "12061"},{id: "17322"},{id: "1547"},{id: "14785"}
|
||||||
|
];
|
||||||
|
response["subsonic-response"].starred = {song: library};
|
||||||
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
expect(promise).toBeResolved();
|
var promise = subsonic.getRandomStarredSongs();
|
||||||
expect(success).toHaveBeenCalled();
|
// We create a spy in order to get the results of the promise
|
||||||
var randomlyPickedSongs = success.calls.mostRecent().args[0];
|
var success = jasmine.createSpy("success");
|
||||||
for (var i = 0; i < randomlyPickedSongs.length; i++) {
|
promise.then(success);
|
||||||
expect(library).toContain(randomlyPickedSongs[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("and given that I have only 1 starred song in my library, when getting random starred songs, it returns my starred song", function() {
|
mockBackend.flush();
|
||||||
response["subsonic-response"].starred = {song: [{id: "11841"}]};
|
|
||||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getRandomStarredSongs();
|
expect(promise).toBeResolved();
|
||||||
mockBackend.flush();
|
expect(success).toHaveBeenCalled();
|
||||||
|
var randomlyPickedSongs = success.calls.mostRecent().args[0];
|
||||||
|
for (var i = 0; i < randomlyPickedSongs.length; i++) {
|
||||||
|
expect(library).toContain(randomlyPickedSongs[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
expect(promise).toBeResolvedWith([{id: "11841"}]);
|
it("and given that I have only 1 starred song in my library, when getting random starred songs, it returns my starred song", function() {
|
||||||
});
|
response["subsonic-response"].starred = {song: [{id: "11841"}]};
|
||||||
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
it("and given that I don't have any starred song in my library, when getting random starred songs, it returns an error object with a message", function() {
|
var promise = subsonic.getRandomStarredSongs();
|
||||||
response["subsonic-response"].starred = {song: []};
|
mockBackend.flush();
|
||||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
|
||||||
|
|
||||||
var promise = subsonic.getRandomStarredSongs();
|
expect(promise).toBeResolvedWith([{id: "11841"}]);
|
||||||
mockBackend.flush();
|
});
|
||||||
|
|
||||||
expect(promise).toBeRejectedWith({reason: 'No starred songs found on the Subsonic server.'});
|
it("and given that I don't have any starred song in my library, when getting random starred songs, it returns an error object with a message", function() {
|
||||||
});
|
response["subsonic-response"].starred = {song: []};
|
||||||
});
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
});
|
|
||||||
|
var promise = subsonic.getRandomStarredSongs();
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(promise).toBeRejectedWith({reason: 'No starred songs found on the Subsonic server.'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
Loading…
Add table
Add a link
Reference in a new issue