diff options
-rw-r--r-- | apps/files/js/filelist.js | 9 | ||||
-rw-r--r-- | apps/files/tests/js/filelistSpec.js | 114 | ||||
-rw-r--r-- | core/js/files/client.js | 7 | ||||
-rw-r--r-- | core/js/files/fileinfo.js | 7 | ||||
-rw-r--r-- | tests/acceptance/features/app-files.feature | 19 | ||||
-rw-r--r-- | tests/acceptance/features/bootstrap/FilesAppContext.php | 86 |
6 files changed, 227 insertions, 15 deletions
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index b1e7c3f5f8c..086e148e102 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1566,11 +1566,16 @@ this._sort = sort; this._sortDirection = (direction === 'desc')?'desc':'asc'; this._sortComparator = function(fileInfo1, fileInfo2) { - if(fileInfo1.isFavorite && !fileInfo2.isFavorite) { + var isFavorite = function(fileInfo) { + return fileInfo.tags && fileInfo.tags.indexOf(OC.TAG_FAVORITE) >= 0; + }; + + if (isFavorite(fileInfo1) && !isFavorite(fileInfo2)) { return -1; - } else if(!fileInfo1.isFavorite && fileInfo2.isFavorite) { + } else if (!isFavorite(fileInfo1) && isFavorite(fileInfo2)) { return 1; } + return direction === 'asc' ? comparator(fileInfo1, fileInfo2) : -comparator(fileInfo1, fileInfo2); }; diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index b7ee9c8554e..ddd9a45d153 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -2476,6 +2476,120 @@ describe('OCA.Files.FileList tests', function() { sortStub.restore(); }); + describe('with favorites', function() { + it('shows favorite files on top', function() { + testFiles.push(new FileInfo({ + id: 5, + type: 'file', + name: 'ZZY Before last file in ascending order', + mimetype: 'text/plain', + mtime: 999999998, + size: 9999998, + // Tags would be added by TagsPlugin + tags: [OC.TAG_FAVORITE], + }), new FileInfo({ + id: 6, + type: 'file', + name: 'ZZZ Last file in ascending order', + mimetype: 'text/plain', + mtime: 999999999, + size: 9999999, + // Tags would be added by TagsPlugin + tags: [OC.TAG_FAVORITE], + })); + + fileList.setFiles(testFiles); + + // Sort by name in ascending order (default sorting is by name + // in ascending order, but setFiles does not trigger a sort, so + // the files must be sorted before being set or a sort must be + // triggered afterwards by clicking on the header). + fileList.$el.find('.column-name .columntitle').click(); + fileList.$el.find('.column-name .columntitle').click(); + + expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); + expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); + expect(fileList.findFileEl('somedir').index()).toEqual(2); + expect(fileList.findFileEl('One.txt').index()).toEqual(3); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(5); + + // Sort by size in ascending order + fileList.$el.find('.column-size .columntitle').click(); + fileList.$el.find('.column-size .columntitle').click(); + + expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); + expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); + expect(fileList.findFileEl('One.txt').index()).toEqual(2); + expect(fileList.findFileEl('somedir').index()).toEqual(3); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(4); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(5); + + // Sort by modification time in ascending order + fileList.$el.find('.column-mtime .columntitle').click(); + fileList.$el.find('.column-mtime .columntitle').click(); + + expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); + expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); + expect(fileList.findFileEl('One.txt').index()).toEqual(2); + expect(fileList.findFileEl('somedir').index()).toEqual(3); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(5); + }); + it('shows favorite files on top also when using descending order', function() { + testFiles.push(new FileInfo({ + id: 5, + type: 'file', + name: 'AAB Before last file in descending order', + mimetype: 'text/plain', + mtime: 2, + size: 2, + // Tags would be added by TagsPlugin + tags: [OC.TAG_FAVORITE], + }), new FileInfo({ + id: 6, + type: 'file', + name: 'AAA Last file in descending order', + mimetype: 'text/plain', + mtime: 1, + size: 1, + // Tags would be added by TagsPlugin + tags: [OC.TAG_FAVORITE], + })); + + fileList.setFiles(testFiles); + + // Sort by name in descending order + fileList.$el.find('.column-name .columntitle').click(); + + expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); + expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(3); + expect(fileList.findFileEl('One.txt').index()).toEqual(4); + expect(fileList.findFileEl('somedir').index()).toEqual(5); + + // Sort by size in descending order + fileList.$el.find('.column-size .columntitle').click(); + + expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); + expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(2); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(3); + expect(fileList.findFileEl('somedir').index()).toEqual(4); + expect(fileList.findFileEl('One.txt').index()).toEqual(5); + + // Sort by modification time in descending order + fileList.$el.find('.column-mtime .columntitle').click(); + + expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); + expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(3); + expect(fileList.findFileEl('somedir').index()).toEqual(4); + expect(fileList.findFileEl('One.txt').index()).toEqual(5); + }); + }); }); describe('create file', function() { var deferredCreate; diff --git a/core/js/files/client.js b/core/js/files/client.js index da8a1205e4b..d8e615f6d6d 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -304,13 +304,6 @@ data.hasPreview = true; } - var isFavorite = props['{' + Client.NS_OWNCLOUD + '}favorite']; - if (!_.isUndefined(isFavorite)) { - data.isFavorite = isFavorite === '1'; - } else { - data.isFavorite = false; - } - var contentType = props[Client.PROPERTY_GETCONTENTTYPE]; if (!_.isUndefined(contentType)) { data.mimetype = contentType; diff --git a/core/js/files/fileinfo.js b/core/js/files/fileinfo.js index 7c8e4586448..1fc239da47a 100644 --- a/core/js/files/fileinfo.js +++ b/core/js/files/fileinfo.js @@ -132,12 +132,7 @@ /** * @type boolean */ - hasPreview: true, - - /** - * @type boolean - */ - isFavorite: false + hasPreview: true }; if (!OC.Files) { diff --git a/tests/acceptance/features/app-files.feature b/tests/acceptance/features/app-files.feature index 8d32508513a..c968ae53ce4 100644 --- a/tests/acceptance/features/app-files.feature +++ b/tests/acceptance/features/app-files.feature @@ -68,3 +68,22 @@ Feature: app-files And I see that the "Sharing" tab in the details view is eventually loaded When I open the input field for tags in the details view Then I see that the input field for tags in the details view is shown + + Scenario: marking a file as favorite causes the file list to be sorted again + Given I am logged in + And I create a new folder named "A name alphabetically lower than welcome.txt" + And I see that "A name alphabetically lower than welcome.txt" precedes "welcome.txt" in the file list + When I mark "welcome.txt" as favorite + Then I see that "welcome.txt" is marked as favorite + And I see that "welcome.txt" precedes "A name alphabetically lower than welcome.txt" in the file list + + Scenario: unmarking a file as favorite causes the file list to be sorted again + Given I am logged in + And I create a new folder named "A name alphabetically lower than welcome.txt" + And I see that "A name alphabetically lower than welcome.txt" precedes "welcome.txt" in the file list + And I mark "welcome.txt" as favorite + And I see that "welcome.txt" is marked as favorite + And I see that "welcome.txt" precedes "A name alphabetically lower than welcome.txt" in the file list + When I unmark "welcome.txt" as favorite + Then I see that "welcome.txt" is not marked as favorite + And I see that "A name alphabetically lower than welcome.txt" precedes "welcome.txt" in the file list diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php index 52f69c66796..631eb60393d 100644 --- a/tests/acceptance/features/bootstrap/FilesAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesAppContext.php @@ -216,6 +216,40 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ + public static function createMenuButton() { + return Locator::forThe()->css("#controls .button.new")-> + descendantOf(self::currentSectionMainView())-> + describedAs("Create menu button in Files app"); + } + + /** + * @return Locator + */ + public static function createNewFolderMenuItem() { + return self::createMenuItemFor("New folder"); + } + + /** + * @return Locator + */ + public static function createNewFolderMenuItemNameInput() { + return Locator::forThe()->css(".filenameform input")-> + descendantOf(self::createNewFolderMenuItem())-> + describedAs("Name input in create new folder menu item in Files app"); + } + + /** + * @return Locator + */ + private static function createMenuItemFor($newType) { + return Locator::forThe()->xpath("//div[contains(concat(' ', normalize-space(@class), ' '), ' newFileMenu ')]//span[normalize-space() = '$newType']/ancestor::li")-> + descendantOf(self::currentSectionMainView())-> + describedAs("Create $newType menu item in Files app"); + } + + /** + * @return Locator + */ public static function rowForFile($fileName) { return Locator::forThe()->xpath("//*[@id = 'fileList']//span[contains(concat(' ', normalize-space(@class), ' '), ' nametext ') and normalize-space() = '$fileName']/ancestor::tr")-> descendantOf(self::currentSectionMainView())-> @@ -225,6 +259,15 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ + public static function rowForFilePreceding($fileName1, $fileName2) { + return Locator::forThe()->xpath("//preceding-sibling::tr//span[contains(concat(' ', normalize-space(@class), ' '), ' nametext ') and normalize-space() = '$fileName1']/ancestor::tr")-> + descendantOf(self::rowForFile($fileName2))-> + describedAs("Row for file $fileName1 preceding $fileName2 in Files app"); + } + + /** + * @return Locator + */ public static function favoriteActionForFile($fileName) { return Locator::forThe()->css(".action-favorite")->descendantOf(self::rowForFile($fileName))-> describedAs("Favorite action for file $fileName in Files app"); @@ -233,6 +276,14 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @return Locator */ + public static function notFavoritedStateIconForFile($fileName) { + return Locator::forThe()->css(".icon-star")->descendantOf(self::favoriteActionForFile($fileName))-> + describedAs("Not favorited state icon for file $fileName in Files app"); + } + + /** + * @return Locator + */ public static function favoritedStateIconForFile($fileName) { return Locator::forThe()->css(".icon-starred")->descendantOf(self::favoriteActionForFile($fileName))-> describedAs("Favorited state icon for file $fileName in Files app"); @@ -294,6 +345,16 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @Given I create a new folder named :folderName + */ + public function iCreateANewFolderNamed($folderName) { + $this->actor->find(self::createMenuButton(), 10)->click(); + + $this->actor->find(self::createNewFolderMenuItem(), 2)->click(); + $this->actor->find(self::createNewFolderMenuItemNameInput(), 2)->setValue($folderName . "\r"); + } + + /** * @Given I open the :section section */ public function iOpenTheSection($section) { @@ -327,6 +388,17 @@ class FilesAppContext implements Context, ActorAwareInterface { * @Given I mark :fileName as favorite */ public function iMarkAsFavorite($fileName) { + $this->iSeeThatIsNotMarkedAsFavorite($fileName); + + $this->actor->find(self::favoriteActionForFile($fileName), 10)->click(); + } + + /** + * @Given I unmark :fileName as favorite + */ + public function iUnmarkAsFavorite($fileName) { + $this->iSeeThatIsMarkedAsFavorite($fileName); + $this->actor->find(self::favoriteActionForFile($fileName), 10)->click(); } @@ -414,6 +486,13 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @Then I see that :fileName1 precedes :fileName2 in the file list + */ + public function iSeeThatPrecedesInTheFileList($fileName1, $fileName2) { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::rowForFilePreceding($fileName1, $fileName2), 10)); + } + + /** * @Then I see that :fileName is marked as favorite */ public function iSeeThatIsMarkedAsFavorite($fileName) { @@ -421,6 +500,13 @@ class FilesAppContext implements Context, ActorAwareInterface { } /** + * @Then I see that :fileName is not marked as favorite + */ + public function iSeeThatIsNotMarkedAsFavorite($fileName) { + PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::notFavoritedStateIconForFile($fileName), 10)); + } + + /** * @Then I see that the input field for tags in the details view is shown */ public function iSeeThatTheInputFieldForTagsInTheDetailsViewIsShown() { |