Refactors the getStarred function, refactors its tests.
getStarred queries the Subsonic server and caches the request. It handles both GET and JSONP. It returns meaningful messages when there is a problem and distinguishes between HTTP errors and Subsonic errors. Those messages are meant to be displayed by the controller using the notifications. The tests are refactored too : most of what is common is at the top describe to keep the tests lean. Tests for error conditions have been added.
This commit is contained in:
parent
4a09559aae
commit
c5cbad003f
2 changed files with 162 additions and 41 deletions
|
@ -557,28 +557,59 @@ Jamstash.factory('subsonic', function ($rootScope, $http, $q, globals, utils, ma
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
getStarred: function (action, type) {
|
getStarred: function (action, type) {
|
||||||
|
var exception = {reason: 'Error when contacting the Subsonic server.'};
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
// TODO: JMA: GET variant
|
var httpPromise;
|
||||||
$http.jsonp(globals.BaseURL() + '/getStarred.view?callback=JSON_CALLBACK&' + globals.BaseParams(),
|
if(globals.settings.Protocol === 'jsonp') {
|
||||||
{
|
httpPromise = $http.jsonp(globals.BaseURL() + '/getStarred.view?callback=JSON_CALLBACK&' + globals.BaseParams(),
|
||||||
timeout: globals.settings.Timeout
|
{
|
||||||
})
|
timeout: globals.settings.Timeout,
|
||||||
.success(function(data, status) {
|
cache: true
|
||||||
console.log("blu");
|
});
|
||||||
console.log(data);
|
} else {
|
||||||
if(data['subsonic-response'] !== undefined && data['subsonic-response'].status === 'ok') {
|
httpPromise = $http.get(globals.BaseURL() + '/getStarred.view?' + globals.BaseParams(),
|
||||||
console.log('green');
|
{
|
||||||
// Return only first X starred songs
|
timeout: globals.settings.Timeout,
|
||||||
var starredSongs = data['subsonic-response'].starred.song.slice(0, globals.settings.AutoPlaylistSize);
|
cache: true
|
||||||
deferred.resolve(starredSongs);
|
});
|
||||||
|
}
|
||||||
|
httpPromise.success(function(data, status) {
|
||||||
|
var subsonicResponse = (data['subsonic-response'] !== undefined) ? data['subsonic-response'] : {status: 'failed'};
|
||||||
|
if (subsonicResponse.status === 'ok') {
|
||||||
|
if(angular.equals(subsonicResponse.starred, {})) {
|
||||||
|
deferred.reject({reason: 'Nothing is starred on the Subsonic server.'});
|
||||||
|
} else {
|
||||||
|
deferred.resolve(subsonicResponse.starred);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
deferred.reject();
|
if(subsonicResponse.status === 'failed' && subsonicResponse.error !== undefined) {
|
||||||
|
exception.subsonicError = subsonicResponse.error;
|
||||||
|
}
|
||||||
|
deferred.reject(exception);
|
||||||
}
|
}
|
||||||
}).error(function(data, status) {
|
}).error(function(data, status) {
|
||||||
deferred.reject();
|
exception.httpError = status;
|
||||||
|
deferred.reject(exception);
|
||||||
});
|
});
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
|
getRandomStarredSongs: function() {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
|
||||||
|
this.getStarred().then(function (data) {
|
||||||
|
if(data.song !== undefined) {
|
||||||
|
// Return only first X starred songs
|
||||||
|
var starredSongs = data.song.slice(0, globals.settings.AutoPlaylistSize);
|
||||||
|
deferred.resolve(starredSongs);
|
||||||
|
} else {
|
||||||
|
deferred.reject('No starred songs found on the Subsonic server.');
|
||||||
|
}
|
||||||
|
}, function (reason) {
|
||||||
|
deferred.reject(reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
},
|
||||||
/*
|
/*
|
||||||
getStarred: function (action, type) {
|
getStarred: function (action, type) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
|
@ -1,51 +1,141 @@
|
||||||
describe("subsonic service -", function() {
|
describe("subsonic service -", function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var subsonic, mockBackend;
|
var subsonic, mockBackend, mockGlobals;
|
||||||
|
var response;
|
||||||
|
// Spies
|
||||||
|
var success, failure;
|
||||||
|
|
||||||
describe("Given that the global setting AutoPlaylist Size is 3", function() {
|
var url = 'http://demo.subsonic.com/rest/getStarred.view?'+
|
||||||
var mockGlobals = {
|
'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 = {
|
||||||
settings: {
|
settings: {
|
||||||
AutoPlaylistSize: 3,
|
AutoPlaylistSize: 3,
|
||||||
protocol: 'jsonp'
|
Protocol: 'jsonp'
|
||||||
},
|
},
|
||||||
BaseURL: function () {
|
BaseURL: function () {
|
||||||
return 'http://subsonic.furinax.com/rest';
|
return 'http://demo.subsonic.com/rest';
|
||||||
},
|
},
|
||||||
BaseParams: function () {
|
BaseParams: function () {
|
||||||
return 'u=Hyzual&p=enc:7375622e6461726b353079306432&v=1.10.2&c=Jamstash&f=jsonp';
|
return 'u=Hyzual&p=enc:cGFzc3dvcmQ=&v=1.10.2&c=Jamstash&f=jsonp';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(function() {
|
module('JamStash', function ($provide) {
|
||||||
module('JamStash', function ($provide) {
|
$provide.value('globals', mockGlobals);
|
||||||
$provide.value('globals', mockGlobals);
|
|
||||||
});
|
|
||||||
|
|
||||||
inject(function (_subsonic_, $httpBackend) {
|
|
||||||
subsonic = _subsonic_;
|
|
||||||
mockBackend = $httpBackend;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
inject(function (_subsonic_, $httpBackend) {
|
||||||
mockBackend.verifyNoOutstandingExpectation();
|
subsonic = _subsonic_;
|
||||||
mockBackend.verifyNoOutstandingRequest();
|
mockBackend = $httpBackend;
|
||||||
});
|
});
|
||||||
|
success = jasmine.createSpy('success');
|
||||||
|
failure = jasmine.createSpy('failure');
|
||||||
|
response = {"subsonic-response": {status: "ok", version: "1.10.2"}};
|
||||||
|
});
|
||||||
|
|
||||||
it("and given that I have more than 3 starred songs in my library, when getting the starred artists, the result should be limited to 3 starred artists", function() {
|
afterEach(function() {
|
||||||
|
mockBackend.verifyNoOutstandingExpectation();
|
||||||
|
mockBackend.verifyNoOutstandingRequest();
|
||||||
|
});
|
||||||
|
|
||||||
var url = 'http://subsonic.furinax.com/rest/getStarred.view?'+
|
describe("getStarred -", function() {
|
||||||
'callback=JSON_CALLBACK&u=Hyzual&p=enc:7375622e6461726b353079306432&v=1.10.2&c=Jamstash&f=jsonp';
|
|
||||||
var response = '{"subsonic-response": {"status": "ok","version": "1.10.2","starred": {"song": [{"id": "11841"},{"id": "12061"},{"id": "17322"},{"id": "1547"}]}}}';
|
|
||||||
|
|
||||||
var limitedStarred = [{id: "11841"},{id: "12061"},{id: "17322"}];
|
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() {
|
||||||
mockBackend.whenJSONP(url).respond(200, response);
|
response["subsonic-response"].starred = {artist: [{id: 2245}], album: [{id: 1799},{id: 20987}], song: [{id: 2478},{id: 14726},{id: 742}]};
|
||||||
var success = jasmine.createSpy('success');
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
subsonic.getStarred().then(success);
|
subsonic.getStarred().then(success);
|
||||||
mockBackend.flush();
|
mockBackend.flush();
|
||||||
expect(success).toHaveBeenCalledWith(limitedStarred);
|
|
||||||
|
expect(success).toHaveBeenCalledWith({artist: [{id: 2245}], album: [{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() {
|
||||||
|
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));
|
||||||
|
|
||||||
|
subsonic.getStarred().then(success);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).toHaveBeenCalledWith({song: [{id: "2147"},{id:"9847"},{id:"214"}]});
|
||||||
|
});
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
subsonic.getStarred().then(success, failure);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).not.toHaveBeenCalled();
|
||||||
|
expect(failure).toHaveBeenCalledWith({reason: 'Nothing is starred on the Subsonic server.'});
|
||||||
|
});
|
||||||
|
|
||||||
|
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');
|
||||||
|
|
||||||
|
subsonic.getStarred().then(success, failure);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).not.toHaveBeenCalled();
|
||||||
|
expect(failure).toHaveBeenCalledWith({reason: 'Error when contacting the Subsonic server.', httpError: 503});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Given a missing parameter, when getting the starred songs, it returns an error object with a message", function() {
|
||||||
|
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);
|
||||||
|
|
||||||
|
subsonic.getStarred().then(success, failure);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).not.toHaveBeenCalled();
|
||||||
|
expect(failure).toHaveBeenCalledWith({reason: 'Error when contacting the Subsonic server.', subsonicError: {code: 10, message:'Required parameter is missing.'}});
|
||||||
|
});
|
||||||
|
}); //end getStarred
|
||||||
|
|
||||||
|
describe("getRandomStarredSongs -", function() {
|
||||||
|
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() {
|
||||||
|
response["subsonic-response"].starred = {song: [{id: "11841"},{id: "12061"},{id: "17322"},{id: "1547"}]};
|
||||||
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
|
subsonic.getRandomStarredSongs().then(success);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).toHaveBeenCalledWith([{id: "11841"},{id: "12061"},{id: "17322"}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
subsonic.getRandomStarredSongs().then(success);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).toHaveBeenCalledWith([{id: "11841"}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and given that I don't have any starred song in my library, when getting random starred songs, it returns an empty array", function() {
|
||||||
|
response["subsonic-response"].starred = {song: []};
|
||||||
|
mockBackend.whenJSONP(url).respond(200, JSON.stringify(response));
|
||||||
|
|
||||||
|
subsonic.getRandomStarredSongs().then(success);
|
||||||
|
mockBackend.flush();
|
||||||
|
|
||||||
|
expect(success).toHaveBeenCalledWith([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
Add table
Add a link
Reference in a new issue