summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--appinfo/routes.php1
-rw-r--r--controller/foldercontroller.php24
-rw-r--r--js/app/Run.js3
-rw-r--r--js/build/app.js181
-rw-r--r--js/controller/NavigationController.js7
-rw-r--r--js/directive/NewsDraggable.js22
-rw-r--r--js/directive/NewsDroppable.js34
-rw-r--r--js/service/FeedResource.js106
-rw-r--r--js/service/FolderResource.js84
-rw-r--r--js/tests/unit/controller/NavigationControllerSpec.js13
-rw-r--r--js/tests/unit/service/FeedResourceSpec.js103
-rw-r--r--js/tests/unit/service/FolderResourceSpec.js133
-rw-r--r--templates/main.php4
-rw-r--r--templates/part.listfeed.php13
-rw-r--r--templates/part.listfolder.php18
-rw-r--r--tests/unit/controller/FolderControllerTest.php58
16 files changed, 711 insertions, 93 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 50b071302..3ca61814a 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -32,7 +32,6 @@ $application->registerRoutes($this, ['routes' => [
['name' => 'folder#rename', 'url' => '/folders/{folderId}/rename', 'verb' => 'POST'],
['name' => 'folder#read', 'url' => '/folders/{folderId}/read', 'verb' => 'POST'],
['name' => 'folder#open', 'url' => '/folders/{folderId}/open', 'verb' => 'POST'],
- ['name' => 'folder#collapse', 'url' => '/folders/{folderId}/collapse', 'verb' => 'POST'],
// feeds
['name' => 'feed#index', 'url' => '/feeds', 'verb' => 'GET'],
diff --git a/controller/foldercontroller.php b/controller/foldercontroller.php
index 1137a2528..576fee422 100644
--- a/controller/foldercontroller.php
+++ b/controller/foldercontroller.php
@@ -57,33 +57,15 @@ class FolderController extends Controller {
}
- private function setOpened($isOpened, $folderId) {
- $this->folderService->open($folderId, $isOpened, $this->userId);
- }
-
-
- /**
- * @NoAdminRequired
- *
- * @param int $folderId
- */
- public function open($folderId) {
- try {
- $this->setOpened(true, $folderId);
- } catch(ServiceNotFoundException $ex) {
- return $this->error($ex, Http::STATUS_NOT_FOUND);
- }
- }
-
-
/**
* @NoAdminRequired
*
* @param int $folderId
+ * @param bool $open
*/
- public function collapse($folderId) {
+ public function open($folderId, $open) {
try {
- $this->setOpened(false, $folderId);
+ $this->folderService->open($folderId, $open, $this->userId);
} catch(ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND);
}
diff --git a/js/app/Run.js b/js/app/Run.js
index e119f0464..cdb2ba6d0 100644
--- a/js/app/Run.js
+++ b/js/app/Run.js
@@ -54,8 +54,7 @@ app.run(($rootScope, $location, $http, $q, $interval, Loading, ItemResource,
}
// only redirect if url is empty or faulty
- // TODO check for faulty url
- if (path === '') {
+ if (!/^\/items(\/(starred|feeds\/\d+|folders\/\d+))?$/.test(path)) {
$location.path(url);
}
diff --git a/js/build/app.js b/js/build/app.js
index d6355a108..c482c3fb4 100644
--- a/js/build/app.js
+++ b/js/build/app.js
@@ -132,7 +132,7 @@ var $__build_47_app__ = function () {
default:
url = '/items';
}
- if (path === '') {
+ if (!/^\/items(\/(starred|feeds\/\d+|folders\/\d+))?$/.test(path)) {
$location.path(url);
}
activeFeedDeferred.resolve();
@@ -299,6 +299,8 @@ var $__build_47_app__ = function () {
'SettingsResource',
function (FeedResource, FolderResource, ItemResource, SettingsResource) {
'use strict';
+ this.feedError = '';
+ this.folderError = '';
this.getFeeds = function () {
return FeedResource.getAll();
};
@@ -329,6 +331,9 @@ var $__build_47_app__ = function () {
this.isShowAll = function () {
return SettingsResource.get('showAll');
};
+ this.getFeedsOfFolder = function (folderId) {
+ return FeedResource.getByFolderId(folderId);
+ };
this.createFeed = function () {
console.log('TBD');
};
@@ -418,12 +423,15 @@ var $__build_47_app__ = function () {
this.ids = {};
this.unreadCount = 0;
this.folderUnreadCount = {};
+ this.folderIds = {};
+ this.deleted = null;
};
var $FeedResource = FeedResource;
$traceurRuntime.createClass(FeedResource, {
receive: function (data) {
$traceurRuntime.superCall(this, $FeedResource.prototype, 'receive', [data]);
this.updateUnreadCache();
+ this.updateFolderCache();
},
updateUnreadCache: function () {
var $__14, $__15, $__16, $__17, $__18;
@@ -446,16 +454,34 @@ var $__build_47_app__ = function () {
}
}
},
+ updateFolderCache: function () {
+ this.folderIds = {};
+ for (var $__3 = this.values[$traceurRuntime.toProperty(Symbol.iterator)](), $__4; !($__4 = $__3.next()).done;) {
+ try {
+ throw undefined;
+ } catch (feed) {
+ feed = $__4.value;
+ {
+ $traceurRuntime.setProperty(this.folderIds, feed.folderId, this.folderIds[$traceurRuntime.toProperty(feed.folderId)] || []);
+ this.folderIds[$traceurRuntime.toProperty(feed.folderId)].push(feed);
+ }
+ }
+ }
+ },
add: function (value) {
$traceurRuntime.superCall(this, $FeedResource.prototype, 'add', [value]);
if (value.id !== undefined) {
$traceurRuntime.setProperty(this.ids, value.id, this.hashMap[$traceurRuntime.toProperty(value.url)]);
}
},
- delete: function (id) {
- var feed = this.get(id);
+ delete: function (url) {
+ var feed = this.get(url);
+ this.deleted = feed;
delete this.ids[$traceurRuntime.toProperty(feed.id)];
- $traceurRuntime.superCall(this, $FeedResource.prototype, 'delete', [id]);
+ $traceurRuntime.superCall(this, $FeedResource.prototype, 'delete', [url]);
+ this.updateUnreadCache();
+ this.updateFolderCache();
+ return this.http.delete(this.BASE_URL + '/feeds/' + feed.id);
},
markRead: function () {
for (var $__3 = this.values[$traceurRuntime.toProperty(Symbol.iterator)](), $__4; !($__4 = $__3.next()).done;) {
@@ -518,12 +544,61 @@ var $__build_47_app__ = function () {
return this.folderUnreadCount[$traceurRuntime.toProperty(folderId)] || 0;
},
getByFolderId: function (folderId) {
- return this.values.filter(function (v) {
- return v.folderId === folderId;
- });
+ return this.folderIds[$traceurRuntime.toProperty(folderId)] || [];
},
getById: function (feedId) {
return this.ids[$traceurRuntime.toProperty(feedId)];
+ },
+ rename: function (url, name) {
+ var feed = this.get(url);
+ feed.title = name;
+ return this.http({
+ method: 'POST',
+ url: this.BASE_URL + '/feeds/' + feed.id + '/rename',
+ data: { feedTitle: name }
+ });
+ },
+ move: function (url, folderId) {
+ var feed = this.get(url);
+ feed.folderId = folderId;
+ this.updateFolderCache();
+ return this.http({
+ method: 'POST',
+ url: this.BASE_URL + '/feeds/' + feed.id + '/move',
+ data: { parentFolderId: folderId }
+ });
+ },
+ create: function (url, folderId) {
+ var title = arguments[2] !== void 0 ? arguments[2] : null;
+ if (title) {
+ title = title.toUpperCase();
+ }
+ var feed = {
+ url: url,
+ folderId: folderId,
+ title: title
+ };
+ if (!this.get(url)) {
+ this.add(feed);
+ }
+ this.updateFolderCache();
+ return this.http({
+ method: 'POST',
+ url: this.BASE_URL + '/feeds',
+ data: {
+ url: url,
+ parentFolderId: folderId,
+ title: title
+ }
+ });
+ },
+ undoDelete: function () {
+ if (this.deleted) {
+ this.add(this.deleted);
+ return this.http.post(this.BASE_URL + '/feeds/' + this.deleted.id + '/restore');
+ }
+ this.updateFolderCache();
+ this.updateUnreadCache();
}
}, {}, Resource);
return new FeedResource($http, BASE_URL);
@@ -541,9 +616,65 @@ var $__build_47_app__ = function () {
BASE_URL,
'name'
]);
+ this.deleted = null;
};
var $FolderResource = FolderResource;
- $traceurRuntime.createClass(FolderResource, {}, {}, Resource);
+ $traceurRuntime.createClass(FolderResource, {
+ delete: function (folderName) {
+ var folder = this.get(folderName);
+ this.deleted = folder;
+ $traceurRuntime.superCall(this, $FolderResource.prototype, 'delete', [folderName]);
+ return this.http.delete(this.BASE_URL + '/folders/' + folder.id);
+ },
+ toggleOpen: function (folderName) {
+ var folder = this.get(folderName);
+ folder.opened = !folder.opened;
+ return this.http({
+ url: this.BASE_URL + '/folders/' + folder.id + '/open',
+ method: 'POST',
+ data: {
+ folderId: folder.id,
+ open: folder.opened
+ }
+ });
+ },
+ rename: function (folderName, toFolderName) {
+ toFolderName = toFolderName.toUpperCase();
+ var folder = this.get(folderName);
+ if (!this.get(toFolderName)) {
+ folder.name = toFolderName;
+ delete this.hashMap[$traceurRuntime.toProperty(folderName)];
+ $traceurRuntime.setProperty(this.hashMap, toFolderName, folder);
+ }
+ return this.http({
+ url: this.BASE_URL + '/folders/' + folder.id + '/rename',
+ method: 'POST',
+ data: { folderName: toFolderName }
+ });
+ },
+ create: function (folderName) {
+ folderName = folderName.toUpperCase();
+ if (!this.get(folderName)) {
+ try {
+ throw undefined;
+ } catch (folder) {
+ folder = { name: folderName };
+ this.add(folder);
+ }
+ }
+ return this.http({
+ url: this.BASE_URL + '/folders',
+ method: 'POST',
+ data: { folderName: folderName }
+ });
+ },
+ undoDelete: function () {
+ if (this.deleted) {
+ this.add(this.deleted);
+ return this.http.post(this.BASE_URL + '/folders/' + this.deleted.id + '/restore');
+ }
+ }
+ }, {}, Resource);
return new FolderResource($http, BASE_URL);
}
]);
@@ -1383,6 +1514,40 @@ var $__build_47_app__ = function () {
});
};
});
+ app.directive('newsDraggable', function () {
+ 'use strict';
+ return function (scope, elem, attr) {
+ var options = scope.$eval(attr.newsDraggable);
+ if (angular.isDefined(options)) {
+ elem.draggable(options);
+ } else {
+ elem.draggable();
+ }
+ };
+ });
+ app.directive('newsDroppable', [
+ '$rootScope',
+ function ($rootScope) {
+ 'use strict';
+ return function (scope, elem, attr) {
+ var details = {
+ accept: '.feed',
+ hoverClass: 'drag-and-drop',
+ greedy: true,
+ drop: function (event, ui) {
+ $('.drag-and-drop').removeClass('drag-and-drop');
+ var data = {
+ folderId: parseInt(elem.data('id'), 10),
+ feedId: parseInt($(ui.draggable).data('id'), 10)
+ };
+ $rootScope.$broadcast('moveFeedToFolder', data);
+ scope.$apply(attr.droppable);
+ }
+ };
+ elem.droppable(details);
+ };
+ }
+ ]);
app.directive('newsReadFile', function () {
'use strict';
return function (scope, elem, attr) {
diff --git a/js/controller/NavigationController.js b/js/controller/NavigationController.js
index 08443191b..e6cb14a93 100644
--- a/js/controller/NavigationController.js
+++ b/js/controller/NavigationController.js
@@ -11,6 +11,9 @@ app.controller('NavigationController',
function (FeedResource, FolderResource, ItemResource, SettingsResource) {
'use strict';
+ this.feedError = '';
+ this.folderError = '';
+
this.getFeeds = () => {
return FeedResource.getAll();
};
@@ -41,6 +44,10 @@ function (FeedResource, FolderResource, ItemResource, SettingsResource) {
return SettingsResource.get('showAll');
};
+ this.getFeedsOfFolder = (folderId) => {
+ return FeedResource.getByFolderId(folderId);
+ };
+
// TBD
this.createFeed = () => {
console.log('TBD');
diff --git a/js/directive/NewsDraggable.js b/js/directive/NewsDraggable.js
new file mode 100644
index 000000000..76360ecb7
--- /dev/null
+++ b/js/directive/NewsDraggable.js
@@ -0,0 +1,22 @@
+/**
+ * ownCloud - News
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Bernhard Posselt <dev@bernhard-posselt.com>
+ * @copyright Bernhard Posselt 2014
+ */
+app.directive('newsDraggable', () => {
+ 'use strict';
+
+ return (scope, elem, attr) => {
+ let options = scope.$eval(attr.newsDraggable);
+
+ if (angular.isDefined(options)) {
+ elem.draggable(options);
+ } else {
+ elem.draggable();
+ }
+ };
+}); \ No newline at end of file
diff --git a/js/directive/NewsDroppable.js b/js/directive/NewsDroppable.js
new file mode 100644
index 000000000..a68f26444
--- /dev/null
+++ b/js/directive/NewsDroppable.js
@@ -0,0 +1,34 @@
+/**
+ * ownCloud - News
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Bernhard Posselt <dev@bernhard-posselt.com>
+ * @copyright Bernhard Posselt 2014
+ */
+app.directive('newsDroppable', ($rootScope) => {
+ 'use strict';
+
+ return (scope, elem, attr) => {
+ let details = {
+ accept: '.feed',
+ hoverClass: 'drag-and-drop',
+ greedy: true,
+ drop: (event, ui) => {
+
+ $('.drag-and-drop').removeClass('drag-and-drop');
+
+ let data = {
+ folderId: parseInt(elem.data('id'), 10),
+ feedId: parseInt($(ui.draggable).data('id'), 10)
+ };
+
+ $rootScope.$broadcast('moveFeedToFolder', data);
+ scope.$apply(attr.droppable);
+ }
+ };
+
+ elem.droppable(details);
+ };
+}); \ No newline at end of file
diff --git a/js/service/FeedResource.js b/js/service/FeedResource.js
index ab5aec9b4..9759724ac 100644
--- a/js/service/FeedResource.js
+++ b/js/service/FeedResource.js
@@ -17,12 +17,15 @@ app.factory('FeedResource', (Resource, $http, BASE_URL) => {
this.ids = {};
this.unreadCount = 0;
this.folderUnreadCount = {};
+ this.folderIds = {};
+ this.deleted = null;
}
receive (data) {
super.receive(data);
this.updateUnreadCache();
+ this.updateFolderCache();
}
@@ -43,6 +46,17 @@ app.factory('FeedResource', (Resource, $http, BASE_URL) => {
}
+ updateFolderCache () {
+ this.folderIds = {};
+
+ for (let feed of this.values) {
+ this.folderIds[feed.folderId] =
+ this.folderIds[feed.folderId] || [];
+ this.folderIds[feed.folderId].push(feed);
+ }
+ }
+
+
add (value) {
super.add(value);
if (value.id !== undefined) {
@@ -51,10 +65,17 @@ app.factory('FeedResource', (Resource, $http, BASE_URL) => {
}
- delete (id) {
- let feed = this.get(id);
+ delete (url) {
+ let feed = this.get(url);
+ this.deleted = feed;
delete this.ids[feed.id];
- super.delete(id);
+
+ super.delete(url);
+
+ this.updateUnreadCache();
+ this.updateFolderCache();
+
+ return this.http.delete(`${this.BASE_URL}/feeds/${feed.id}`);
}
@@ -114,12 +135,89 @@ app.factory('FeedResource', (Resource, $http, BASE_URL) => {
getByFolderId (folderId) {
- return this.values.filter(v => v.folderId === folderId);
+ return this.folderIds[folderId] || [];
}
+
getById (feedId) {
return this.ids[feedId];
}
+
+
+ rename (url, name) {
+ let feed = this.get(url);
+ feed.title = name;
+
+ return this.http({
+ method: 'POST',
+ url: `${this.BASE_URL}/feeds/${feed.id}/rename`,
+ data: {
+ feedTitle: name
+ }
+ });
+ }
+
+
+ move (url, folderId) {
+ let feed = this.get(url);
+ feed.folderId = folderId;
+
+ this.updateFolderCache();
+
+ return this.http({
+ method: 'POST',
+ url: `${this.BASE_URL}/feeds/${feed.id}/move`,
+ data: {
+ parentFolderId: folderId
+ }
+ });
+
+ }
+
+
+ create (url, folderId, title=null) {
+ if (title) {
+ title = title.toUpperCase();
+ }
+
+ let feed = {
+ url: url,
+ folderId: folderId,
+ title: title
+ };
+
+ if (!this.get(url)) {
+ this.add(feed);
+ }
+
+ this.updateFolderCache();
+
+ return this.http({
+ method: 'POST',
+ url: `${this.BASE_URL}/feeds`,
+ data: {
+ url: url,
+ parentFolderId: folderId,
+ title: title
+ }
+ });
+ }
+
+
+ undoDelete () {
+ if (this.deleted) {
+ this.add(this.deleted);
+
+ return this.http.post(
+ `${this.BASE_URL}/feeds/${this.deleted.id}/restore`
+ );
+ }
+
+ this.updateFolderCache();
+ this.updateUnreadCache();
+ }
+
+
}
return new FeedResource($http, BASE_URL);
diff --git a/js/service/FolderResource.js b/js/service/FolderResource.js
index 1ea48e0bb..2e67fa690 100644
--- a/js/service/FolderResource.js
+++ b/js/service/FolderResource.js
@@ -14,8 +14,92 @@ app.factory('FolderResource', (Resource, $http, BASE_URL) => {
constructor ($http, BASE_URL) {
super($http, BASE_URL, 'name');
+ this.deleted = null;
}
+
+ delete (folderName) {
+ let folder = this.get(folderName);
+ this.deleted = folder;
+
+ super.delete(folderName);
+
+ return this.http.delete(`${this.BASE_URL}/folders/${folder.id}`);
+ }
+
+
+ toggleOpen (folderName) {
+ let folder = this.get(folderName);
+ folder.opened = !folder.opened;
+
+ return this.http({
+ url: `${this.BASE_URL}/folders/${folder.id}/open`,
+ method: 'POST',
+ data: {
+ folderId: folder.id,
+ open: folder.opened
+ }
+ });
+ }
+
+
+ rename (folderName, toFolderName) {
+ toFolderName = toFolderName.toUpperCase();
+ let folder = this.get(folderName);
+
+ // still do http request if folder exists but dont change the name
+ // to have one point of failure
+ if (!this.get(toFolderName)) {
+ folder.name = toFolderName;
+
+ delete this.hashMap[folderName];
+ this.hashMap[toFolderName] = folder;
+ }
+
+ return this.http({
+ url: `${this.BASE_URL}/folders/${folder.id}/rename`,
+ method: 'POST',
+ data: {
+ folderName: toFolderName
+ }
+ });
+ }
+
+
+ create (folderName) {
+ folderName = folderName.toUpperCase();
+
+ // still do http request if folder exists but dont change the name
+ // to have one point of failure
+ if (!this.get(folderName)) {
+ let folder = {
+ name: folderName
+ };
+
+ this.add(folder);
+ }
+
+ return this.http({
+ url: `${this.BASE_URL}/folders`,
+ method: 'POST',
+ data: {
+ folderName: folderName
+ }
+ });
+ }
+
+
+ undoDelete () {
+ if (this.deleted) {
+ this.add(this.deleted);
+
+ return this.http.post(
+ `${this.BASE_URL}/folders/${this.deleted.id}/restore`
+ );
+ }
+ }
+
+
}
return new FolderResource($http, BASE_URL);
diff --git a/js/tests/unit/controller/NavigationControllerSpec.js b/js/tests/unit/controller/NavigationControllerSpec.js
index 433a40e3f..adefd157f 100644
--- a/js/tests/unit/controller/NavigationControllerSpec.js
+++ b/js/tests/unit/controller/NavigationControllerSpec.js
@@ -111,6 +111,19 @@ describe('NavigationController', () => {
SettingsResource.set('showAll', true);
expect(ctrl.isShowAll()).toBe(true);
+ }));
+
+ it('should get all of folder', inject((FeedResource, $controller) => {
+ let ctrl = $controller('NavigationController', {
+ FeedResource: FeedResource,
+ });
+
+ FeedResource.getByFolderId = jasmine.createSpy('getByFolderId');
+ ctrl.getFeedsOfFolder(3);
+
+ expect(FeedResource.getByFolderId).toHaveBeenCalledWith(3);
}));
+
+
}); \ No newline at end of file
diff --git a/js/tests/unit/service/FeedResourceSpec.js b/js/tests/unit/service/FeedResourceSpec.js
index 5187435f0..a37ff42f3 100644
--- a/js/tests/unit/service/FeedResourceSpec.js
+++ b/js/tests/unit/service/FeedResourceSpec.js
@@ -10,19 +10,21 @@
describe('FeedResource', () => {
'use strict';
- let resource;
+ let resource,
+ http;
beforeEach(module('News', ($provide) => {
$provide.value('BASE_URL', 'base');
}));
- beforeEach(inject((FeedResource) => {
+ beforeEach(inject((FeedResource, $httpBackend) => {
resource = FeedResource;
+ http = $httpBackend;
FeedResource.receive([
{id: 1, folderId: 3, url: 'ye', unreadCount: 45},
{id: 2, folderId: 4, url: 'sye', unreadCount: 25},
- {id: 3, folderId: 3, url: '1sye', unreadCount: 0}
+ {id: 3, folderId: 3, title: 'hore', url: '1sye', unreadCount: 0}
]);
}));
@@ -104,4 +106,99 @@ describe('FeedResource', () => {
expect(FeedResource.getUnreadCount()).toBe(68);
}));
+
+
+ it ('should delete a feed', inject((FeedResource) => {
+ http.expectDELETE('base/feeds/1').respond(200, {});
+
+ FeedResource.delete('ye');
+
+ http.flush();
+
+ expect(FeedResource.size()).toBe(2);
+ }));
+
+
+ it ('should rename a feed', inject((FeedResource) => {
+ http.expectPOST('base/feeds/3/rename', {
+ feedTitle: 'heho'
+ }).respond(200, {});
+
+ FeedResource.rename('1sye', 'heho');
+
+ http.flush();
+
+ expect(FeedResource.get('1sye').title).toBe('heho');
+ }));
+
+
+ it ('should move a feed', inject((FeedResource) => {
+ http.expectPOST('base/feeds/3/move', {
+ parentFolderId: 5
+ }).respond(200, {});
+
+ FeedResource.move('1sye', 5);
+
+ http.flush();
+
+ expect(FeedResource.get('1sye').folderId).toBe(5);
+ }));
+
+
+ it ('should create a feed', inject((FeedResource) => {
+ http.expectPOST('base/feeds', {
+ parentFolderId: 5,
+ url: 'hey',
+ title: 'ABC'
+ }).respond(200, {});
+
+ FeedResource.create('hey', 5, 'abc');
+
+ http.flush();
+
+ expect(FeedResource.get('hey').folderId).toBe(5);
+ }));
+
+
+ it ('should not create a feed if it exists', inject((FeedResource) => {
+ http.expectPOST('base/feeds', {
+ parentFolderId: 5,
+ url: 'ye',
+ title: 'ABC'
+ }).respond(200, {});
+
+ FeedResource.create('ye', 5, 'abc');
+
+ http.flush();
+
+ expect(FeedResource.size()).toBe(3);
+ }));
+
+
+ it ('should undo a delete folder', inject((FeedResource) => {
+ http.expectDELETE('base/feeds/1').respond(200, {});
+
+ FeedResource.delete('ye');
+
+ http.flush();
+
+
+ http.expectPOST('base/feeds/1/restore').respond(200, {});
+
+ FeedResource.undoDelete();
+
+ http.flush();
+
+ expect(FeedResource.get('ye').id).toBe(1);
+ }));
+
+
+
+
+ afterEach(() => {
+ http.verifyNoOutstandingExpectation();
+ http.verifyNoOutstandingRequest();
+ });
+
+
});
diff --git a/js/tests/unit/service/FolderResourceSpec.js b/js/tests/unit/service/FolderResourceSpec.js
new file mode 100644
index 000000000..db8312232
--- /dev/null
+++ b/js/tests/unit/service/FolderResourceSpec.js
@@ -0,0 +1,133 @@
+/**
+ * ownCloud - News
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Bernhard Posselt <dev@bernhard-posselt.com>
+ * @copyright Bernhard Posselt 2014
+ */
+describe('FolderResource', () => {
+ 'use strict';
+
+ let resource,
+ http;
+
+ beforeEach(module('News', ($provide) => {
+ $provide.value('BASE_URL', 'base');
+ }));
+
+
+ beforeEach(inject((FolderResource, $httpBackend) => {
+ resource = FolderResource;
+ http = $httpBackend;
+ FolderResource.receive([
+ {id: 1, name: 'ye'},
+ {id: 2, name: 'SYE'},
+ {id: 3, name: 'hore', opened: true}
+ ]);
+ }));
+
+
+ it ('should delete a folder', inject((FolderResource) => {
+ http.expectDELETE('base/folders/1').respond(200, {});
+
+ FolderResource.delete('ye');
+
+ http.flush();
+
+ expect(FolderResource.size()).toBe(2);
+ }));
+
+
+ it ('should rename a folder', inject((FolderResource) => {
+ http.expectPOST('base/folders/1/rename', {
+ folderName: 'HEHO'
+ }).respond(200, {});
+
+ FolderResource.rename('ye', 'heho');
+
+ http.flush();
+
+ expect(FolderResource.get('HEHO').id).toBe(1);
+ }));
+
+
+ it ('should not rename a folder if it exists', inject((FolderResource) => {
+ http.expectPOST('base/folders/1/rename', {
+ folderName: 'SYE'
+ }).respond(200, {});
+
+ FolderResource.rename('ye', 'sye');
+
+ http.flush();
+
+ expect(FolderResource.get('ye').id).toBe(1);
+ }));
+
+
+ it ('should open a folder', inject((FolderResource) => {
+ http.expectPOST('base/folders/3/open', {
+ folderId: 3,
+ open: false,
+ }).respond(200, {});
+
+ FolderResource.toggleOpen('hore');
+
+ http.flush();
+
+ expect(FolderResource.get('hore').opened).toBe(false);
+ }));
+
+
+ it ('should create a folder', inject((FolderResource) => {
+ http.expectPOST('base/folders', {
+ folderName: 'HEY'
+ }).respond(200, {});
+
+ FolderResource.create('hey');
+
+ http.flush();
+
+ expect(FolderResource.size()).toBe(4);
+ }));
+
+
+ it ('should not create a folder if it exists', inject((FolderResource) => {
+ http.expectPOST('base/folders', {
+ folderName: 'SYE'
+ }).respond(200, {});
+
+ FolderResource.create('SYE');
+
+ http.flush();
+
+ expect(FolderResource.size()).toBe(3);
+ }));
+
+
+ it ('should undo a delete folder', inject((FolderResource) => {
+ http.expectDELETE('base/folders/1').respond(20