diff options
author | Lukas Reschke <lukas@statuscode.ch> | 2016-05-10 09:44:50 +0200 |
---|---|---|
committer | Lukas Reschke <lukas@statuscode.ch> | 2016-05-10 09:44:50 +0200 |
commit | e8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f (patch) | |
tree | 0eec63cb17f7ad60130474a0bbdcbfaaa281d884 /apps | |
parent | 1fb7be42e55236c2663b52f89a85b54d81ae08ba (diff) | |
parent | 254576e1f7f5ec610ddbd9de81005397191cf52f (diff) | |
download | nextcloud-server-e8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f.tar.gz nextcloud-server-e8e72aa9101b1c4b7e321dd3f17dcc9462f34a8f.zip |
Merge pull request #24434 from owncloud/permalinks
Permalinks
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/appinfo/application.php | 15 | ||||
-rw-r--r-- | apps/files/controller/viewcontroller.php | 48 | ||||
-rw-r--r-- | apps/files/css/detailsView.css | 13 | ||||
-rw-r--r-- | apps/files/js/app.js | 37 | ||||
-rw-r--r-- | apps/files/js/fileactions.js | 2 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 36 | ||||
-rw-r--r-- | apps/files/js/mainfileinfodetailview.js | 38 | ||||
-rw-r--r-- | apps/files/tests/controller/ViewControllerTest.php | 103 | ||||
-rw-r--r-- | apps/files/tests/js/appSpec.js | 36 | ||||
-rw-r--r-- | apps/files/tests/js/filelistSpec.js | 9 | ||||
-rw-r--r-- | apps/files/tests/js/mainfileinfodetailviewSpec.js | 5 |
11 files changed, 317 insertions, 25 deletions
diff --git a/apps/files/appinfo/application.php b/apps/files/appinfo/application.php index 2d2decf6288..3dd73037871 100644 --- a/apps/files/appinfo/application.php +++ b/apps/files/appinfo/application.php @@ -26,6 +26,7 @@ use OCA\Files\Controller\ApiController; use OCP\AppFramework\App; use \OCA\Files\Service\TagService; use \OCP\IContainer; +use OCA\Files\Controller\ViewController; class Application extends App { public function __construct(array $urlParams=array()) { @@ -48,6 +49,20 @@ class Application extends App { ); }); + $container->registerService('ViewController', function (IContainer $c) use ($server) { + return new ViewController( + $c->query('AppName'), + $c->query('Request'), + $server->getURLGenerator(), + $server->getNavigationManager(), + $c->query('L10N'), + $server->getConfig(), + $server->getEventDispatcher(), + $server->getUserSession(), + $server->getUserFolder() + ); + }); + /** * Core */ diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php index ded6fd555df..6ee924e2f0b 100644 --- a/apps/files/controller/viewcontroller.php +++ b/apps/files/controller/viewcontroller.php @@ -3,6 +3,7 @@ * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Lukas Reschke <lukas@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2016, ownCloud, Inc. * @license AGPL-3.0 @@ -26,6 +27,7 @@ namespace OCA\Files\Controller; use OC\AppFramework\Http\Request; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; @@ -35,6 +37,8 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\Files\Folder; /** * Class ViewController @@ -58,6 +62,8 @@ class ViewController extends Controller { protected $eventDispatcher; /** @var IUserSession */ protected $userSession; + /** @var \OCP\Files\Folder */ + protected $userFolder; /** * @param string $appName @@ -68,6 +74,7 @@ class ViewController extends Controller { * @param IConfig $config * @param EventDispatcherInterface $eventDispatcherInterface * @param IUserSession $userSession + * @param Folder $userFolder */ public function __construct($appName, IRequest $request, @@ -76,7 +83,9 @@ class ViewController extends Controller { IL10N $l10n, IConfig $config, EventDispatcherInterface $eventDispatcherInterface, - IUserSession $userSession) { + IUserSession $userSession, + Folder $userFolder + ) { parent::__construct($appName, $request); $this->appName = $appName; $this->request = $request; @@ -86,6 +95,7 @@ class ViewController extends Controller { $this->config = $config; $this->eventDispatcher = $eventDispatcherInterface; $this->userSession = $userSession; + $this->userFolder = $userFolder; } /** @@ -124,10 +134,15 @@ class ViewController extends Controller { * * @param string $dir * @param string $view + * @param string $fileid * @return TemplateResponse * @throws \OCP\Files\NotFoundException */ - public function index($dir = '', $view = '') { + public function index($dir = '', $view = '', $fileid = null) { + if ($fileid !== null) { + return $this->showFile($fileid); + } + $nav = new \OCP\Template('files', 'appnavigation', ''); // Load the files we need @@ -239,4 +254,33 @@ class ViewController extends Controller { return $response; } + + /** + * Redirects to the file list and highlight the given file id + * + * @param string $fileId file id to show + * @return Response redirect response or not found response + * + * @NoCSRFRequired + * @NoAdminRequired + */ + public function showFile($fileId) { + $files = $this->userFolder->getById($fileId); + $params = []; + + if (!empty($files)) { + $file = current($files); + if ($file instanceof Folder) { + // set the full path to enter the folder + $params['dir'] = $this->userFolder->getRelativePath($file->getPath()); + } else { + // set parent path as dir + $params['dir'] = $this->userFolder->getRelativePath($file->getParent()->getPath()); + // and scroll to the entry + $params['scrollto'] = $file->getName(); + } + return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params)); + } + return new NotFoundResponse(); + } } diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css index c77bb28c774..669a15c4e38 100644 --- a/apps/files/css/detailsView.css +++ b/apps/files/css/detailsView.css @@ -14,6 +14,19 @@ width: 100%; } +#app-sidebar .mainFileInfoView .icon { + display: inline-block; +} + +#app-sidebar .mainFileInfoView .permalink { + margin-left: 10px; + opacity: .5; +} +#app-sidebar .mainFileInfoView .permalink-field>input { + clear: both; + width: 90%; +} + #app-sidebar .file-details-container { display: inline-block; float: left; diff --git a/apps/files/js/app.js b/apps/files/js/app.js index eac080a009d..7a3d78f9663 100644 --- a/apps/files/js/app.js +++ b/apps/files/js/app.js @@ -174,6 +174,7 @@ // detect when app changed their current directory $('#app-content').delegate('>div', 'changeDirectory', _.bind(this._onDirectoryChanged, this)); + $('#app-content').delegate('>div', 'afterChangeDirectory', _.bind(this._onAfterDirectoryChanged, this)); $('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this)); $('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this)); @@ -224,7 +225,16 @@ */ _onDirectoryChanged: function(e) { if (e.dir) { - this._changeUrl(this.navigation.getActiveItem(), e.dir); + this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId); + } + }, + + /** + * Event handler for when an app notified that its directory changed + */ + _onAfterDirectoryChanged: function(e) { + if (e.dir && e.fileId) { + this._changeUrl(this.navigation.getActiveItem(), e.dir, e.fileId); } }, @@ -261,14 +271,35 @@ }, /** + * Encode URL params into a string, except for the "dir" attribute + * that gets encoded as path where "/" is not encoded + * + * @param {Object.<string>} params + * @return {string} encoded params + */ + _makeUrlParams: function(params) { + var dir = params.dir; + delete params.dir; + return 'dir=' + OC.encodePath(dir) + '&' + OC.buildQueryString(params); + }, + + /** * Change the URL to point to the given dir and view */ - _changeUrl: function(view, dir) { + _changeUrl: function(view, dir, fileId) { var params = {dir: dir}; if (view !== 'files') { params.view = view; + } else if (fileId) { + params.fileid = fileId; + } + var currentParams = OC.Util.History.parseUrlQuery(); + if (currentParams.dir === params.dir && currentParams.view === params.view && currentParams.fileid !== params.fileid) { + // if only fileid changed or was added, replace instead of push + OC.Util.History.replaceState(this._makeUrlParams(params)); + } else { + OC.Util.History.pushState(this._makeUrlParams(params)); } - OC.Util.History.pushState(params); } }; })(); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 69e32d500c4..c3d4fba9ef5 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -619,7 +619,7 @@ this.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) { var dir = context.$file.attr('data-path') || context.fileList.getCurrentDirectory(); - context.fileList.changeDirectory(OC.joinPaths(dir, filename)); + context.fileList.changeDirectory(OC.joinPaths(dir, filename), true, false, parseInt(context.$file.attr('data-id'), 10)); }); this.registerAction({ diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 16ca5e91ed2..9395112bce3 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1362,19 +1362,20 @@ return parseInt(this.$el.find('#permissions').val(), 10); }, /** - * @brief Changes the current directory and reload the file list. - * @param targetDir target directory (non URL encoded) - * @param changeUrl false if the URL must not be changed (defaults to true) - * @param {boolean} force set to true to force changing directory + * Changes the current directory and reload the file list. + * @param {string} targetDir target directory (non URL encoded) + * @param {boolean} [changeUrl=true] if the URL must not be changed (defaults to true) + * @param {boolean} [force=false] set to true to force changing directory + * @param {string} [fileId] optional file id, if known, to be appended in the URL */ - changeDirectory: function(targetDir, changeUrl, force) { + changeDirectory: function(targetDir, changeUrl, force, fileId) { var self = this; var currentDir = this.getCurrentDirectory(); targetDir = targetDir || '/'; if (!force && currentDir === targetDir) { return; } - this._setCurrentDir(targetDir, changeUrl); + this._setCurrentDir(targetDir, changeUrl, fileId); this.reload().then(function(success){ if (!success) { self.changeDirectory(currentDir, true); @@ -1389,8 +1390,9 @@ * Sets the current directory name and updates the breadcrumb. * @param targetDir directory to display * @param changeUrl true to also update the URL, false otherwise (default) + * @param {string} [fileId] file id */ - _setCurrentDir: function(targetDir, changeUrl) { + _setCurrentDir: function(targetDir, changeUrl, fileId) { targetDir = targetDir.replace(/\\/g, '/'); var previousDir = this.getCurrentDirectory(), baseDir = OC.basename(targetDir); @@ -1408,10 +1410,14 @@ this.$el.find('#dir').val(targetDir); if (changeUrl !== false) { - this.$el.trigger(jQuery.Event('changeDirectory', { + var params = { dir: targetDir, previousDir: previousDir - })); + }; + if (fileId) { + params.fileId = fileId; + } + this.$el.trigger(jQuery.Event('changeDirectory', params)); } this.breadcrumb.setDirectory(this.getCurrentDirectory()); }, @@ -1557,6 +1563,18 @@ result.sort(this._sortComparator); this.setFiles(result); + + if (this.dirInfo) { + var newFileId = this.dirInfo.id; + // update fileid in URL + var params = { + dir: this.getCurrentDirectory() + }; + if (newFileId) { + params.fileId = newFileId; + } + this.$el.trigger(jQuery.Event('afterChangeDirectory', params)); + } return true; }, diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index 1bcb4873c53..c586135b9c7 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -12,7 +12,13 @@ var TEMPLATE = '<div class="thumbnailContainer"><a href="#" class="thumbnail action-default"><div class="stretcher"/></a></div>' + '<div class="file-details-container">' + - '<div class="fileName"><h3 title="{{name}}" class="ellipsis">{{name}}</h3></div>' + + '<div class="fileName">' + + '<h3 title="{{name}}" class="ellipsis">{{name}}</h3>' + + '<a class="permalink" href="{{permalink}}" title="{{permalinkTitle}}">' + + '<span class="icon icon-public"></span>' + + '<span class="hidden-visually">{{permalinkTitle}}</span>' + + '</a>' + + '</div>' + ' <div class="file-details ellipsis">' + ' <a href="#" ' + ' class="action action-favorite favorite">' + @@ -20,6 +26,9 @@ ' </a>' + ' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date" title="{{altDate}}">{{date}}</span>' + ' </div>' + + '</div>' + + '<div class="hidden permalink-field">' + + '<input type="text" value="{{permalink}}" placeholder="{{permalinkTitle}}" readonly="readonly"/>' + '</div>'; /** @@ -50,7 +59,9 @@ events: { 'click a.action-favorite': '_onClickFavorite', - 'click a.action-default': '_onClickDefaultAction' + 'click a.action-default': '_onClickDefaultAction', + 'click a.permalink': '_onClickPermalink', + 'focus .permalink-field>input': '_onFocusPermalink' }, template: function(data) { @@ -72,6 +83,20 @@ } }, + _onClickPermalink: function() { + var $row = this.$('.permalink-field'); + $row.toggleClass('hidden'); + if (!$row.hasClass('hidden')) { + $row.find('>input').focus(); + } + // cancel click, user must right-click + copy or middle click + return false; + }, + + _onFocusPermalink: function() { + this.$('.permalink-field>input').select(); + }, + _onClickFavorite: function(event) { event.preventDefault(); this._fileActions.triggerAction('Favorite', this.model, this._fileList); @@ -87,6 +112,11 @@ this.render(); }, + _makePermalink: function(fileId) { + var baseUrl = OC.getProtocol() + '://' + OC.getHost(); + return baseUrl + OC.generateUrl('/f/{fileId}', {fileId: fileId}); + }, + setFileInfo: function(fileInfo) { if (this.model) { this.model.off('change', this._onModelChanged, this); @@ -118,7 +148,9 @@ altDate: OC.Util.formatDate(this.model.get('mtime')), date: OC.Util.relativeModifiedDate(this.model.get('mtime')), starAltText: isFavorite ? t('files', 'Favorited') : t('files', 'Favorite'), - starIcon: OC.imagePath('core', isFavorite ? 'actions/starred' : 'actions/star') + starIcon: OC.imagePath('core', isFavorite ? 'actions/starred' : 'actions/star'), + permalink: this._makePermalink(this.model.get('id')), + permalinkTitle: t('files', 'Local link') })); // TODO: we really need OC.Previews diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php index 420e635b4b9..797702def6b 100644 --- a/apps/files/tests/controller/ViewControllerTest.php +++ b/apps/files/tests/controller/ViewControllerTest.php @@ -36,6 +36,7 @@ use OCP\IL10N; use OCP\IConfig; use OCP\IUserSession; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use OCP\Files\Folder; /** * Class ViewControllerTest @@ -61,6 +62,8 @@ class ViewControllerTest extends TestCase { private $user; /** @var IUserSession */ private $userSession; + /** @var Folder */ + private $userFolder; public function setUp() { parent::setUp(); @@ -75,6 +78,7 @@ class ViewControllerTest extends TestCase { $this->userSession->expects($this->any()) ->method('getUser') ->will($this->returnValue($this->user)); + $this->userFolder = $this->getMock('\OCP\Files\Folder'); $this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController') ->setConstructorArgs([ 'files', @@ -84,7 +88,8 @@ class ViewControllerTest extends TestCase { $this->l10n, $this->config, $this->eventDispatcher, - $this->userSession + $this->userSession, + $this->userFolder ]) ->setMethods([ 'getStorageInfo', @@ -287,4 +292,100 @@ class ViewControllerTest extends TestCase { $expected->setContentSecurityPolicy($policy); $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); } + + public function showFileMethodProvider() { + return [ + [true], + [false], + ]; + } + + /** + * @dataProvider showFileMethodProvider + */ + public function testShowFileRouteWithFolder($useShowFile) { + $node = $this->getMock('\OCP\Files\Folder'); + $node->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('/user/files/test/sub')); + + $this->userFolder->expects($this->at(0)) + ->method('getById') + ->with(123) + ->will($this->returnValue([$node])); + $this->userFolder->expects($this->at(1)) + ->method('getRelativePath') + ->with('/user/files/test/sub') + ->will($this->returnValue('/test/sub')); + + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index', ['dir' => '/test/sub']) + ->will($this->returnValue('/apps/files/?dir=/test/sub')); + + $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub'); + if ($useShowFile) { + $this->assertEquals($expected, $this->viewController->showFile(123)); + } else { + $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123')); + } + } + + /** + * @dataProvider showFileMethodProvider + */ + public function testShowFileRouteWithFile($useShowFile) { + $parentNode = $this->getMock('\OCP\Files\Folder'); + $parentNode->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('/user/files/test')); + + $node = $this->getMock('\OCP\Files\File'); + $node->expects($this->once()) + ->method('getParent') + ->will($this->returnValue($parentNode)); + $node->expects($this->once()) + ->method('getName') + ->will($this->returnValue('somefile.txt')); + + $this->userFolder->expects($this->at(0)) + ->method('getById') + ->with(123) + ->will($this->returnValue([$node])); + $this->userFolder->expects($this->at(1)) + ->method('getRelativePath') + ->with('/user/files/test') + ->will($this->returnValue('/test')); + + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRoute') + ->with('files.view.index', ['dir' => '/test', 'scrollto' => 'somefile.txt']) + ->will($this->returnValue('/apps/files/?dir=/test/sub&scrollto=somefile.txt')); + + $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub&scrollto=somefile.txt'); + if ($useShowFile) { + $this->assertEquals($expected, $this->viewController->showFile(123)); + } else { + $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123')); + } + } + + /** + * @dataProvider showFileMethodProvider + */ + public function testShowFileRouteWithInvalidFileId($useShowFile) { + $this->userFolder->expects($this->at(0)) + ->method('getById') + ->with(123) + ->will($this->returnValue([])); + + $expected = new Http\NotFoundResponse(); + if ($useShowFile) { + $this->assertEquals($expected, $this->viewController->showFile(123)); + } else { + $this->assertEquals($expected, $this->viewController->index('/whatever', '', '123')); + } + } } diff --git a/apps/files/tests/js/appSpec.js b/apps/files/tests/js/appSpec.js index dce513339f0..b9c323e7c12 100644 --- a/apps/files/tests/js/appSpec.js +++ b/apps/files/tests/js/appSpec.js @@ -22,6 +22,7 @@ describe('OCA.Files.App tests', function() { var App = OCA.Files.App; var pushStateStub; + var replaceStateStub; var parseUrlQueryStub; var oldLegacyFileActions; @@ -48,6 +49,7 @@ describe('OCA.Files.App tests', function() { OCA.Files.fileActions = new OCA.Files.FileActions(); pushStateStub = sinon.stub(OC.Util.History, 'pushState'); + replaceStateStub = sinon.stub(OC.Util.History, 'replaceState'); parseUrlQueryStub = sinon.stub(OC.Util.History, 'parseUrlQuery'); parseUrlQueryStub.returns({}); @@ -59,6 +61,7 @@ describe('OCA.Files.App tests', function() { window.FileActions = oldLegacyFileActions; pushStateStub.restore(); + replaceStateStub.restore(); parseUrlQueryStub.restore(); }); @@ -119,18 +122,39 @@ describe('OCA.Files.App tests', function() { describe('URL handling', function() { it('pushes the state to the URL when current app changed directory', function() { - $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'subdir'})); + $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'sub dir'})); expect(pushStateStub.calledOnce).toEqual(true); - expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir'); - expect(pushStateStub.getCall(0).args[0].view).not.toBeDefined(); + var params = OC.parseQueryString(pushStateStub.getCall(0).args[0]); + expect(params.dir).toEqual('sub dir'); + expect(params.view).not.toBeDefined(); $('li[data-id=other]>a').click(); pushStateStub.reset(); - $('#app-content-other').trigger(new $.Event('changeDirectory', {dir: 'subdir'})); + $('#app-content-other').trigger(new $.Event('changeDirectory', {dir: 'sub dir'})); expect(pushStateStub.calledOnce).toEqual(true); - expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir'); - expect(pushStateStub.getCall(0).args[0].view).toEqual('other'); + params = OC.parseQueryString(pushStateStub.getCall(0).args[0]); + expect(params.dir).toEqual('sub dir'); + expect(params.view).toEqual('other'); + }); + it('replaces the state to the URL when fileid is known', function() { + $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'sub dir'})); + expect(pushStateStub.calledOnce).toEqual(true); + var params = OC.parseQueryString(pushStateStub.getCall(0).args[0]); + expect(params.dir).toEqual('sub dir'); + expect(params.view).not.toBeDefined(); + expect(replaceStateStub.notCalled).toEqual(true); + + parseUrlQueryStub.returns({dir: 'sub dir'}); + + $('#app-content-files').trigger(new $.Event('afterChangeDirectory', {dir: 'sub dir', fileId: 123})); + + expect(pushStateStub.calledOnce).toEqual(true); + expect(replaceStateStub.calledOnce).toEqual(true); + params = OC.parseQueryString(replaceStateStub.getCall(0).args[0]); + expect(params.dir).toEqual('sub dir'); + expect(params.view).not.toBeDefined(); + expect(params.fileid).toEqual('123'); }); describe('onpopstate', function() { it('sends "urlChanged" event to current app', function() { diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index cc3bcd74b46..7e6408128bb 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -1358,6 +1358,15 @@ describe('OCA.Files.FileList tests', function() { expect(handler.calledOnce).toEqual(true); expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); }); + it('triggers "afterChangeDirectory" event with fileid after changing directory', function() { + var handler = sinon.stub(); + $('#app-content-files').on('afterChangeDirectory', handler); + fileList.changeDirectory('/somedir'); + deferredList.resolve(200, [testRoot].concat(testFiles)); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); + expect(handler.getCall(0).args[0].fileId).toEqual(99); + }); it('changes the directory when receiving "urlChanged" event', function() { $('#app-content-files').trigger(new $.Event('urlChanged', {view: 'files', dir: '/somedir'})); expect(fileList.getCurrentDirectory()).toEqual('/somedir'); diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js index 460629806c8..e81adbcf7ac 100644 --- a/apps/files/tests/js/mainfileinfodetailviewSpec.js +++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js @@ -62,6 +62,11 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { expect(view.$el.find('.date').attr('title')).toEqual(dateExpected); clock.restore(); }); + it('displays permalink', function() { + view.setFileInfo(testFileInfo); + expect(view.$el.find('.permalink').attr('href')) + .toEqual(OC.getProtocol() + '://' + OC.getHost() + OC.generateUrl('/f/5')); + }); it('displays favorite icon', function() { testFileInfo.set('tags', [OC.TAG_FAVORITE]); view.setFileInfo(testFileInfo); |