diff --git a/app/app.js b/app/app.js index 088f9e8..1d9c3da 100755 --- a/app/app.js +++ b/app/app.js @@ -1,8 +1,8 @@ 'use strict'; /* Declare app level module */ -angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize', 'ui.keypress', - 'jamstash.subsonic.controller', 'jamstash.archive.controller', 'jamstash.player.controller', 'jamstash.queue.controller', 'jamstash.persistence']) +angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize', 'ui.keypress', 'angular-underscore/utils', + 'jamstash.subsonic.controller', 'jamstash.archive.controller', 'jamstash.player.controller', 'jamstash.queue.controller', 'jamstash.settings.controller', 'jamstash.persistence']) .config(['$routeProvider',function($routeProvider) { $routeProvider @@ -48,4 +48,6 @@ angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize', 'ui.keypress', } }; }]); -}]); +}]) + +.constant('jamstashVersion', '4.4.5'); diff --git a/app/archive/archive-service.js b/app/archive/archive-service.js index d20b42a..e2c37b4 100644 --- a/app/archive/archive-service.js +++ b/app/archive/archive-service.js @@ -3,7 +3,7 @@ * * Access Archive.org */ -angular.module('jamstash.archive.service', ['jamstash.settings', 'jamstash.model', 'jamstash.notifications', +angular.module('jamstash.archive.service', ['jamstash.settings.service', 'jamstash.model', 'jamstash.notifications', 'jamstash.player.service']) .factory('archive', ['$rootScope', '$http', '$q', '$sce', 'globals', 'model', 'utils', 'map', 'notifications', 'player', diff --git a/app/common/main-controller.js b/app/common/main-controller.js index ae431a4..d6721f8 100644 --- a/app/common/main-controller.js +++ b/app/common/main-controller.js @@ -32,19 +32,12 @@ angular.module('JamStash') $scope.loadSettings = function () { // Temporary Code to Convert Cookies added 2/2/2014 if ($cookieStore.get('Settings')) { - utils.setValue('Settings', $cookieStore.get('Settings'), false); + persistence.saveSettings($cookieStore.get('Settings')); $cookieStore.remove('Settings'); } - if (utils.getValue('Settings')) { - $.each(utils.getValue('Settings'), function (k, v) { - if (v == 'false') { v = false; } - if (v == 'true') { v = true; } - var exclude = ['Url']; - var idx = exclude.indexOf(k); - if (idx === -1) { - globals.settings[k] = v; - } - }); + var settings = persistence.getSettings(); + if (settings !== undefined) { + globals.settings = _(settings).omit('Url'); } if (utils.getValue("SavedCollections")) { globals.SavedCollections = utils.getValue("SavedCollections").split(","); } if (utils.getValue("DefaultCollection")) { globals.DefaultCollection = utils.getValue("DefaultCollection"); } diff --git a/app/common/main-controller_test.js b/app/common/main-controller_test.js index 27d74f2..8c9b659 100644 --- a/app/common/main-controller_test.js +++ b/app/common/main-controller_test.js @@ -21,7 +21,14 @@ describe("Main controller", function() { player.queue = []; // Mock the persistence service - persistence = jasmine.createSpyObj("persistence", ["loadQueue", "loadTrackPosition", "getVolume", "saveVolume"]); + persistence = jasmine.createSpyObj("persistence", [ + "loadQueue", + "loadTrackPosition", + "getVolume", + "saveVolume", + "getSettings", + "saveSettings" + ]); inject(function (_$controller_, $rootScope, _$document_, _$window_, _$location_, _$cookieStore_, _utils_, globals, _model_, _notifications_, _Page_) { scope = $rootScope.$new(); @@ -166,6 +173,24 @@ describe("Main controller", function() { expect(player.previousTrack).not.toHaveBeenCalled(); }); }); + + describe("loadSettings() -", function() { + it("Given user settings were saved using persistence, when I load the settings, the globals object will be completed with them, excluding the Url setting", function() { + persistence.getSettings.and.returnValue({ + "Url": "http://gmelinite.com/contrastive/hypercyanotic?a=overdrive&b=chirpling#postjugular", + "Username": "Hollingshead", + "AutoPlaylistSize": 25, + "AutoPlay": true + }); + + scope.loadSettings(); + expect(mockGlobals.settings.Username).toEqual("Hollingshead"); + expect(mockGlobals.settings.AutoPlaylistSize).toBe(25); + expect(mockGlobals.settings.AutoPlay).toBe(true); + expect(mockGlobals.settings.Url).toBeUndefined(); + }); + + }); }); describe("When starting up,", function() { diff --git a/app/common/page-service.js b/app/common/page-service.js index 89747da..781c7aa 100644 --- a/app/common/page-service.js +++ b/app/common/page-service.js @@ -3,7 +3,7 @@ * * Set the page's title from anywhere, the angular way */ -angular.module('jamstash.page', ['jamstash.settings', 'jamstash.utils']) +angular.module('jamstash.page', ['jamstash.settings.service', 'jamstash.utils']) .factory('Page', ['$interval', 'globals', 'utils', function($interval, globals, utils){ 'use strict'; diff --git a/app/common/persistence-service.js b/app/common/persistence-service.js index e8a4766..9b7cc59 100644 --- a/app/common/persistence-service.js +++ b/app/common/persistence-service.js @@ -5,7 +5,8 @@ * Provides load, save and delete operations for the current song and queue. * Data storage provided by HTML5 localStorage. */ -angular.module('jamstash.persistence', ['jamstash.settings', 'jamstash.player.service', 'jamstash.notifications', 'angular-locker']) +angular.module('jamstash.persistence', ['angular-locker', + 'jamstash.settings.service', 'jamstash.player.service', 'jamstash.notifications']) .config(['lockerProvider', function (lockerProvider) { lockerProvider.setDefaultDriver('local') @@ -13,7 +14,9 @@ angular.module('jamstash.persistence', ['jamstash.settings', 'jamstash.player.se .setEventsEnabled(false); }]) -.service('persistence', ['globals', 'player', 'notifications', 'locker', function (globals, player, notifications, locker) { +.service('persistence', ['globals', 'player', 'notifications', 'locker', 'jamstashVersion', + function (globals, player, notifications, locker, jamstashVersion) { + /* Manage current track */ this.loadTrackPosition = function () { // Load Saved Song var song = locker.get('CurrentSong'); @@ -33,6 +36,7 @@ angular.module('jamstash.persistence', ['jamstash.settings', 'jamstash.player.se if (globals.settings.Debug) { console.log('Removing Current Position from localStorage'); } }; + /* Manage playing queue */ this.loadQueue = function () { // load Saved queue var queue = locker.get('CurrentQueue'); @@ -55,6 +59,7 @@ angular.module('jamstash.persistence', ['jamstash.settings', 'jamstash.player.se if (globals.settings.Debug) { console.log('Removing Play Queue from localStorage'); } }; + /* Manage player volume */ this.getVolume = function () { return locker.get('Volume'); }; @@ -66,5 +71,37 @@ angular.module('jamstash.persistence', ['jamstash.settings', 'jamstash.player.se this.deleteVolume = function () { locker.forget('Volume'); }; + + /* Manage user settings */ + this.getSettings = function () { + if(this.getVersion() !== jamstashVersion) { + this.upgradeToVersion(jamstashVersion); + } + return locker.get('Settings'); + }; + + this.saveSettings = function (settings) { + locker.put('Settings', settings); + }; + + this.deleteSettings = function () { + locker.forget('Settings'); + }; + + /* Manage Jamstash Version */ + this.getVersion = function () { + return locker.get('version'); + }; + + this.upgradeToVersion = function (version) { + locker.put('version', version); + switch (version) { + case '4.4.5': + var settings = locker.get('Settings'); + settings.DefaultSearchType = 0; + this.saveSettings(settings); + break; + } + }; }]); diff --git a/app/common/persistence-service_test.js b/app/common/persistence-service_test.js index f60ae3e..771d030 100644 --- a/app/common/persistence-service_test.js +++ b/app/common/persistence-service_test.js @@ -1,10 +1,16 @@ describe("Persistence service", function() { 'use strict'; - var persistence, player, notifications, locker; - var song; + var persistence, player, notifications, locker, + song, fakeStorage; beforeEach(function() { - module('jamstash.persistence'); + module('jamstash.persistence', function ($provide) { + // Mock locker + $provide.decorator('locker', function () { + return jasmine.createSpyObj("locker", ["get", "put", "forget"]); + }); + $provide.constant("jamstashVersion", "1.0.1"); + }); inject(function (_persistence_, _player_, _notifications_, _locker_) { persistence = _persistence_; @@ -20,135 +26,196 @@ describe("Persistence service", function() { album: 'Tammanyize' }; player.queue = []; + + fakeStorage = {}; + + locker.get.and.callFake(function(key) { + return fakeStorage[key]; + }); }); - describe("load from localStorage -", function() { - var fakeStorage; + describe("loadTrackPosition() -", function() { beforeEach(function() { - fakeStorage = {}; + spyOn(player, "load"); + }); - spyOn(locker, "get").and.callFake(function(key) { - return fakeStorage[key]; + it("Given a previously saved song in local storage, when I load the song, the player will load it", function() { + fakeStorage = { 'CurrentSong': song }; + + persistence.loadTrackPosition(); + + expect(locker.get).toHaveBeenCalledWith('CurrentSong'); + expect(player.load).toHaveBeenCalledWith(song); + }); + + it("Given that no song was previously saved in local storage, it doesn't do anything", function() { + persistence.loadTrackPosition(); + expect(locker.get).toHaveBeenCalledWith('CurrentSong'); + expect(player.load).not.toHaveBeenCalled(); + }); + }); + + it("saveTrackPosition() - saves the current track's position in local storage", function() { + persistence.saveTrackPosition(song); + expect(locker.put).toHaveBeenCalledWith('CurrentSong', song); + }); + + it("deleteTrackPosition() - deletes the current track from local storage", function() { + persistence.deleteTrackPosition(); + expect(locker.forget).toHaveBeenCalledWith('CurrentSong'); + }); + + describe("loadQueue() -", function() { + beforeEach(function() { + spyOn(notifications, "updateMessage"); + spyOn(player, "addSongs").and.callFake(function (songs) { + // Update the queue length so that notifications work + player.queue.length += songs.length; }); }); - describe("loadTrackPosition -", function() { - beforeEach(function() { - spyOn(player, "load"); - }); + it("Given a previously saved queue in local storage, when I load the queue, the player's queue will be filled with the retrieved queue and the user will be notified", function() { + var queue = [ + { id: 8705 }, + { id: 1617 }, + { id: 9812 } + ]; + fakeStorage = { 'CurrentQueue': queue }; - it("Given that we previously saved the current track's position in local Storage, it loads the song we saved into the player", function() { - fakeStorage = { 'CurrentSong': song }; + persistence.loadQueue(); - persistence.loadTrackPosition(); + expect(locker.get).toHaveBeenCalledWith('CurrentQueue'); + expect(player.addSongs).toHaveBeenCalledWith(queue); + expect(notifications.updateMessage).toHaveBeenCalledWith('3 Saved Song(s)', true); + }); - expect(locker.get).toHaveBeenCalledWith('CurrentSong'); - expect(player.load).toHaveBeenCalledWith(song); - }); + it("Given that no queue was previously saved in local storage, when I load the queue, the player's queue will stay the same and no notification will be displayed", function() { + persistence.loadQueue(); - it("Given that we didn't save anything in local Storage, it doesn't load anything", function() { - persistence.loadTrackPosition(); - expect(locker.get).toHaveBeenCalledWith('CurrentSong'); - expect(player.load).not.toHaveBeenCalled(); + expect(locker.get).toHaveBeenCalledWith('CurrentQueue'); + expect(player.addSongs).not.toHaveBeenCalled(); + expect(notifications.updateMessage).not.toHaveBeenCalled(); + }); + }); + + it("saveQueue() - saves the playing queue in local storage", function() { + player.queue = [ + { id: 1245 }, + { id: 7465 }, + { id: 948 } + ]; + persistence.saveQueue(); + expect(locker.put).toHaveBeenCalledWith('CurrentQueue', player.queue); + }); + + it("deleteQueue() - deletes the saved playing queue from local storage", function() { + persistence.deleteQueue(); + expect(locker.forget).toHaveBeenCalledWith('CurrentQueue'); + }); + + describe("getVolume() -", function() { + it("Given a previously saved volume value in local storage, it retrieves it", function() { + fakeStorage = { 'Volume': 0.46582 }; + + var volume = persistence.getVolume(); + + expect(locker.get).toHaveBeenCalledWith('Volume'); + expect(volume).toBe(0.46582); + }); + + it("Given that no volume value was previously saved in local storage, it returns undefined", function() { + var volume = persistence.getVolume(); + + expect(locker.get).toHaveBeenCalledWith('Volume'); + expect(volume).toBeUndefined(); + }); + }); + + it("saveVolume() - given a volume, it will be saved in local storage", function() { + persistence.saveVolume(0.05167); + expect(locker.put).toHaveBeenCalledWith('Volume', 0.05167); + }); + + it("deleteVolume() - deletes the saved volume from local storage", function() { + persistence.deleteVolume(); + expect(locker.forget).toHaveBeenCalledWith('Volume'); + }); + + describe("getSettings() -", function() { + it("Given previously saved user settings in local storage, it retrieves them", function() { + fakeStorage = { + "Settings": { + "url": "https://headed.com/aleurodidae/taistrel?a=roquet&b=trichophoric#cathole", + "Username": "Haupert" + } + }; + + var settings = persistence.getSettings(); + + expect(locker.get).toHaveBeenCalledWith('Settings'); + expect(settings).toEqual({ + "url": "https://headed.com/aleurodidae/taistrel?a=roquet&b=trichophoric#cathole", + "Username": "Haupert" }); }); - describe("loadQueue -", function() { + it("Given that the previously stored Jamstash version was '1.0.0' and given the current constant jamstash.version was '1.0.1', when I get the settings, then upgradeToVersion will be called", function() { + spyOn(persistence, 'upgradeToVersion'); + + persistence.getSettings(); + + expect(persistence.upgradeToVersion).toHaveBeenCalledWith('1.0.1'); + }); + + it("Given that no user settings had been saved in local storage, it returns undefined", function() { + var settings = persistence.getSettings(); + + expect(locker.get).toHaveBeenCalledWith('Settings'); + expect(settings).toBeUndefined(); + }); + }); + + it("saveSettings() - given a user settings object, it will be saved in local storage", function() { + persistence.saveSettings({ + "url": "http://crotalic.com/cabernet/coelenteron?a=dayshine&b=pantaletless#sus", + "Username": "Herrig" + }); + expect(locker.put).toHaveBeenCalledWith('Settings', { + "url": "http://crotalic.com/cabernet/coelenteron?a=dayshine&b=pantaletless#sus", + "Username": "Herrig" + }); + }); + + it("deleteSettings() - deletes the saved user settings from local storage", function() { + persistence.deleteSettings(); + expect(locker.forget).toHaveBeenCalledWith('Settings'); + }); + + describe("upgradeToVersion() -", function() { + describe("Given that Jamstash version '1.0.0' was previously stored in local storage,", function() { beforeEach(function() { - spyOn(notifications, "updateMessage"); - spyOn(player, "addSongs").and.callFake(function (songs) { - // Update the queue length so that notifications work - player.queue.length += songs.length; + fakeStorage.version = '1.0.0'; + }); + + it("when I upgrade the storage version to '1.0.1', Jamstash version '1.0.1' will be in local storage", function() { + persistence.upgradeToVersion('1.0.1'); + expect(locker.put).toHaveBeenCalledWith('version', '1.0.1'); + }); + + it("that settings.DefaultSearchType was stored as an object and that a changeset for version '4.4.5' was defined that changes it to an int, when I upgrade the storage version to '4.4.5', settings.DefaultSearch will be stored as an int", function() { + fakeStorage = { + Settings: { + DefaultSearchType: { + id: "song", + name: "Song" + } + } + }; + persistence.upgradeToVersion('4.4.5'); + expect(locker.put).toHaveBeenCalledWith('Settings', { + DefaultSearchType: 0 }); }); - - 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 }; - - persistence.loadQueue(); - - expect(locker.get).toHaveBeenCalledWith('CurrentQueue'); - expect(player.addSongs).toHaveBeenCalledWith(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() { - persistence.loadQueue(); - - expect(locker.get).toHaveBeenCalledWith('CurrentQueue'); - expect(player.addSongs).not.toHaveBeenCalled(); - expect(notifications.updateMessage).not.toHaveBeenCalled(); - }); - }); - - describe("getVolume -", function() { - it("Given that we previously saved the volume in local Storage, it retrieves it", function() { - fakeStorage = { 'Volume': 0.46582 }; - - var volume = persistence.getVolume(); - - expect(locker.get).toHaveBeenCalledWith('Volume'); - expect(volume).toBe(0.46582); - }); - - it("Given that we didn't save the volume in local Storage, it returns undefined", function() { - var volume = persistence.getVolume(); - - expect(locker.get).toHaveBeenCalledWith('Volume'); - expect(volume).toBeUndefined(); - }); - }); - }); - - describe("save to localStorage -", function() { - beforeEach(function() { - spyOn(locker, "put"); - }); - - it("saves the current track's position in local Storage", function() { - persistence.saveTrackPosition(song); - expect(locker.put).toHaveBeenCalledWith('CurrentSong', song); - }); - - it("saves the playing queue in local Storage", function() { - player.queue = [ - { id: 1245 }, - { id: 7465 }, - { id: 948 } - ]; - persistence.saveQueue(); - expect(locker.put).toHaveBeenCalledWith('CurrentQueue', player.queue); - }); - - it("saves the volume in local Storage", function() { - persistence.saveVolume(0.05167); - expect(locker.put).toHaveBeenCalledWith('Volume', 0.05167); - }); - }); - - describe("remove from localStorage -", function() { - beforeEach(function() { - spyOn(locker, "forget"); - }); - - it("deletes the current track from local Storage", function() { - persistence.deleteTrackPosition(); - expect(locker.forget).toHaveBeenCalledWith('CurrentSong'); - }); - - it("deletes the saved playing queue from local Storage", function() { - persistence.deleteQueue(); - expect(locker.forget).toHaveBeenCalledWith('CurrentQueue'); - }); - - it("deletes the saved volume from local Storage", function() { - persistence.deleteVolume(); - expect(locker.forget).toHaveBeenCalledWith('Volume'); }); }); }); diff --git a/app/common/utils-service.js b/app/common/utils-service.js index c2b9e01..9788b3d 100644 --- a/app/common/utils-service.js +++ b/app/common/utils-service.js @@ -3,7 +3,7 @@ * * Provides generally useful functions, like sorts, date-related functions, localStorage access, etc. */ -angular.module('jamstash.utils', ['jamstash.settings']) +angular.module('jamstash.utils', ['jamstash.settings.service']) .service('utils', ['$rootScope', 'globals', function ($rootScope, globals) { 'use strict'; diff --git a/app/player/player-directive.js b/app/player/player-directive.js index a0d9afc..65ccc31 100644 --- a/app/player/player-directive.js +++ b/app/player/player-directive.js @@ -4,7 +4,7 @@ * 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', 'jamstash.notifications', 'jamstash.persistence', 'jamstash.page']) +angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstash.settings.service', 'jamstash.subsonic.service', 'jamstash.notifications', 'jamstash.persistence', 'jamstash.page']) .directive('jplayer', ['$interval', 'player', 'globals', 'subsonic', 'notifications', 'persistence', 'Page', function($interval, playerService, globals, subsonic, notifications, persistence, Page) { diff --git a/app/player/player-directive_test.js b/app/player/player-directive_test.js index ea48650..60ddddc 100644 --- a/app/player/player-directive_test.js +++ b/app/player/player-directive_test.js @@ -32,6 +32,7 @@ describe("jplayer directive", function() { return $delegate; }); $provide.value('globals', mockGlobals); + $provide.constant('jamstashVersion', '1.0.0'); }); spyOn($.fn, "jPlayer").and.callThrough(); diff --git a/app/player/player-service.js b/app/player/player-service.js index 1150662..5752941 100644 --- a/app/player/player-service.js +++ b/app/player/player-service.js @@ -3,7 +3,7 @@ * * 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', ['angular-underscore/utils', 'jamstash.settings']) +angular.module('jamstash.player.service', ['jamstash.settings.service', 'angular-underscore/utils']) .factory('player', ['globals', function (globals) { 'use strict'; diff --git a/app/settings/settings-service.js b/app/settings/settings-service.js index 9338211..a48aed1 100644 --- a/app/settings/settings-service.js +++ b/app/settings/settings-service.js @@ -1,9 +1,9 @@ /** -* jamstash.settings Module +* jamstash.settings.service Module * * Houses Jamstash's global settings and a few utility functions. */ -angular.module('jamstash.settings', []) +angular.module('jamstash.settings.service', []) .service('globals', function () { 'use strict'; diff --git a/app/settings/settings-service_test.js b/app/settings/settings-service_test.js index 2937ceb..9389e50 100644 --- a/app/settings/settings-service_test.js +++ b/app/settings/settings-service_test.js @@ -1,9 +1,9 @@ -describe("settings service", function() { +describe("Settings service", function() { 'use strict'; var globals; beforeEach(function() { - module('jamstash.settings'); + module('jamstash.settings.service'); inject(function (_globals_) { globals = _globals_; }); @@ -24,4 +24,4 @@ describe("settings service", function() { }); //TODO: JMA: add callback param if jsonp -}); \ No newline at end of file +}); diff --git a/app/settings/settings.js b/app/settings/settings.js index 6ce8755..e45b6cc 100644 --- a/app/settings/settings.js +++ b/app/settings/settings.js @@ -1,7 +1,7 @@ -angular.module('JamStash') +angular.module('jamstash.settings.controller', ['jamstash.settings.service', 'jamstash.persistence']) -.controller('SettingsController', ['$rootScope', '$scope', '$routeParams', '$location', 'utils', 'globals', 'json', 'notifications', 'persistence', 'subsonic', - function ($rootScope, $scope, $routeParams, $location, utils, globals, json, notifications, persistence, subsonic) { +.controller('SettingsController', ['$rootScope', '$scope', '$location', 'utils', 'globals', 'json', 'notifications', 'persistence', 'subsonic', + function ($rootScope, $scope, $location, utils, globals, json, notifications, persistence, subsonic) { 'use strict'; $rootScope.hideQueue(); $scope.settings = globals.settings; /* See service.js */ @@ -28,8 +28,9 @@ } }); $scope.reset = function () { - utils.setValue('Settings', null, true); + persistence.deleteSettings(); $scope.loadSettings(); + // TODO: Hyz: reload the page }; $scope.save = function () { if ($scope.settings.Password !== '' && globals.settings.Password.substring(0, 4) != 'enc:') { $scope.settings.Password = 'enc:' + utils.HexEncode($scope.settings.Password); } @@ -60,7 +61,7 @@ } else { $rootScope.hideQueue(); } - utils.setValue('Settings', $scope.settings, true); + persistence.saveSettings($scope.settings); notifications.updateMessage('Settings Updated!', true); $scope.loadSettings(); if (globals.settings.Server !== '' && globals.settings.Username !== '' && globals.settings.Password !== '') { diff --git a/app/settings/settings_test.js b/app/settings/settings_test.js new file mode 100644 index 0000000..3755ad8 --- /dev/null +++ b/app/settings/settings_test.js @@ -0,0 +1,106 @@ +describe("Settings controller", function() { + 'use strict'; + + var scope, $rootScope, $controller, $location, $q, + controllerParams, utils, persistence, mockGlobals, json, notifications, subsonic, deferred; + + beforeEach(function() { + jasmine.addCustomEqualityTester(angular.equals); + + module('jamstash.settings.controller'); + + mockGlobals = { + settings: { + Password: '', + Server: '' + } + }; + // Mock all the services + utils = jasmine.createSpyObj("utils", ["HexEncode"]); + persistence = jasmine.createSpyObj("persistence", ["saveQueue", "deleteQueue", "deleteTrackPosition", "saveSettings", "deleteSettings"]); + json = jasmine.createSpyObj("json", ["getChangeLog"]); + notifications = jasmine.createSpyObj("notifications", ["requestPermissionIfRequired", "isSupported", "updateMessage"]); + + + inject(function (_$controller_, _$rootScope_, _$location_, _$q_) { + $rootScope = _$rootScope_; + scope = $rootScope.$new(); + $location = _$location_; + $q = _$q_; + deferred = $q.defer(); + + $rootScope.hideQueue = jasmine.createSpy("hideQueue"); + $rootScope.loadSettings = jasmine.createSpy("loadSettings"); + + // Mock subsonic-service using $q + subsonic = jasmine.createSpyObj("subsonic", ["ping"]); + + $controller = _$controller_; + controllerParams = { + $rootScope: $rootScope, + $scope: scope, + $location: $location, + utils: utils, + globals: mockGlobals, + json: json, + notifications: notifications, + persistence: persistence, + subsonic: subsonic + }; + }); + }); + + describe("", function() { + beforeEach(function() { + $controller('SettingsController', controllerParams); + }); + + describe("save() -", function() { + it("Given the settings have been set, when I save them, then the settings will be saved using the persistence service and the user will be notified", function() { + scope.save(); + + expect(persistence.saveSettings).toHaveBeenCalledWith(scope.settings); + expect(notifications.updateMessage).toHaveBeenCalledWith('Settings Updated!', true); + }); + + it("Given that the SaveTrackPosition setting was true, when I save the settings, then the current queue will be saved using the persistence service", function() { + scope.settings.SaveTrackPosition = true; + + scope.save(); + + expect(persistence.saveQueue).toHaveBeenCalled(); + }); + + it("Given that the SaveTrackPosition setting was false, when I save the settings, then the saved queue and track will be deleted from the persistence service", function() { + scope.settings.SaveTrackPosition = false; + + scope.save(); + + expect(persistence.deleteTrackPosition).toHaveBeenCalled(); + expect(persistence.deleteQueue).toHaveBeenCalled(); + }); + + it("Given that the Server, Username and Password settings weren't empty, when I save the settings, then subsonic service will be pinged", function() { + scope.settings.Server = 'http://hexagram.com/malacobdella/liposis?a=platybasic&b=enantiopathia#stratoplane'; + scope.settings.Username = 'Mollura'; + scope.settings.Password = 'FPTVjZtBwEyq'; + subsonic.ping.and.returnValue(deferred.promise); + + scope.save(); + + expect(subsonic.ping).toHaveBeenCalled(); + }); + }); + + it("reset() - When I reset the settings, they will be deleted from the persistence service and will be reloaded with default values", function() { + scope.reset(); + + expect(persistence.deleteSettings).toHaveBeenCalled(); + expect(scope.loadSettings).toHaveBeenCalled(); + }); + }); + + describe("On startup", function() { + + }); +}); diff --git a/app/subsonic/subsonic-service.js b/app/subsonic/subsonic-service.js index c021a76..86d9feb 100644 --- a/app/subsonic/subsonic-service.js +++ b/app/subsonic/subsonic-service.js @@ -4,8 +4,8 @@ * Provides access through $http to the Subsonic server's API. * Also offers more fine-grained functionality that is not part of Subsonic's API. */ -angular.module('jamstash.subsonic.service', ['jamstash.settings', 'jamstash.utils', 'jamstash.model', - 'jamstash.notifications', 'jamstash.player.service', 'angular-underscore/utils']) +angular.module('jamstash.subsonic.service', ['angular-underscore/utils', + 'jamstash.settings.service', 'jamstash.utils', 'jamstash.model', 'jamstash.notifications', 'jamstash.player.service']) .factory('subsonic', ['$rootScope', '$http', '$q', 'globals', 'utils', 'map', 'notifications', 'player', function ($rootScope, $http, $q, globals, utils, map, notifications, player) { diff --git a/app/subsonic/subsonic_test.js b/app/subsonic/subsonic_test.js index 042cf5f..b00694f 100644 --- a/app/subsonic/subsonic_test.js +++ b/app/subsonic/subsonic_test.js @@ -1,7 +1,8 @@ describe("Subsonic controller", function() { 'use strict'; - var scope, $rootScope, $controller, $window, subsonic, notifications, player, controllerParams, deferred; + var scope, $rootScope, $controller, $window, + subsonic, notifications, player, controllerParams, deferred; beforeEach(function() { jasmine.addCustomEqualityTester(angular.equals);