You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SharingService.spec.ts 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /**
  2. * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
  3. *
  4. * @author John Molakvoæ <skjnldsv@protonmail.com>
  5. *
  6. * @license AGPL-3.0-or-later
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. import type { OCSResponse } from '@nextcloud/typings/ocs'
  23. import { expect } from '@jest/globals'
  24. import { Type } from '@nextcloud/sharing'
  25. import * as auth from '@nextcloud/auth'
  26. import axios from '@nextcloud/axios'
  27. import { getContents } from './SharingService'
  28. import { File, Folder } from '@nextcloud/files'
  29. import logger from './logger'
  30. global.window.OC = {
  31. TAG_FAVORITE: '_$!<Favorite>!$_',
  32. }
  33. describe('SharingService methods definitions', () => {
  34. beforeAll(() => {
  35. jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => {
  36. return {
  37. data: {
  38. ocs: {
  39. meta: {
  40. status: 'ok',
  41. statuscode: 200,
  42. message: 'OK',
  43. },
  44. data: [],
  45. },
  46. } as OCSResponse<any>,
  47. }
  48. })
  49. })
  50. afterAll(() => {
  51. jest.restoreAllMocks()
  52. })
  53. test('Shared with you', async () => {
  54. await getContents(true, false, false, false, [])
  55. expect(axios.get).toHaveBeenCalledTimes(2)
  56. expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
  57. headers: {
  58. 'Content-Type': 'application/json',
  59. },
  60. params: {
  61. shared_with_me: true,
  62. include_tags: true,
  63. },
  64. })
  65. expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares', {
  66. headers: {
  67. 'Content-Type': 'application/json',
  68. },
  69. params: {
  70. include_tags: true,
  71. },
  72. })
  73. })
  74. test('Shared with others', async () => {
  75. await getContents(false, true, false, false, [])
  76. expect(axios.get).toHaveBeenCalledTimes(1)
  77. expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
  78. headers: {
  79. 'Content-Type': 'application/json',
  80. },
  81. params: {
  82. shared_with_me: false,
  83. include_tags: true,
  84. },
  85. })
  86. })
  87. test('Pending shares', async () => {
  88. await getContents(false, false, true, false, [])
  89. expect(axios.get).toHaveBeenCalledTimes(2)
  90. expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending', {
  91. headers: {
  92. 'Content-Type': 'application/json',
  93. },
  94. params: {
  95. include_tags: true,
  96. },
  97. })
  98. expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending', {
  99. headers: {
  100. 'Content-Type': 'application/json',
  101. },
  102. params: {
  103. include_tags: true,
  104. },
  105. })
  106. })
  107. test('Deleted shares', async () => {
  108. await getContents(false, true, false, false, [])
  109. expect(axios.get).toHaveBeenCalledTimes(1)
  110. expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
  111. headers: {
  112. 'Content-Type': 'application/json',
  113. },
  114. params: {
  115. shared_with_me: false,
  116. include_tags: true,
  117. },
  118. })
  119. })
  120. test('Unknown owner', async () => {
  121. jest.spyOn(auth, 'getCurrentUser').mockReturnValue(null)
  122. const results = await getContents(false, true, false, false, [])
  123. expect(results.folder.owner).toEqual(null)
  124. })
  125. })
  126. describe('SharingService filtering', () => {
  127. beforeAll(() => {
  128. jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => {
  129. return {
  130. data: {
  131. ocs: {
  132. meta: {
  133. status: 'ok',
  134. statuscode: 200,
  135. message: 'OK',
  136. },
  137. data: [
  138. {
  139. id: '62',
  140. share_type: Type.SHARE_TYPE_USER,
  141. uid_owner: 'test',
  142. displayname_owner: 'test',
  143. permissions: 31,
  144. stime: 1688666292,
  145. expiration: '2023-07-13 00:00:00',
  146. token: null,
  147. path: '/Collaborators',
  148. item_type: 'folder',
  149. item_permissions: 31,
  150. mimetype: 'httpd/unix-directory',
  151. storage: 224,
  152. item_source: 419413,
  153. file_source: 419413,
  154. file_parent: 419336,
  155. file_target: '/Collaborators',
  156. item_size: 41434,
  157. item_mtime: 1688662980,
  158. },
  159. ],
  160. },
  161. },
  162. }
  163. })
  164. })
  165. afterAll(() => {
  166. jest.restoreAllMocks()
  167. })
  168. test('Shared with others filtering', async () => {
  169. const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_USER])
  170. expect(axios.get).toHaveBeenCalledTimes(1)
  171. expect(shares.contents).toHaveLength(1)
  172. expect(shares.contents[0].fileid).toBe(419413)
  173. expect(shares.contents[0]).toBeInstanceOf(Folder)
  174. })
  175. test('Shared with others filtering empty', async () => {
  176. const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_LINK])
  177. expect(axios.get).toHaveBeenCalledTimes(1)
  178. expect(shares.contents).toHaveLength(0)
  179. })
  180. })
  181. describe('SharingService share to Node mapping', () => {
  182. const shareFile = {
  183. id: '66',
  184. share_type: 0,
  185. uid_owner: 'test',
  186. displayname_owner: 'test',
  187. permissions: 19,
  188. can_edit: true,
  189. can_delete: true,
  190. stime: 1688721609,
  191. parent: null,
  192. expiration: '2023-07-14 00:00:00',
  193. token: null,
  194. uid_file_owner: 'test',
  195. note: '',
  196. label: null,
  197. displayname_file_owner: 'test',
  198. path: '/document.md',
  199. item_type: 'file',
  200. item_permissions: 27,
  201. mimetype: 'text/markdown',
  202. has_preview: true,
  203. storage_id: 'home::test',
  204. storage: 224,
  205. item_source: 530936,
  206. file_source: 530936,
  207. file_parent: 419336,
  208. file_target: '/document.md',
  209. item_size: 123,
  210. item_mtime: 1688721600,
  211. share_with: 'user00',
  212. share_with_displayname: 'User00',
  213. share_with_displayname_unique: 'user00@domain.com',
  214. status: {
  215. status: 'away',
  216. message: null,
  217. icon: null,
  218. clearAt: null,
  219. },
  220. mail_send: 0,
  221. hide_download: 0,
  222. attributes: null,
  223. tags: [],
  224. }
  225. const shareFolder = {
  226. id: '67',
  227. share_type: 0,
  228. uid_owner: 'test',
  229. displayname_owner: 'test',
  230. permissions: 31,
  231. can_edit: true,
  232. can_delete: true,
  233. stime: 1688721629,
  234. parent: null,
  235. expiration: '2023-07-14 00:00:00',
  236. token: null,
  237. uid_file_owner: 'test',
  238. note: '',
  239. label: null,
  240. displayname_file_owner: 'test',
  241. path: '/Folder',
  242. item_type: 'folder',
  243. item_permissions: 31,
  244. mimetype: 'httpd/unix-directory',
  245. has_preview: false,
  246. storage_id: 'home::test',
  247. storage: 224,
  248. item_source: 531080,
  249. file_source: 531080,
  250. file_parent: 419336,
  251. file_target: '/Folder',
  252. item_size: 0,
  253. item_mtime: 1688721623,
  254. share_with: 'user00',
  255. share_with_displayname: 'User00',
  256. share_with_displayname_unique: 'user00@domain.com',
  257. status: {
  258. status: 'away',
  259. message: null,
  260. icon: null,
  261. clearAt: null,
  262. },
  263. mail_send: 0,
  264. hide_download: 0,
  265. attributes: null,
  266. tags: [window.OC.TAG_FAVORITE],
  267. }
  268. test('File', async () => {
  269. jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
  270. data: {
  271. ocs: {
  272. data: [shareFile],
  273. },
  274. },
  275. }))
  276. const shares = await getContents(false, true, false, false)
  277. expect(axios.get).toHaveBeenCalledTimes(1)
  278. expect(shares.contents).toHaveLength(1)
  279. const file = shares.contents[0] as File
  280. expect(file).toBeInstanceOf(File)
  281. expect(file.fileid).toBe(530936)
  282. expect(file.source).toBe('http://localhost/remote.php/dav/files/test/document.md')
  283. expect(file.owner).toBe('test')
  284. expect(file.mime).toBe('text/markdown')
  285. expect(file.mtime).toBeInstanceOf(Date)
  286. expect(file.size).toBe(123)
  287. expect(file.permissions).toBe(27)
  288. expect(file.root).toBe('/files/test')
  289. expect(file.attributes).toBeInstanceOf(Object)
  290. expect(file.attributes['has-preview']).toBe(true)
  291. expect(file.attributes.favorite).toBe(0)
  292. })
  293. test('Folder', async () => {
  294. jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
  295. data: {
  296. ocs: {
  297. data: [shareFolder],
  298. },
  299. },
  300. }))
  301. const shares = await getContents(false, true, false, false)
  302. expect(axios.get).toHaveBeenCalledTimes(1)
  303. expect(shares.contents).toHaveLength(1)
  304. const folder = shares.contents[0] as Folder
  305. expect(folder).toBeInstanceOf(Folder)
  306. expect(folder.fileid).toBe(531080)
  307. expect(folder.source).toBe('http://localhost/remote.php/dav/files/test/Folder')
  308. expect(folder.owner).toBe('test')
  309. expect(folder.mime).toBe('httpd/unix-directory')
  310. expect(folder.mtime).toBeInstanceOf(Date)
  311. expect(folder.size).toBe(0)
  312. expect(folder.permissions).toBe(31)
  313. expect(folder.root).toBe('/files/test')
  314. expect(folder.attributes).toBeInstanceOf(Object)
  315. expect(folder.attributes['has-preview']).toBe(false)
  316. expect(folder.attributes.previewUrl).toBeUndefined()
  317. expect(folder.attributes.favorite).toBe(1)
  318. })
  319. test('Error', async () => {
  320. jest.spyOn(logger, 'error').mockImplementationOnce(() => {})
  321. jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
  322. data: {
  323. ocs: {
  324. data: [{}],
  325. },
  326. },
  327. }))
  328. const shares = await getContents(false, true, false, false)
  329. expect(shares.contents).toHaveLength(0)
  330. expect(logger.error).toHaveBeenCalledTimes(1)
  331. })
  332. })