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);
|
||||
};
|
||||
|
||||
function loadTrackPosition() {
|
||||
//TODO: HYZ: Unit test
|
||||
$scope.loadTrackPosition = function () {
|
||||
if (utils.browserStorageCheck()) {
|
||||
// Load Saved Song
|
||||
var song = angular.fromJson(localStorage.getItem('CurrentSong'));
|
||||
if (song) {
|
||||
player.load(song);
|
||||
// Load Saved Queue
|
||||
var items = angular.fromJson(localStorage.getItem('CurrentQueue'));
|
||||
if (items) {
|
||||
player.queue = items;
|
||||
}
|
||||
} else {
|
||||
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 */
|
||||
$scope.loadSettings();
|
||||
|
@ -476,7 +482,8 @@
|
|||
if ($scope.loggedIn()) {
|
||||
//$scope.ping();
|
||||
if (globals.settings.SaveTrackPosition) {
|
||||
loadTrackPosition();
|
||||
$scope.loadQueue();
|
||||
$scope.loadTrackPosition();
|
||||
//FIXME: HYZ: player.startSaveTrackPosition();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,132 @@
|
|||
describe("Main controller", function() {
|
||||
'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
|
||||
});
|
||||
|
||||
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
|
||||
});
|
||||
});
|
||||
|
||||
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';
|
||||
return {
|
||||
restrict: 'EA',
|
||||
template: '<div></div>',
|
||||
link: function(scope, element, attrs) {
|
||||
link: function(scope, element) {
|
||||
|
||||
var $player = element.children('div');
|
||||
console.log($player);
|
||||
var audioSolution = 'html,flash';
|
||||
if (globals.settings.ForceFlash) {
|
||||
audioSolution = 'flash,html';
|
||||
|
@ -17,7 +22,7 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
var updatePlayer = function() {
|
||||
$player.jPlayer({
|
||||
// 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',
|
||||
wmode: 'window',
|
||||
solution: audioSolution,
|
||||
|
@ -37,8 +42,8 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
},
|
||||
play: function() {
|
||||
console.log('jplayer play');
|
||||
$('#playermiddle').css('visibility', 'visible');
|
||||
$('#songdetails').css('visibility', 'visible');
|
||||
scope.revealControls();
|
||||
scope.scrobbled = false;
|
||||
},
|
||||
pause: function() {
|
||||
console.log('jplayer pause');
|
||||
|
@ -47,18 +52,37 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
console.log('jplayer ended');
|
||||
playerService.nextTrack();
|
||||
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();
|
||||
|
||||
scope.currentSong = {};
|
||||
scope.scrobbled = false;
|
||||
|
||||
scope.$watch(function () {
|
||||
return playerService.getPlayingSong();
|
||||
}, function (newVal) {
|
||||
console.log('playingSong changed !');
|
||||
$player.jPlayer('setMedia', {'mp3': newVal.url})
|
||||
.jPlayer('play');
|
||||
scope.currentSong = newVal;
|
||||
$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 () {
|
||||
|
@ -70,6 +94,12 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
playerService.restartSong = false;
|
||||
}
|
||||
});
|
||||
|
||||
scope.revealControls = function () {
|
||||
$('#playermiddle').css('visibility', 'visible');
|
||||
$('#songdetails').css('visibility', 'visible');
|
||||
};
|
||||
|
||||
} //end link
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
describe("jplayer directive", function() {
|
||||
'use strict';
|
||||
|
||||
var element, scope, playerService, globalsService, $player, playingSong;
|
||||
|
||||
function mockGetPlayingSong() {
|
||||
return playingSong;
|
||||
}
|
||||
var element, scope, playerService, globals, subsonic, $player, playingSong;
|
||||
|
||||
beforeEach(function() {
|
||||
playingSong = {};
|
||||
module('jamstash.player.directive', function($provide) {
|
||||
// Mock the player service
|
||||
$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');
|
||||
|
||||
return $delegate;
|
||||
});
|
||||
});
|
||||
|
||||
inject(function($rootScope, $compile, _player_, _globals_) {
|
||||
inject(function($rootScope, $compile, _player_, _globals_, _subsonic_) {
|
||||
playerService = _player_;
|
||||
globalsService = _globals_;
|
||||
globals = _globals_;
|
||||
subsonic = _subsonic_;
|
||||
// Compile the directive
|
||||
scope = $rootScope.$new();
|
||||
element = '<div id="playdeck_1" jplayer></div>';
|
||||
|
@ -31,14 +30,38 @@ describe("jplayer directive", function() {
|
|||
$player = element.children('div');
|
||||
});
|
||||
|
||||
it("When the player service's current playing song changes, it sets jplayer's media and plays the song", function() {
|
||||
spyOn($.fn, "jPlayer").and.returnValue($.fn);
|
||||
describe("When the player service's current song changes,", function() {
|
||||
|
||||
beforeEach(function() {
|
||||
spyOn($.fn, "jPlayer").and.returnValue($.fn);
|
||||
playingSong = {url: 'https://gantry.com/antemarital/vigorless?a=oropharyngeal&b=killcrop#eviscerate'};
|
||||
});
|
||||
|
||||
it("it sets jPlayer's media and stores the song for future scrobbling", function() {
|
||||
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() {
|
||||
|
@ -51,7 +74,7 @@ describe("jplayer directive", function() {
|
|||
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;
|
||||
$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() {
|
||||
affix('#playermiddle').css('visibility', 'hidden');
|
||||
affix('#songdetails').css('visibility', 'hidden');
|
||||
spyOn(scope, "revealControls");
|
||||
|
||||
var e = $.jPlayer.event.play;
|
||||
$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($('#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
|
||||
*
|
||||
* 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'])
|
||||
|
||||
|
@ -13,9 +13,9 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
|||
playingIndex: -1,
|
||||
playingSong: {},
|
||||
restartSong: false,
|
||||
loadSong: false,
|
||||
|
||||
play: function(song) {
|
||||
console.log('player service - play()', song);
|
||||
var songIndexInQueue;
|
||||
// Find the song's index in the queue, if it's in there
|
||||
songIndexInQueue = player.queue.indexOf(song);
|
||||
|
@ -31,22 +31,20 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
|||
},
|
||||
|
||||
playFirstSong: function() {
|
||||
console.log('player service - playFirstSong()');
|
||||
player.playingIndex = 0;
|
||||
player.play(player.queue[0]);
|
||||
},
|
||||
|
||||
load: function(song) {
|
||||
console.log('player service - load()');
|
||||
player.loadSong = true;
|
||||
player.play(song);
|
||||
},
|
||||
|
||||
restart: function() {
|
||||
console.log('player service - restart()');
|
||||
player.restartSong = true;
|
||||
},
|
||||
|
||||
nextTrack: function() {
|
||||
console.log('player service - nextTrack()');
|
||||
if((player.playingIndex + 1) < player.queue.length) {
|
||||
var nextTrack = player.queue[player.playingIndex + 1];
|
||||
player.playingIndex++;
|
||||
|
@ -55,7 +53,6 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
|||
},
|
||||
|
||||
previousTrack: function() {
|
||||
console.log(('player service - previousTrack()'));
|
||||
if((player.playingIndex - 1) > 0) {
|
||||
var previousTrack = player.queue[player.playingIndex - 1];
|
||||
player.playingIndex--;
|
||||
|
@ -66,22 +63,18 @@ angular.module('jamstash.player.service', ['jamstash.settings', 'angular-undersc
|
|||
},
|
||||
|
||||
emptyQueue: function() {
|
||||
console.log('player service - emptyQueue()');
|
||||
player.queue = [];
|
||||
},
|
||||
|
||||
shuffleQueue: function() {
|
||||
console.log('player service - shuffleQueue()');
|
||||
player.queue = _.shuffle(player.queue);
|
||||
},
|
||||
|
||||
addSong: function(song) {
|
||||
console.log('player service - addSong()');
|
||||
player.queue.push(song);
|
||||
},
|
||||
|
||||
removeSong: function(song) {
|
||||
console.log('player service - removeSong()');
|
||||
var index = player.queue.indexOf(song);
|
||||
player.queue.splice(index, 1);
|
||||
},
|
||||
|
|
|
@ -180,9 +180,18 @@ describe("Player service -", function() {
|
|||
player.restart();
|
||||
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() {
|
||||
player.queue = [];
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<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" />
|
||||
</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" />
|
||||
</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" />
|
||||
</a>
|
||||
<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.playSong = function (song) {
|
||||
console.log('Queue Controller - playSong()', song);
|
||||
player.play(song);
|
||||
};
|
||||
|
||||
|
|
|
@ -793,7 +793,35 @@ angular.module('jamstash.subsonic.service', ['jamstash.settings', 'jamstash.util
|
|||
}
|
||||
});
|
||||
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
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -2,10 +2,6 @@ describe("Subsonic service -", function() {
|
|||
'use strict';
|
||||
|
||||
var subsonic, mockBackend, mockGlobals, response;
|
||||
|
||||
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';
|
||||
|
||||
beforeEach(function() {
|
||||
// We redefine it because in some tests we need to alter the settings
|
||||
mockGlobals = {
|
||||
|
@ -37,7 +33,22 @@ describe("Subsonic service -", function() {
|
|||
mockBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
it("scrobble - Given a song, when I scrobble it, it returns true if there was no error", function() {
|
||||
var song = { id: 45872 };
|
||||
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';
|
||||
|
||||
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||
|
||||
var promise = subsonic.scrobble(song);
|
||||
mockBackend.flush();
|
||||
|
||||
expect(promise).toBeResolved();
|
||||
});
|
||||
|
||||
describe("getStarred -", function() {
|
||||
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';
|
||||
|
||||
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() {
|
||||
response["subsonic-response"].starred = {artist: [{id: 2245}], album: [{id: 1799},{id: 20987}], song: [{id: 2478},{id: 14726},{id: 742}]};
|
||||
|
@ -83,7 +94,7 @@ describe("Subsonic service -", function() {
|
|||
|
||||
expect(promise).toBeRejectedWith({reason: 'Nothing is starred on the Subsonic server.'});
|
||||
});
|
||||
|
||||
// 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');
|
||||
|
||||
|
@ -112,6 +123,9 @@ describe("Subsonic service -", function() {
|
|||
}); //end getStarred
|
||||
|
||||
describe("getRandomStarredSongs -", function() {
|
||||
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';
|
||||
|
||||
describe("Given that the global setting AutoPlaylist Size is 3", function() {
|
||||
|
||||
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() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue