From 0e933ee6b9d6598eec1e830b90becb8dcdd4967a Mon Sep 17 00:00:00 2001 From: Daniel Calviño Sánchez Date: Wed, 27 Sep 2017 11:17:05 +0200 Subject: Update acceptance tests to favorite files through the file actions menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently a file can be favorited either through the inline action or through the file actions menu. However, the inline action will be removed in a following commit and then it will be possible to do it only through the file actions menu. Signed-off-by: Daniel Calviño Sánchez --- .../features/bootstrap/FilesAppContext.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php index bb088c0a2c3..a2b286330fd 100644 --- a/tests/acceptance/features/bootstrap/FilesAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesAppContext.php @@ -338,6 +338,20 @@ class FilesAppContext implements Context, ActorAwareInterface { return self::fileActionsMenuItemFor("Details"); } + /** + * @return Locator + */ + public static function addToFavoritesMenuItem() { + return self::fileActionsMenuItemFor("Add to favorites"); + } + + /** + * @return Locator + */ + public static function removeFromFavoritesMenuItem() { + return self::fileActionsMenuItemFor("Remove from favorites"); + } + /** * @return Locator */ @@ -393,7 +407,9 @@ class FilesAppContext implements Context, ActorAwareInterface { public function iMarkAsFavorite($fileName) { $this->iSeeThatIsNotMarkedAsFavorite($fileName); - $this->actor->find(self::favoriteActionForFile($fileName), 10)->click(); + $this->actor->find(self::fileActionsMenuButtonForFile($fileName), 10)->click(); + + $this->actor->find(self::addToFavoritesMenuItem(), 2)->click(); } /** @@ -402,7 +418,9 @@ class FilesAppContext implements Context, ActorAwareInterface { public function iUnmarkAsFavorite($fileName) { $this->iSeeThatIsMarkedAsFavorite($fileName); - $this->actor->find(self::favoriteActionForFile($fileName), 10)->click(); + $this->actor->find(self::fileActionsMenuButtonForFile($fileName), 10)->click(); + + $this->actor->find(self::removeFromFavoritesMenuItem(), 2)->click(); } /** -- cgit v1.2.3 From 9ff0941c076c4f9c96872bdab8f97568793a8f6b Mon Sep 17 00:00:00 2001 From: Daniel Calviño Sánchez Date: Wed, 27 Sep 2017 12:39:59 +0200 Subject: Replace inline favorite action with just a favorite icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a preparatory step for a following commit in which the position of the favorite icon and the checkbox will be swapped; in that new design the favorite icon is no longer expected to be an action but just a simple mark on whether the file is favorited or not (the action is expected to be triggered then only from the file actions menu). The favorite icon is now fully shown or completely hidden depending on whether the file is favorited or not. As the icon is just informative but no longer an action now it does not change when hovered or focus. In the same way, the alternative text when the file is not favorited now it is not "Favorite" (an action) but "Not favorited" instead. Signed-off-by: Daniel Calviño Sánchez --- apps/files/css/files.scss | 19 +++- apps/files/js/tagsplugin.js | 101 +++++---------------- apps/files/tests/js/tagspluginspec.js | 77 +++------------- .../features/bootstrap/FilesAppContext.php | 10 +- 4 files changed, 60 insertions(+), 147 deletions(-) (limited to 'tests') diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 4a59502bc6d..f5cb130cfe3 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -502,7 +502,7 @@ table td.filename .uploadtext { display: inline-block; float: left; } -#fileList tr td.filename .action-favorite:not(.menuitem) { +#fileList tr td.filename .favorite-mark { display: block; float: left; width: 30px; @@ -569,7 +569,8 @@ a.action > img { margin-bottom: -1px; } -#fileList a.action { +#fileList a.action, +#fileList div.favorite-mark { display: inline; padding: 17px 8px; line-height: 50px; @@ -617,7 +618,7 @@ a.action > img { padding-left: 6px; } -#fileList .action.action-favorite.permanent { +#fileList .favorite-mark.permanent { opacity: 1; } @@ -716,12 +717,24 @@ table.dragshadow td.size { #filestable .filename .action .icon, #filestable .selectedActions a .icon, +#filestable .filename .favorite-mark .icon, #controls .actions .button .icon { display: inline-block; vertical-align: middle; background-size: 16px 16px; } +#filestable .filename .favorite-mark { + // Override default icons to always hide the star icon and always show the + // starred icon even when hovered or focused. + & .icon-star { + background-image: none; + } + & .icon-starred { + background-image: url('../../../core/img/actions/starred.svg?v=1'); + } +} + #filestable .filename .action .icon.hidden, #filestable .selectedActions a .icon.hidden, #controls .actions .button .icon.hidden { diff --git a/apps/files/js/tagsplugin.js b/apps/files/js/tagsplugin.js index 22d04e9f19f..e6724e371c8 100644 --- a/apps/files/js/tagsplugin.js +++ b/apps/files/js/tagsplugin.js @@ -17,12 +17,12 @@ PROPERTY_FAVORITE: '{' + OC.Files.Client.NS_OWNCLOUD + '}favorite' }); - var TEMPLATE_FAVORITE_ACTION = - '' + + var TEMPLATE_FAVORITE_MARK = + '
' + '' + '{{altText}}' + - ''; + '
'; /** * Returns the icon class for the matching state @@ -42,24 +42,24 @@ */ function renderStar(state) { if (!this._template) { - this._template = Handlebars.compile(TEMPLATE_FAVORITE_ACTION); + this._template = Handlebars.compile(TEMPLATE_FAVORITE_MARK); } return this._template({ isFavorite: state, - altText: state ? t('files', 'Favorited') : t('files', 'Favorite'), + altText: state ? t('files', 'Favorited') : t('files', 'Not favorited'), iconClass: getStarIconClass(state) }); } /** - * Toggle star icon on action element + * Toggle star icon on favorite mark element * - * @param {Object} action element + * @param {Object} $favoriteMarkEl favorite mark element * @param {boolean} state true if starred, false otherwise */ - function toggleStar($actionEl, state) { - $actionEl.removeClass('icon-star icon-starred').addClass(getStarIconClass(state)); - $actionEl.toggleClass('permanent', state); + function toggleStar($favoriteMarkEl, state) { + $favoriteMarkEl.removeClass('icon-star icon-starred').addClass(getStarIconClass(state)); + $favoriteMarkEl.toggleClass('permanent', state); } OCA.Files = OCA.Files || {}; @@ -67,8 +67,9 @@ /** * @namespace OCA.Files.TagsPlugin * - * Extends the file actions and file list to include a favorite action icon - * and addition "data-tags" and "data-favorite" attributes. + * Extends the file actions and file list to include a favorite mark icon + * and a favorite action in the file actions menu; it also adds "data-tags" + * and "data-favorite" attributes to file elements. */ OCA.Files.TagsPlugin = { name: 'Tags', @@ -84,63 +85,6 @@ _extendFileActions: function(fileActions) { var self = this; - // register "star" action - fileActions.registerAction({ - name: 'FavoriteInline', - displayName: t('files', 'Favorite'), - mime: 'all', - permissions: OC.PERMISSION_READ, - type: OCA.Files.FileActions.TYPE_INLINE, - render: function(actionSpec, isDefault, context) { - var $file = context.$file; - var isFavorite = $file.data('favorite') === true; - var $icon = $(renderStar(isFavorite)); - $file.find('td:first>.favorite').replaceWith($icon); - return $icon; - }, - actionHandler: function(fileName, context) { - var $actionEl = context.$file.find('.action-favorite'); - var $file = context.$file; - var fileInfo = context.fileList.files[$file.index()]; - var dir = context.dir || context.fileList.getCurrentDirectory(); - var tags = $file.attr('data-tags'); - if (_.isUndefined(tags)) { - tags = ''; - } - tags = tags.split('|'); - tags = _.without(tags, ''); - var isFavorite = tags.indexOf(OC.TAG_FAVORITE) >= 0; - if (isFavorite) { - // remove tag from list - tags = _.without(tags, OC.TAG_FAVORITE); - } else { - tags.push(OC.TAG_FAVORITE); - } - - // pre-toggle the star - toggleStar($actionEl, !isFavorite); - - context.fileInfoModel.trigger('busy', context.fileInfoModel, true); - - self.applyFileTags( - dir + '/' + fileName, - tags, - $actionEl, - isFavorite - ).then(function(result) { - context.fileInfoModel.trigger('busy', context.fileInfoModel, false); - // response from server should contain updated tags - var newTags = result.tags; - if (_.isUndefined(newTags)) { - newTags = tags; - } - context.fileInfoModel.set({ - 'tags': newTags, - 'favorite': !isFavorite - }); - }); - } - }); fileActions.registerAction({ name: 'Favorite', @@ -172,7 +116,7 @@ return 'icon-star'; }, actionHandler: function(fileName, context) { - var $actionEl = context.$file.find('.action-favorite'); + var $favoriteMarkEl = context.$file.find('.favorite-mark'); var $file = context.$file; var fileInfo = context.fileList.files[$file.index()]; var dir = context.dir || context.fileList.getCurrentDirectory(); @@ -191,14 +135,14 @@ } // pre-toggle the star - toggleStar($actionEl, !isFavorite); + toggleStar($favoriteMarkEl, !isFavorite); context.fileInfoModel.trigger('busy', context.fileInfoModel, true); self.applyFileTags( dir + '/' + fileName, tags, - $actionEl, + $favoriteMarkEl, isFavorite ).then(function(result) { context.fileInfoModel.trigger('busy', context.fileInfoModel, false); @@ -222,13 +166,16 @@ var oldCreateRow = fileList._createRow; fileList._createRow = function(fileData) { var $tr = oldCreateRow.apply(this, arguments); + var isFavorite = false; if (fileData.tags) { $tr.attr('data-tags', fileData.tags.join('|')); if (fileData.tags.indexOf(OC.TAG_FAVORITE) >= 0) { $tr.attr('data-favorite', true); + isFavorite = true; } } - $tr.find('td:first').prepend('
'); + var $icon = $(renderStar(isFavorite)); + $tr.find('td:first').prepend($icon); return $tr; }; var oldElementToFile = fileList.elementToFile; @@ -288,10 +235,10 @@ * * @param {String} fileName path to the file or folder to tag * @param {Array.} tagNames array of tag names - * @param {Object} $actionEl element + * @param {Object} $favoriteMarkEl favorite mark element * @param {boolean} isFavorite Was the item favorited before */ - applyFileTags: function(fileName, tagNames, $actionEl, isFavorite) { + applyFileTags: function(fileName, tagNames, $favoriteMarkEl, isFavorite) { var encodedPath = OC.encodePath(fileName); while (encodedPath[0] === '/') { encodedPath = encodedPath.substr(1); @@ -311,7 +258,7 @@ message = ': ' + response.responseJSON.message; } OC.Notification.show(t('files', 'An error occurred while trying to update the tags' + message), {type: 'error'}); - toggleStar($actionEl, isFavorite); + toggleStar($favoriteMarkEl, isFavorite); }); } }; diff --git a/apps/files/tests/js/tagspluginspec.js b/apps/files/tests/js/tagspluginspec.js index e2cbaa2c4d0..b76b3c02dd9 100644 --- a/apps/files/tests/js/tagspluginspec.js +++ b/apps/files/tests/js/tagspluginspec.js @@ -49,24 +49,24 @@ describe('OCA.Files.TagsPlugin tests', function() { describe('Favorites icon', function() { it('renders favorite icon and extra data', function() { - var $action, $tr; + var $favoriteMark, $tr; fileList.setFiles(testFiles); $tr = fileList.$el.find('tbody tr:first'); - $action = $tr.find('.action-favorite'); - expect($action.length).toEqual(1); - expect($action.hasClass('permanent')).toEqual(false); + $favoriteMark = $tr.find('.favorite-mark'); + expect($favoriteMark.length).toEqual(1); + expect($favoriteMark.hasClass('permanent')).toEqual(false); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2']); expect($tr.attr('data-favorite')).not.toBeDefined(); }); it('renders permanent favorite icon and extra data', function() { - var $action, $tr; + var $favoriteMark, $tr; testFiles[0].tags.push(OC.TAG_FAVORITE); fileList.setFiles(testFiles); $tr = fileList.$el.find('tbody tr:first'); - $action = $tr.find('.action-favorite'); - expect($action.length).toEqual(1); - expect($action.hasClass('permanent')).toEqual(true); + $favoriteMark = $tr.find('.favorite-mark'); + expect($favoriteMark.length).toEqual(1); + expect($favoriteMark.hasClass('permanent')).toEqual(true); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', OC.TAG_FAVORITE]); expect($tr.attr('data-favorite')).toEqual('true'); @@ -76,58 +76,11 @@ describe('OCA.Files.TagsPlugin tests', function() { }); }); describe('Applying tags', function() { - it('sends request to server and updates icon', function() { - var request; - fileList.setFiles(testFiles); - var $tr = fileList.findFileEl('One.txt'); - var $action = $tr.find('.action-favorite'); - $action.click(); - - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(JSON.parse(request.requestBody)).toEqual({ - tags: ['tag1', 'tag2', OC.TAG_FAVORITE] - }); - request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - tags: ['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE] - })); - - // re-read the element as it was re-inserted - $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); - - expect($tr.attr('data-favorite')).toEqual('true'); - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect($action.find('.icon').hasClass('icon-star')).toEqual(false); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(true); - - $action.click(); - - expect(fakeServer.requests.length).toEqual(2); - request = fakeServer.requests[1]; - expect(JSON.parse(request.requestBody)).toEqual({ - tags: ['tag1', 'tag2', 'tag3'] - }); - request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - tags: ['tag1', 'tag2', 'tag3'] - })); - - // re-read the element as it was re-inserted - $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); - - expect($tr.attr('data-favorite')).toBeFalsy(); - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3']); - expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3']); - expect($action.find('.icon').hasClass('icon-star')).toEqual(true); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(false); - }); it('through FileActionsMenu sends request to server and updates icon', function() { var request; fileList.setFiles(testFiles); var $tr = fileList.findFileEl('One.txt'); - var $action = $tr.find('.action-favorite'); + var $favoriteMark = $tr.find('.favorite-mark'); var $showMenuAction = $tr.find('.action-menu'); $showMenuAction.click(); var $favoriteActionInMenu = $tr.find('.fileActionsMenu .action-favorite'); @@ -144,14 +97,14 @@ describe('OCA.Files.TagsPlugin tests', function() { // re-read the element as it was re-inserted $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); + $favoriteMark = $tr.find('.favorite-mark'); $showMenuAction = $tr.find('.action-menu'); expect($tr.attr('data-favorite')).toEqual('true'); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect($action.find('.icon').hasClass('icon-star')).toEqual(false); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(true); + expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(false); + expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(true); // show again the menu and get the new action, as the menu was // closed and removed (and with it, the previous action) when that @@ -171,13 +124,13 @@ describe('OCA.Files.TagsPlugin tests', function() { // re-read the element as it was re-inserted $tr = fileList.findFileEl('One.txt'); - $action = $tr.find('.action-favorite'); + $favoriteMark = $tr.find('.favorite-mark'); expect($tr.attr('data-favorite')).toBeFalsy(); expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3']); expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3']); - expect($action.find('.icon').hasClass('icon-star')).toEqual(true); - expect($action.find('.icon').hasClass('icon-starred')).toEqual(false); + expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(true); + expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(false); }); }); describe('elementToFile', function() { diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php index a2b286330fd..eee03973dc8 100644 --- a/tests/acceptance/features/bootstrap/FilesAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesAppContext.php @@ -278,16 +278,16 @@ class FilesAppContext implements Context, ActorAwareInterface { /** * @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"); + public static function favoriteMarkForFile($fileName) { + return Locator::forThe()->css(".favorite-mark")->descendantOf(self::rowForFile($fileName))-> + describedAs("Favorite mark for file $fileName in Files app"); } /** * @return Locator */ public static function notFavoritedStateIconForFile($fileName) { - return Locator::forThe()->css(".icon-star")->descendantOf(self::favoriteActionForFile($fileName))-> + return Locator::forThe()->css(".icon-star")->descendantOf(self::favoriteMarkForFile($fileName))-> describedAs("Not favorited state icon for file $fileName in Files app"); } @@ -295,7 +295,7 @@ class FilesAppContext implements Context, ActorAwareInterface { * @return Locator */ public static function favoritedStateIconForFile($fileName) { - return Locator::forThe()->css(".icon-starred")->descendantOf(self::favoriteActionForFile($fileName))-> + return Locator::forThe()->css(".icon-starred")->descendantOf(self::favoriteMarkForFile($fileName))-> describedAs("Favorited state icon for file $fileName in Files app"); } -- cgit v1.2.3 From 065ab6bfff47b4e869b76dacf3b077fd0aff8ad5 Mon Sep 17 00:00:00 2001 From: Daniel Calviño Sánchez Date: Wed, 18 Oct 2017 14:00:32 +0200 Subject: Solve acceptance test failure due to clicks on covered elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firefox and Chrome drivers for Selenium refuse to click on an element if the point to be clicked is covered by a different element, throwing an UnknownError exception with message "Element is not clickable at point ({x}, {y}). Other element would receive the click: {element}". Although in general that would be a legit error (as the user would not be able to click on the element) due to a bad layout, sometimes this can be just a temporal issue caused by an animation, in which case there would be no problem once the animation finished and the elements are all in their final location. Unfortunately, automatically handling those situations in which the problem is caused by an animation by just retrying a few times if the element to be clicked is covered before giving up would probably cause confusion instead of easing test writing. The reason is that if the center of the element is covered by another one the Firefox driver for Selenium tries to click on the corners of the element instead. The problem is that the coordinates used for the click are integer values, but Firefox has sub-pixel accuracy, so sometimes (depending on which corner is not covered and whether the left, top, width or height properties of the element to be clicked have a decimal component or not) the clicks silently land on a different HTML element (and that is with squared borders; with round borders they always land on a different HTML element. That was partially addressed for Selenium 3.0 by clicking first on the edges, but it would still fail if the middle point of the edges is covered but not the corners). It is not possible to fix or even detect all that from the tests (except maybe with some extreme hacks involving accessing private PHP members from Mink and bypassing or replacing the standard JavaScript executed by the Firefox driver with a custom implementation...), so it is not possible to ensure that clicks during an animation will land on the right element (in fact it is not possible even on static elements, although except when the layout is wrong there should be no problem); sometimes retrying a click when the element is covered would solve the problem, sometimes it would cause a different element to be clicked (and sometimes there would be even no retry, as the first click would have silently landed on a different element than the expected one). Therefore, a different approach must be used. Instead of trying to automatically handle clicks during animations the tests must be written being aware of the problem and thus waiting somehow for the animations that can cause a problem to end before performing the clicks. Signed-off-by: Daniel Calviño Sánchez --- tests/acceptance/features/app-files.feature | 16 ++++++++++++++++ tests/acceptance/features/bootstrap/FilesAppContext.php | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'tests') diff --git a/tests/acceptance/features/app-files.feature b/tests/acceptance/features/app-files.feature index 37e01bcada2..ac2d05fac2c 100644 --- a/tests/acceptance/features/app-files.feature +++ b/tests/acceptance/features/app-files.feature @@ -145,6 +145,14 @@ Feature: app-files 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 + # To mark the file as favorite the file actions menu has to be shown but, as + # the details view is opened automatically when the folder is created, + # clicking on the menu trigger could fail if it is covered by the details + # view due to its opening animation. Instead of ensuring that the animations + # of the contents and the details view have both finished it is easier to + # close the details view and wait until it is closed before continuing. + And I close the details view + And I see that the details view is closed 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 @@ -153,6 +161,14 @@ Feature: app-files 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 + # To mark the file as favorite the file actions menu has to be shown but, as + # the details view is opened automatically when the folder is created, + # clicking on the menu trigger could fail if it is covered by the details + # view due to its opening animation. Instead of ensuring that the animations + # of the contents and the details view have both finished it is easier to + # close the details view and wait until it is closed before continuing. + And I close the details view + And I see that the details view is closed 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 diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php index eee03973dc8..338823a9478 100644 --- a/tests/acceptance/features/bootstrap/FilesAppContext.php +++ b/tests/acceptance/features/bootstrap/FilesAppContext.php @@ -77,6 +77,15 @@ class FilesAppContext implements Context, ActorAwareInterface { describedAs("Current section details view in Files app"); } + /** + * @return Locator + */ + public static function closeDetailsViewButton() { + return Locator::forThe()->css(".icon-close")-> + descendantOf(self::currentSectionDetailsView())-> + describedAs("Close current section details view in Files app"); + } + /** * @return Locator */ @@ -387,6 +396,13 @@ class FilesAppContext implements Context, ActorAwareInterface { $this->actor->find(self::detailsMenuItem(), 2)->click(); } + /** + * @Given I close the details view + */ + public function iCloseTheDetailsView() { + $this->actor->find(self::closeDetailsViewButton(), 10)->click(); + } + /** * @Given I open the input field for tags in the details view */ -- cgit v1.2.3