From b9099435cb6535db835d25361e7b706b85744b20 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Mon, 22 Apr 2013 16:05:45 +0200 Subject: add undo for feed and folder deletion, fix #56 --- js/app/directives/undonotification.coffee | 52 ++++++ .../businesslayer/feedbusinesslayer.coffee | 21 ++- .../businesslayer/folderbusinesslayer.coffee | 19 +- js/app/services/models/feedmodel.coffee | 3 +- js/app/services/undoqueue.coffee | 86 +++++++++ js/public/app.js | 207 +++++++++++++++++++-- .../businesslayer/feedbusinesslayerSpec.coffee | 8 +- .../businesslayer/folderbusinesslayerSpec.coffee | 6 +- js/tests/services/undoqueueSpec.coffee | 59 ++++++ 9 files changed, 434 insertions(+), 27 deletions(-) create mode 100644 js/app/directives/undonotification.coffee create mode 100644 js/app/services/undoqueue.coffee create mode 100644 js/tests/services/undoqueueSpec.coffee (limited to 'js') diff --git a/js/app/directives/undonotification.coffee b/js/app/directives/undonotification.coffee new file mode 100644 index 000000000..5e30af169 --- /dev/null +++ b/js/app/directives/undonotification.coffee @@ -0,0 +1,52 @@ +### + +ownCloud - News + +@author Bernhard Posselt +@copyright 2012 Bernhard Posselt nukeawhale@gmail.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +License as published by the Free Software Foundation; either +version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU AFFERO GENERAL PUBLIC LICENSE for more details. + +You should have received a copy of the GNU Affero General Public +License along with this library. If not, see . + +### + +angular.module('News').directive 'undoNotification', ['$rootScope', +($rootScope) -> + + return (scope, elm, attr) -> + + elm.click -> + $(@).fadeOut() + + scope.$on 'notUndone', -> + $(elm).fadeOut() + + undo = -> + caption = '' + + link = $(elm).find('a') + link.click -> + undo() + $rootScope.$apply() + elm.fadeOut() + + scope.getCaption = -> + return caption + + scope.$on 'undoMessage', (scope, data) -> + undo = data.undoCallback + caption = data.caption + elm.fadeIn().css("display","inline") + + +] \ No newline at end of file diff --git a/js/app/services/businesslayer/feedbusinesslayer.coffee b/js/app/services/businesslayer/feedbusinesslayer.coffee index 9d2f37390..93f89ad31 100644 --- a/js/app/services/businesslayer/feedbusinesslayer.coffee +++ b/js/app/services/businesslayer/feedbusinesslayer.coffee @@ -23,14 +23,16 @@ License along with this library. If not, see . angular.module('News').factory 'FeedBusinessLayer', ['_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType', -'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', +'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', '$rootScope', +'UndoQueue', (_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel, -FeedModel, NewLoading, _ExistsError, Utils) -> +FeedModel, NewLoading, _ExistsError, Utils, $rootScope, UndoQueue) -> class FeedBusinessLayer extends _BusinessLayer constructor: (@_showAll, @_feedModel, persistence, activeFeed, feedType, - itemModel, @_newLoading, @_utils) -> + itemModel, @_newLoading, @_utils, @_$rootScope, + @_undoQueue) -> super(activeFeed, persistence, itemModel, feedType.Feed) @_feedType = feedType @@ -52,8 +54,14 @@ FeedModel, NewLoading, _ExistsError, Utils) -> delete: (feedId) -> - @_feedModel.removeById(feedId) - @_persistence.deleteFeed(feedId) + feed = @_feedModel.removeById(feedId) + callback = => + @_persistence.deleteFeed(feedId) + + undoCallback = => + @_feedModel.add(feed) + + @_undoQueue.add(feed.title, callback, 10*1000, undoCallback) markFeedRead: (feedId) -> @@ -185,6 +193,7 @@ FeedModel, NewLoading, _ExistsError, Utils) -> return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed, - FeedType, ItemModel, NewLoading, Utils) + FeedType, ItemModel, NewLoading, Utils, + $rootScope, UndoQueue) ] \ No newline at end of file diff --git a/js/app/services/businesslayer/folderbusinesslayer.coffee b/js/app/services/businesslayer/folderbusinesslayer.coffee index d19796d85..e35866f21 100644 --- a/js/app/services/businesslayer/folderbusinesslayer.coffee +++ b/js/app/services/businesslayer/folderbusinesslayer.coffee @@ -24,22 +24,31 @@ License along with this library. If not, see . angular.module('News').factory 'FolderBusinessLayer', ['_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence', 'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser', +'UndoQueue', (_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType, -ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) -> +ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser, UndoQueue) -> class FolderBusinessLayer extends _BusinessLayer constructor: (@_folderModel, @_feedBusinessLayer, @_showAll, activeFeed, - persistence, @_feedType, itemModel, @_opmlParser) -> + persistence, @_feedType, itemModel, @_opmlParser, + @_undoQueue) -> super(activeFeed, persistence, itemModel, @_feedType.Folder) getById: (folderId) -> return @_folderModel.getById(folderId) + delete: (folderId) -> - @_folderModel.removeById(folderId) - @_persistence.deleteFolder(folderId) + folder = @_folderModel.removeById(folderId) + callback = => + @_persistence.deleteFolder(folderId) + + undoCallback = => + @_folderModel.add(folder) + + @_undoQueue.add(folder.name, callback, 10*1000, undoCallback) hasFeeds: (folderId) -> @@ -155,6 +164,6 @@ ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) -> return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll, ActiveFeed, Persistence, FeedType, ItemModel, - OPMLParser) + OPMLParser, UndoQueue) ] \ No newline at end of file diff --git a/js/app/services/models/feedmodel.coffee b/js/app/services/models/feedmodel.coffee index 4c925b94c..bddd647d3 100644 --- a/js/app/services/models/feedmodel.coffee +++ b/js/app/services/models/feedmodel.coffee @@ -40,7 +40,8 @@ angular.module('News').factory 'FeedModel', if data.faviconLink == null data.faviconLink = 'url(' + @_utils.imagePath('news', 'rss.svg') + ')' - else if angular.isDefined(data.faviconLink) + else if angular.isDefined(data.faviconLink) and + data.faviconLink.indexOf('url(') != 0 data.faviconLink = 'url(' + data.faviconLink + ')' ### We want to add a feed on the client side before diff --git a/js/app/services/undoqueue.coffee b/js/app/services/undoqueue.coffee new file mode 100644 index 000000000..30418bacf --- /dev/null +++ b/js/app/services/undoqueue.coffee @@ -0,0 +1,86 @@ +### + +ownCloud - App Framework + +@author Bernhard Posselt +@copyright 2012 Bernhard Posselt nukeawhale@gmail.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +License as published by the Free Software Foundation; either +version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU AFFERO GENERAL PUBLIC LICENSE for more details. + +You should have received a copy of the GNU Affero General Public +License along with this library. If not, see . + +### + +# A class which follows the command pattern +# Can be used for actions that need need to be able to undo like folder deletion +angular.module('News').factory 'UndoQueue', +['$timeout', '$rootScope', +($timeout, $rootScope) -> + + class UndoQueue + + constructor: (@_$timeout, @_$rootScope) -> + @_queue = [] + + + add: (@_caption, @_callback, @_timeout=0, @_undoCallback=null) -> + ### + @_caption the caption which indentifies the item + @_callback function the callback which should be executed when it was + not undone, this will usually be a request to the server to finally + delete something + @_timeout int the timeout after the callback should be executed + defaults to 0 + @_undoCallback function the function which should be executed when + an command has been canceled. Usually this will add back a deleted + object back to the interface, defaults to an empty function + ### + @_executeAll() + + command = + _undoCallback: @_undoCallback or= -> + _callback: @_callback + execute: => + command._callback() + undo: => + command._undoCallback() + @_$timeout.cancel(command.promise) + @_queue = [] + promise: @_$timeout => + command.execute() + @_$rootScope.$broadcast('notUndone') + , @_timeout + + data = + undoCallback: command.undo + caption: @_caption + + @_$rootScope.$broadcast 'undoMessage', data + + @_queue.push(command) + + + _executeAll: -> + ### + Executes the callback before the timeout has run out + This is useful to execute all remaining commands if a new command is + added + ### + for command in @_queue + @_$timeout.cancel(command.promise) + command.execute() + @_queue = [] + + + return new UndoQueue($timeout, $rootScope) + +] \ No newline at end of file diff --git a/js/public/app.js b/js/public/app.js index 38c2c6219..ca7124ad7 100644 --- a/js/public/app.js +++ b/js/public/app.js @@ -312,6 +312,63 @@ License along with this library. If not, see . */ +(function() { + angular.module('News').directive('undoNotification', [ + '$rootScope', function($rootScope) { + return function(scope, elm, attr) { + var caption, link, undo; + + elm.click(function() { + return $(this).fadeOut(); + }); + scope.$on('notUndone', function() { + return $(elm).fadeOut(); + }); + undo = function() {}; + caption = ''; + link = $(elm).find('a'); + link.click(function() { + undo(); + $rootScope.$apply(); + return elm.fadeOut(); + }); + scope.getCaption = function() { + return caption; + }; + return scope.$on('undoMessage', function(scope, data) { + undo = data.undoCallback; + caption = data.caption; + return elm.fadeIn().css("display", "inline"); + }); + }; + } + ]); + +}).call(this); + +// Generated by CoffeeScript 1.6.2 +/* + +ownCloud - News + +@author Bernhard Posselt +@copyright 2012 Bernhard Posselt nukeawhale@gmail.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +License as published by the Free Software Foundation; either +version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU AFFERO GENERAL PUBLIC LICENSE for more details. + +You should have received a copy of the GNU Affero General Public +License along with this library. If not, see . +*/ + + (function() { angular.module('News').controller('FeedController', [ '$scope', '_ExistsError', 'Persistence', 'FolderBusinessLayer', 'FeedBusinessLayer', 'SubscriptionsBusinessLayer', 'StarredBusinessLayer', 'unreadCountFormatter', 'ActiveFeed', 'FeedType', '$window', function($scope, _ExistsError, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter, ActiveFeed, FeedType, $window) { @@ -711,17 +768,19 @@ License along with this library. If not, see . __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; angular.module('News').factory('FeedBusinessLayer', [ - '_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType', 'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', function(_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel, FeedModel, NewLoading, _ExistsError, Utils) { + '_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType', 'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', '$rootScope', 'UndoQueue', function(_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel, FeedModel, NewLoading, _ExistsError, Utils, $rootScope, UndoQueue) { var FeedBusinessLayer; FeedBusinessLayer = (function(_super) { __extends(FeedBusinessLayer, _super); - function FeedBusinessLayer(_showAll, _feedModel, persistence, activeFeed, feedType, itemModel, _newLoading, _utils) { + function FeedBusinessLayer(_showAll, _feedModel, persistence, activeFeed, feedType, itemModel, _newLoading, _utils, _$rootScope, _undoQueue) { this._showAll = _showAll; this._feedModel = _feedModel; this._newLoading = _newLoading; this._utils = _utils; + this._$rootScope = _$rootScope; + this._undoQueue = _undoQueue; FeedBusinessLayer.__super__.constructor.call(this, activeFeed, persistence, itemModel, feedType.Feed); this._feedType = feedType; } @@ -743,8 +802,17 @@ License along with this library. If not, see . }; FeedBusinessLayer.prototype["delete"] = function(feedId) { - this._feedModel.removeById(feedId); - return this._persistence.deleteFeed(feedId); + var callback, feed, undoCallback, + _this = this; + + feed = this._feedModel.removeById(feedId); + callback = function() { + return _this._persistence.deleteFeed(feedId); + }; + undoCallback = function() { + return _this._feedModel.add(feed); + }; + return this._undoQueue.add(feed.title, callback, 10 * 1000, undoCallback); }; FeedBusinessLayer.prototype.markFeedRead = function(feedId) { @@ -912,7 +980,7 @@ License along with this library. If not, see . return FeedBusinessLayer; })(_BusinessLayer); - return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed, FeedType, ItemModel, NewLoading, Utils); + return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed, FeedType, ItemModel, NewLoading, Utils, $rootScope, UndoQueue); } ]); @@ -946,18 +1014,19 @@ License along with this library. If not, see . __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; angular.module('News').factory('FolderBusinessLayer', [ - '_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence', 'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser', function(_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType, ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) { + '_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence', 'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser', 'UndoQueue', function(_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType, ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser, UndoQueue) { var FolderBusinessLayer; FolderBusinessLayer = (function(_super) { __extends(FolderBusinessLayer, _super); - function FolderBusinessLayer(_folderModel, _feedBusinessLayer, _showAll, activeFeed, persistence, _feedType, itemModel, _opmlParser) { + function FolderBusinessLayer(_folderModel, _feedBusinessLayer, _showAll, activeFeed, persistence, _feedType, itemModel, _opmlParser, _undoQueue) { this._folderModel = _folderModel; this._feedBusinessLayer = _feedBusinessLayer; this._showAll = _showAll; this._feedType = _feedType; this._opmlParser = _opmlParser; + this._undoQueue = _undoQueue; FolderBusinessLayer.__super__.constructor.call(this, activeFeed, persistence, itemModel, this._feedType.Folder); } @@ -966,8 +1035,17 @@ License along with this library. If not, see . }; FolderBusinessLayer.prototype["delete"] = function(folderId) { - this._folderModel.removeById(folderId); - return this._persistence.deleteFolder(folderId); + var callback, folder, undoCallback, + _this = this; + + folder = this._folderModel.removeById(folderId); + callback = function() { + return _this._persistence.deleteFolder(folderId); + }; + undoCallback = function() { + return _this._folderModel.add(folder); + }; + return this._undoQueue.add(folder.name, callback, 10 * 1000, undoCallback); }; FolderBusinessLayer.prototype.hasFeeds = function(folderId) { @@ -1136,7 +1214,7 @@ License along with this library. If not, see . return FolderBusinessLayer; })(_BusinessLayer); - return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll, ActiveFeed, Persistence, FeedType, ItemModel, OPMLParser); + return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll, ActiveFeed, Persistence, FeedType, ItemModel, OPMLParser, UndoQueue); } ]); @@ -1626,7 +1704,7 @@ License along with this library. If not, see . } if (data.faviconLink === null) { data.faviconLink = 'url(' + this._utils.imagePath('news', 'rss.svg') + ')'; - } else if (angular.isDefined(data.faviconLink)) { + } else if (angular.isDefined(data.faviconLink) && data.faviconLink.indexOf('url(') !== 0) { data.faviconLink = 'url(' + data.faviconLink + ')'; } /* @@ -2977,6 +3055,113 @@ License along with this library. If not, see . // Generated by CoffeeScript 1.6.2 /* +ownCloud - App Framework + +@author Bernhard Posselt +@copyright 2012 Bernhard Posselt nukeawhale@gmail.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +License as published by the Free Software Foundation; either +version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU AFFERO GENERAL PUBLIC LICENSE for more details. + +You should have received a copy of the GNU Affero General Public +License along with this library. If not, see . +*/ + + +(function() { + angular.module('News').factory('UndoQueue', [ + '$timeout', '$rootScope', function($timeout, $rootScope) { + var UndoQueue; + + UndoQueue = (function() { + function UndoQueue(_$timeout, _$rootScope) { + this._$timeout = _$timeout; + this._$rootScope = _$rootScope; + this._queue = []; + } + + UndoQueue.prototype.add = function(_caption, _callback, _timeout, _undoCallback) { + var command, data, + _this = this; + + this._caption = _caption; + this._callback = _callback; + this._timeout = _timeout != null ? _timeout : 0; + this._undoCallback = _undoCallback != null ? _undoCallback : null; + /* + @_caption the caption which indentifies the item + @_callback function the callback which should be executed when it was + not undone, this will usually be a request to the server to finally + delete something + @_timeout int the timeout after the callback should be executed + defaults to 0 + @_undoCallback function the function which should be executed when + an command has been canceled. Usually this will add back a deleted + object back to the interface, defaults to an empty function + */ + + this._executeAll(); + command = { + _undoCallback: this._undoCallback || (this._undoCallback = function() {}), + _callback: this._callback, + execute: function() { + return command._callback(); + }, + undo: function() { + command._undoCallback(); + _this._$timeout.cancel(command.promise); + return _this._queue = []; + }, + promise: this._$timeout(function() { + command.execute(); + return _this._$rootScope.$broadcast('notUndone'); + }, this._timeout) + }; + data = { + undoCallback: command.undo, + caption: this._caption + }; + this._$rootScope.$broadcast('undoMessage', data); + return this._queue.push(command); + }; + + UndoQueue.prototype._executeAll = function() { + /* + Executes the callback before the timeout has run out + This is useful to execute all remaining commands if a new command is + added + */ + + var command, _i, _len, _ref; + + _ref = this._queue; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + command = _ref[_i]; + this._$timeout.cancel(command.promise); + command.execute(); + } + return this._queue = []; + }; + + return UndoQueue; + + })(); + return new UndoQueue($timeout, $rootScope); + } + ]); + +}).call(this); + +// Generated by CoffeeScript 1.6.2 +/* + ownCloud - News @author Bernhard Posselt diff --git a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee index 2bb37c023..4f7e8f8b3 100644 --- a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee +++ b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee @@ -44,16 +44,20 @@ describe 'FeedBusinessLayer', -> beforeEach inject (@FeedBusinessLayer, @FeedModel, @ItemModel, @FeedType, - @ShowAll, @ActiveFeed, @_ExistsError) => + @ShowAll, @ActiveFeed, @_ExistsError, @$timeout) => @ShowAll.setShowAll(false) @ActiveFeed.handle({type: @FeedType.Folder, id:0}) it 'should delete feeds', => - @FeedModel.removeById = jasmine.createSpy('remove') + @FeedModel.removeById = jasmine.createSpy('remove').andCallFake -> + return {id: 3, title: 'test'} @persistence.deleteFeed = jasmine.createSpy('deletequery') @FeedBusinessLayer.delete(3) expect(@FeedModel.removeById).toHaveBeenCalledWith(3) + + @$timeout.flush() + expect(@persistence.deleteFeed).toHaveBeenCalledWith(3) diff --git a/js/tests/services/businesslayer/folderbusinesslayerSpec.coffee b/js/tests/services/businesslayer/folderbusinesslayerSpec.coffee index f0241979f..7179218c2 100644 --- a/js/tests/services/businesslayer/folderbusinesslayerSpec.coffee +++ b/js/tests/services/businesslayer/folderbusinesslayerSpec.coffee @@ -39,15 +39,17 @@ describe 'FolderBusinessLayer', -> beforeEach inject (@FolderBusinessLayer, @FolderModel, @FeedModel, @ShowAll, - @ActiveFeed, @FeedType, @_ExistsError) => + @ActiveFeed, @FeedType, @_ExistsError, @$timeout) => @ShowAll.setShowAll(false) @ActiveFeed.handle({type: @FeedType.Feed, id:0}) it 'should delete folders', => - @FolderModel.removeById = jasmine.createSpy('remove') + @FolderModel.removeById = jasmine.createSpy('remove').andCallFake -> + return {id: 3, name: 'test'} @persistence.deleteFolder = jasmine.createSpy('deletequery') @FolderBusinessLayer.delete(3) + @$timeout.flush() expect(@FolderModel.removeById).toHaveBeenCalledWith(3) expect(@persistence.deleteFolder).toHaveBeenCalledWith(3) diff --git a/js/tests/services/undoqueueSpec.coffee b/js/tests/services/undoqueueSpec.coffee new file mode 100644 index 000000000..dcb95e9fd --- /dev/null +++ b/js/tests/services/undoqueueSpec.coffee @@ -0,0 +1,59 @@ +### + +ownCloud - App Framework + +@author Bernhard Posselt +@copyright 2012 Bernhard Posselt nukeawhale@gmail.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +License as published by the Free Software Foundation; either +version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU AFFERO GENERAL PUBLIC LICENSE for more details. + +You should have received a copy of the GNU Affero General Public +License along with this library. If not, see . + +### + +describe 'UndoQueue', -> + + beforeEach module 'News' + + + beforeEach inject (@UndoQueue, @$timeout, @$rootScope) => + @queue = @UndoQueue + + + it 'should execute a callback', => + executed = false + callback = -> + executed = true + + @queue.add('hi', callback, 3000) + + @$timeout.flush() + + expect(executed).toBe(true) + + + it 'should execute a task when a new one is added', => + executed = 0 + undone = 0 + callback = -> + executed += 1 + + undoCallback = -> + undone += 1 + + @queue.add('hi', callback, 3000, undoCallback) + @queue.add('hi', callback, 3000, undoCallback) + + expect(executed).toBe(1) + expect(undone).toBe(0) + + -- cgit v1.2.3