fileactionsmenuSpec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /**
  2. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-FileCopyrightText: 2015 ownCloud, Inc.
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. describe('OCA.Files.FileActionsMenu tests', function() {
  7. var fileList, fileActions, menu, actionStub, menuContext, $tr;
  8. beforeEach(function() {
  9. // init horrible parameters
  10. var $body = $('#testArea');
  11. $body.append('<input type="hidden" id="permissions" value="31"></input>');
  12. // dummy files table
  13. actionStub = sinon.stub();
  14. fileActions = new OCA.Files.FileActions();
  15. fileList = new OCA.Files.FileList($body, {
  16. fileActions: fileActions
  17. });
  18. fileList.changeDirectory('/subdir', false, true);
  19. fileActions.registerAction({
  20. name: 'Testdropdown',
  21. displayName: 'Testdropdowndisplay',
  22. mime: 'all',
  23. permissions: OC.PERMISSION_READ,
  24. icon: function () {
  25. return OC.imagePath('core', 'actions/download');
  26. },
  27. actionHandler: actionStub
  28. });
  29. fileActions.registerAction({
  30. name: 'Testdropdownnoicon',
  31. displayName: 'Testdropdowndisplaynoicon',
  32. mime: 'all',
  33. permissions: OC.PERMISSION_READ,
  34. actionHandler: actionStub
  35. });
  36. fileActions.registerAction({
  37. name: 'Testinline',
  38. displayName: 'Testinlinedisplay',
  39. type: OCA.Files.FileActions.TYPE_INLINE,
  40. mime: 'all',
  41. permissions: OC.PERMISSION_READ
  42. });
  43. fileActions.registerAction({
  44. name: 'Testdefault',
  45. displayName: 'Testdefaultdisplay',
  46. mime: 'all',
  47. permissions: OC.PERMISSION_READ
  48. });
  49. fileActions.setDefault('all', 'Testdefault');
  50. var fileData = {
  51. id: 18,
  52. type: 'file',
  53. name: 'testName.txt',
  54. mimetype: 'text/plain',
  55. size: '1234',
  56. etag: 'a01234c',
  57. mtime: '123456'
  58. };
  59. $tr = fileList.add(fileData);
  60. menuContext = {
  61. $file: $tr,
  62. fileList: fileList,
  63. fileActions: fileActions,
  64. dir: fileList.getCurrentDirectory()
  65. };
  66. menu = new OCA.Files.FileActionsMenu();
  67. menu.show(menuContext);
  68. });
  69. afterEach(function() {
  70. fileActions = null;
  71. fileList.destroy();
  72. fileList = undefined;
  73. menu.remove();
  74. $('#permissions, .files-filestable').remove();
  75. });
  76. describe('rendering', function() {
  77. it('renders dropdown actions in menu', function() {
  78. var $action = menu.$el.find('a[data-action=Testdropdown]');
  79. expect($action.length).toEqual(1);
  80. expect($action.find('img').attr('src'))
  81. .toEqual(OC.imagePath('core', 'actions/download'));
  82. expect($action.find('.no-icon').length).toEqual(0);
  83. $action = menu.$el.find('a[data-action=Testdropdownnoicon]');
  84. expect($action.length).toEqual(1);
  85. expect($action.find('img').length).toEqual(0);
  86. expect($action.find('.no-icon').length).toEqual(1);
  87. });
  88. it('does not render default actions', function() {
  89. expect(menu.$el.find('a[data-action=Testdefault]').length).toEqual(0);
  90. });
  91. it('render inline actions', function() {
  92. expect(menu.$el.find('a[data-action=Testinline]').length).toEqual(1);
  93. });
  94. it('render inline actions but it is hidden', function() {
  95. expect(menu.$el.find('a[data-action=Testinline]').parent().hasClass('hidden')).toEqual(true);
  96. });
  97. it('only renders actions relevant to the mime type', function() {
  98. fileActions.registerAction({
  99. name: 'Match',
  100. displayName: 'MatchDisplay',
  101. mime: 'text/plain',
  102. permissions: OC.PERMISSION_READ
  103. });
  104. fileActions.registerAction({
  105. name: 'Nomatch',
  106. displayName: 'NoMatchDisplay',
  107. mime: 'application/octet-stream',
  108. permissions: OC.PERMISSION_READ
  109. });
  110. menu.render();
  111. expect(menu.$el.find('a[data-action=Match]').length).toEqual(1);
  112. expect(menu.$el.find('a[data-action=NoMatch]').length).toEqual(0);
  113. });
  114. it('only renders actions relevant to the permissions', function() {
  115. fileActions.registerAction({
  116. name: 'Match',
  117. displayName: 'MatchDisplay',
  118. mime: 'text/plain',
  119. permissions: OC.PERMISSION_UPDATE
  120. });
  121. fileActions.registerAction({
  122. name: 'Nomatch',
  123. displayName: 'NoMatchDisplay',
  124. mime: 'text/plain',
  125. permissions: OC.PERMISSION_DELETE
  126. });
  127. menu.render();
  128. expect(menu.$el.find('a[data-action=Match]').length).toEqual(1);
  129. expect(menu.$el.find('a[data-action=NoMatch]').length).toEqual(0);
  130. });
  131. it('sorts by order attribute, then name', function() {
  132. fileActions.registerAction({
  133. name: 'Baction',
  134. displayName: 'Baction',
  135. order: 2,
  136. mime: 'text/plain',
  137. permissions: OC.PERMISSION_ALL
  138. });
  139. fileActions.registerAction({
  140. name: 'Zaction',
  141. displayName: 'Zaction',
  142. order: 1,
  143. mime: 'text/plain',
  144. permissions: OC.PERMISSION_ALL
  145. });
  146. fileActions.registerAction({
  147. name: 'Yaction',
  148. displayName: 'Yaction',
  149. mime: 'text/plain',
  150. permissions: OC.PERMISSION_ALL
  151. });
  152. fileActions.registerAction({
  153. name: 'Waction',
  154. displayName: 'Waction',
  155. mime: 'text/plain',
  156. permissions: OC.PERMISSION_ALL
  157. });
  158. menu.render();
  159. var zactionIndex = menu.$el.find('a[data-action=Zaction]').closest('li').index();
  160. var bactionIndex = menu.$el.find('a[data-action=Baction]').closest('li').index();
  161. expect(zactionIndex).toBeLessThan(bactionIndex);
  162. var wactionIndex = menu.$el.find('a[data-action=Waction]').closest('li').index();
  163. var yactionIndex = menu.$el.find('a[data-action=Yaction]').closest('li').index();
  164. expect(wactionIndex).toBeLessThan(yactionIndex);
  165. });
  166. it('calls displayName function', function() {
  167. var displayNameStub = sinon.stub().returns('Test');
  168. fileActions.registerAction({
  169. name: 'Something',
  170. displayName: displayNameStub,
  171. mime: 'text/plain',
  172. permissions: OC.PERMISSION_ALL
  173. });
  174. menu.render();
  175. expect(displayNameStub.calledOnce).toEqual(true);
  176. expect(displayNameStub.calledWith(menuContext)).toEqual(true);
  177. expect(menu.$el.find('a[data-action=Something] span:not(.icon)').text()).toEqual('Test');
  178. });
  179. it('uses plain iconClass', function() {
  180. fileActions.registerAction({
  181. name: 'Something',
  182. mime: 'text/plain',
  183. permissions: OC.PERMISSION_ALL,
  184. iconClass: 'test'
  185. });
  186. menu.render();
  187. expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true);
  188. });
  189. it('calls iconClass function', function() {
  190. var iconClassStub = sinon.stub().returns('test');
  191. fileActions.registerAction({
  192. name: 'Something',
  193. mime: 'text/plain',
  194. permissions: OC.PERMISSION_ALL,
  195. iconClass: iconClassStub
  196. });
  197. menu.render();
  198. expect(iconClassStub.calledOnce).toEqual(true);
  199. expect(iconClassStub.calledWith(menuContext.$file.attr('data-file'), menuContext)).toEqual(true);
  200. expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true);
  201. });
  202. });
  203. describe('action handler', function() {
  204. it('calls action handler when clicking menu item', function() {
  205. var $action = menu.$el.find('a[data-action=Testdropdown]');
  206. $action.click();
  207. expect(actionStub.calledOnce).toEqual(true);
  208. expect(actionStub.getCall(0).args[0]).toEqual('testName.txt');
  209. expect(actionStub.getCall(0).args[1].$file[0]).toEqual($tr[0]);
  210. expect(actionStub.getCall(0).args[1].fileList).toEqual(fileList);
  211. expect(actionStub.getCall(0).args[1].fileActions).toEqual(fileActions);
  212. expect(actionStub.getCall(0).args[1].dir).toEqual('/subdir');
  213. });
  214. });
  215. describe('default actions from registerDefaultActions', function() {
  216. beforeEach(function() {
  217. fileActions.clear();
  218. fileActions.registerDefaultActions();
  219. });
  220. it('redirects to download URL when clicking download', function() {
  221. var redirectStub = sinon.stub(OC, 'redirect');
  222. var fileData = {
  223. id: 18,
  224. type: 'file',
  225. name: 'testName.txt',
  226. mimetype: 'text/plain',
  227. size: '1234',
  228. etag: 'a01234c',
  229. mtime: '123456'
  230. };
  231. var $tr = fileList.add(fileData);
  232. fileActions.display($tr.find('td.filename'), true, fileList);
  233. var menuContext = {
  234. $file: $tr,
  235. fileList: fileList,
  236. fileActions: fileActions,
  237. fileInfoModel: new OCA.Files.FileInfoModel(fileData),
  238. dir: fileList.getCurrentDirectory()
  239. };
  240. menu = new OCA.Files.FileActionsMenu();
  241. menu.show(menuContext);
  242. menu.$el.find('.action-download').click();
  243. expect(redirectStub.calledOnce).toEqual(true);
  244. expect(redirectStub.getCall(0).args[0]).toContain(
  245. OC.getRootPath() +
  246. '/remote.php/webdav/subdir/testName.txt'
  247. );
  248. redirectStub.restore();
  249. });
  250. it('takes the file\'s path into account when clicking download', function() {
  251. var redirectStub = sinon.stub(OC, 'redirect');
  252. var fileData = {
  253. id: 18,
  254. type: 'file',
  255. name: 'testName.txt',
  256. path: '/anotherpath/there',
  257. mimetype: 'text/plain',
  258. size: '1234',
  259. etag: 'a01234c',
  260. mtime: '123456'
  261. };
  262. var $tr = fileList.add(fileData);
  263. fileActions.display($tr.find('td.filename'), true, fileList);
  264. var menuContext = {
  265. $file: $tr,
  266. fileList: fileList,
  267. fileActions: fileActions,
  268. fileInfoModel: new OCA.Files.FileInfoModel(fileData),
  269. dir: '/anotherpath/there'
  270. };
  271. menu = new OCA.Files.FileActionsMenu();
  272. menu.show(menuContext);
  273. menu.$el.find('.action-download').click();
  274. expect(redirectStub.calledOnce).toEqual(true);
  275. expect(redirectStub.getCall(0).args[0]).toContain(
  276. OC.getRootPath() + '/remote.php/webdav/anotherpath/there/testName.txt'
  277. );
  278. redirectStub.restore();
  279. });
  280. it('deletes file when clicking delete', function() {
  281. var deleteStub = sinon.stub(fileList, 'do_delete');
  282. var fileData = {
  283. id: 18,
  284. type: 'file',
  285. name: 'testName.txt',
  286. path: '/somepath/dir',
  287. mimetype: 'text/plain',
  288. size: '1234',
  289. etag: 'a01234c',
  290. mtime: '123456'
  291. };
  292. var $tr = fileList.add(fileData);
  293. fileActions.display($tr.find('td.filename'), true, fileList);
  294. var menuContext = {
  295. $file: $tr,
  296. fileList: fileList,
  297. fileActions: fileActions,
  298. fileInfoModel: new OCA.Files.FileInfoModel(fileData),
  299. dir: '/somepath/dir'
  300. };
  301. menu = new OCA.Files.FileActionsMenu();
  302. menu.show(menuContext);
  303. menu.$el.find('.action-delete').click();
  304. expect(deleteStub.calledOnce).toEqual(true);
  305. expect(deleteStub.getCall(0).args[0]).toEqual('testName.txt');
  306. expect(deleteStub.getCall(0).args[1]).toEqual('/somepath/dir');
  307. deleteStub.restore();
  308. });
  309. });
  310. });