Browse Source

fix: adjust testing

Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
pull/39196/head
John Molakvoæ 2 years ago
parent
commit
f5f142d31b
No known key found for this signature in database GPG Key ID: 60C25B8C072916CF
  1. 1
      __mocks__/@nextcloud/axios.ts
  2. 9
      apps/files_sharing/lib/AppInfo/Application.php
  3. 6
      apps/files_sharing/lib/Controller/ShareAPIController.php
  4. 6
      apps/files_sharing/lib/Listener/LoadAdditionalListener.php
  5. 364
      apps/files_sharing/src/services/SharingService.spec.ts
  6. 45
      apps/files_sharing/src/services/SharingService.ts
  7. 125
      apps/files_sharing/src/views/shares.spec.ts
  8. 14
      apps/files_sharing/src/views/shares.ts
  9. 120
      apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
  10. 125
      apps/files_sharing/tests/js/appSpec.js
  11. 41
      build/integration/sharing_features/sharing-v1-part4.feature

1
__mocks__/@nextcloud/axios.ts

@ -20,6 +20,7 @@
*
*/
export default {
get: async () => ({ status: 200, data: {} }),
delete: async () => ({ status: 200, data: {} }),
post: async () => ({ status: 200, data: {} }),
}

9
apps/files_sharing/lib/AppInfo/Application.php

@ -117,7 +117,6 @@ class Application extends App implements IBootstrap {
$context->injectFn([$this, 'registerMountProviders']);
$context->injectFn([$this, 'registerEventsScripts']);
$context->injectFn([$this, 'registerDownloadEvents']);
$context->injectFn([$this, 'loadFilesSharing']);
Helper::registerHooks();
@ -214,12 +213,4 @@ class Application extends App implements IBootstrap {
}
);
}
public function loadFilesSharing(IManager $shareManager): void {
if (!$shareManager->shareApiEnabled() || !class_exists('\OCA\Files\App')) {
return;
}
Util::addScript(self::APP_ID, 'files_sharing', 'files');
}
}

6
apps/files_sharing/lib/Controller/ShareAPIController.php

@ -232,7 +232,7 @@ class ShareAPIController extends OCSController {
// Get the original node permission if the share owner is the current user
if ($isOwnShare) {
$result['permissions'] = $node->getPermissions();
$result['item_permissions'] = $node->getPermissions();
}
$result['mimetype'] = $node->getMimetype();
@ -243,8 +243,8 @@ class ShareAPIController extends OCSController {
$result['file_source'] = $node->getId();
$result['file_parent'] = $node->getParent()->getId();
$result['file_target'] = $share->getTarget();
$result['size'] = $node->getSize();
$result['mtime'] = $node->getMTime();
$result['item_size'] = $node->getSize();
$result['item_mtime'] = $node->getMTime();
$expiration = $share->getExpirationDate();
if ($expiration !== null) {

6
apps/files_sharing/lib/Listener/LoadAdditionalListener.php

@ -29,6 +29,7 @@ use OCA\Files_Sharing\AppInfo\Application;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Share\IManager;
use OCP\Util;
class LoadAdditionalListener implements IEventListener {
@ -40,5 +41,10 @@ class LoadAdditionalListener implements IEventListener {
// After files for the breadcrumb share indicator
Util::addScript(Application::APP_ID, 'additionalScripts', 'files');
Util::addStyle(Application::APP_ID, 'icons');
$shareManager = \OC::$server->get(IManager::class);
if ($shareManager->shareApiEnabled() && class_exists('\OCA\Files\App')) {
Util::addScript(Application::APP_ID, 'files_sharing', 'files');
}
}
}

364
apps/files_sharing/src/services/SharingService.spec.ts

@ -0,0 +1,364 @@
/**
* @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { expect } from '@jest/globals'
import axios from '@nextcloud/axios'
import { Type } from '@nextcloud/sharing'
import * as auth from '@nextcloud/auth'
import { getContents, type OCSResponse } from './SharingService'
import { File, Folder } from '@nextcloud/files'
import logger from './logger'
global.window.OC = {
TAG_FAVORITE: '_$!<Favorite>!$_',
}
describe('SharingService methods definitions', () => {
beforeAll(() => {
jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => {
return {
data: {
ocs: {
meta: {
status: 'ok',
statuscode: 200,
message: 'OK',
},
data: [],
},
} as OCSResponse,
}
})
})
afterAll(() => {
jest.restoreAllMocks()
})
test('Shared with you', async () => {
await getContents(true, false, false, false, [])
expect(axios.get).toHaveBeenCalledTimes(2)
expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
headers: {
'Content-Type': 'application/json',
},
params: {
shared_with_me: true,
include_tags: true,
},
})
expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares', {
headers: {
'Content-Type': 'application/json',
},
params: {
include_tags: true,
},
})
})
test('Shared with others', async () => {
await getContents(false, true, false, false, [])
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
headers: {
'Content-Type': 'application/json',
},
params: {
shared_with_me: false,
include_tags: true,
},
})
})
test('Pending shares', async () => {
await getContents(false, false, true, false, [])
expect(axios.get).toHaveBeenCalledTimes(2)
expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending', {
headers: {
'Content-Type': 'application/json',
},
params: {
include_tags: true,
},
})
expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending', {
headers: {
'Content-Type': 'application/json',
},
params: {
include_tags: true,
},
})
})
test('Deleted shares', async () => {
await getContents(false, true, false, false, [])
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', {
headers: {
'Content-Type': 'application/json',
},
params: {
shared_with_me: false,
include_tags: true,
},
})
})
test('Unknown owner', async () => {
jest.spyOn(auth, 'getCurrentUser').mockReturnValue(null)
const results = await getContents(false, true, false, false, [])
expect(results.folder.owner).toEqual(null)
})
})
describe('SharingService filtering', () => {
beforeAll(() => {
jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => {
return {
data: {
ocs: {
meta: {
status: 'ok',
statuscode: 200,
message: 'OK',
},
data: [
{
id: '62',
share_type: Type.SHARE_TYPE_USER,
uid_owner: 'test',
displayname_owner: 'test',
permissions: 31,
stime: 1688666292,
expiration: '2023-07-13 00:00:00',
token: null,
path: '/Collaborators',
item_type: 'folder',
item_permissions: 31,
mimetype: 'httpd/unix-directory',
storage: 224,
item_source: 419413,
file_source: 419413,
file_parent: 419336,
file_target: '/Collaborators',
item_size: 41434,
item_mtime: 1688662980,
},
],
},
},
}
})
})
afterAll(() => {
jest.restoreAllMocks()
})
test('Shared with others filtering', async () => {
const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_USER])
expect(axios.get).toHaveBeenCalledTimes(1)
expect(shares.contents).toHaveLength(1)
expect(shares.contents[0].fileid).toBe(419413)
expect(shares.contents[0]).toBeInstanceOf(Folder)
})
test('Shared with others filtering empty', async () => {
const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_LINK])
expect(axios.get).toHaveBeenCalledTimes(1)
expect(shares.contents).toHaveLength(0)
})
})
describe('SharingService share to Node mapping', () => {
const shareFile = {
id: '66',
share_type: 0,
uid_owner: 'test',
displayname_owner: 'test',
permissions: 19,
can_edit: true,
can_delete: true,
stime: 1688721609,
parent: null,
expiration: '2023-07-14 00:00:00',
token: null,
uid_file_owner: 'test',
note: '',
label: null,
displayname_file_owner: 'test',
path: '/document.md',
item_type: 'file',
item_permissions: 27,
mimetype: 'text/markdown',
has_preview: true,
storage_id: 'home::test',
storage: 224,
item_source: 530936,
file_source: 530936,
file_parent: 419336,
file_target: '/document.md',
item_size: 123,
item_mtime: 1688721600,
share_with: 'user00',
share_with_displayname: 'User00',
share_with_displayname_unique: 'user00@domain.com',
status: {
status: 'away',
message: null,
icon: null,
clearAt: null,
},
mail_send: 0,
hide_download: 0,
attributes: null,
tags: [],
}
const shareFolder = {
id: '67',
share_type: 0,
uid_owner: 'test',
displayname_owner: 'test',
permissions: 31,
can_edit: true,
can_delete: true,
stime: 1688721629,
parent: null,
expiration: '2023-07-14 00:00:00',
token: null,
uid_file_owner: 'test',
note: '',
label: null,
displayname_file_owner: 'test',
path: '/Folder',
item_type: 'folder',
item_permissions: 31,
mimetype: 'httpd/unix-directory',
has_preview: false,
storage_id: 'home::test',
storage: 224,
item_source: 531080,
file_source: 531080,
file_parent: 419336,
file_target: '/Folder',
item_size: 0,
item_mtime: 1688721623,
share_with: 'user00',
share_with_displayname: 'User00',
share_with_displayname_unique: 'user00@domain.com',
status: {
status: 'away',
message: null,
icon: null,
clearAt: null,
},
mail_send: 0,
hide_download: 0,
attributes: null,
tags: [window.OC.TAG_FAVORITE],
}
test('File', async () => {
jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
data: {
ocs: {
data: [shareFile],
},
},
}))
const shares = await getContents(false, true, false, false)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(shares.contents).toHaveLength(1)
const file = shares.contents[0] as File
expect(file).toBeInstanceOf(File)
expect(file.fileid).toBe(530936)
expect(file.source).toBe('http://localhost/remote.php/dav/files/test/document.md')
expect(file.owner).toBe('test')
expect(file.mime).toBe('text/markdown')
expect(file.mtime).toBeInstanceOf(Date)
expect(file.size).toBe(123)
expect(file.permissions).toBe(27)
expect(file.root).toBe('/files/test')
expect(file.attributes).toBeInstanceOf(Object)
expect(file.attributes['has-preview']).toBe(true)
expect(file.attributes.previewUrl).toBe('/index.php/core/preview?fileId=530936&x=32&y=32&forceIcon=0')
expect(file.attributes.favorite).toBe(0)
})
test('Folder', async () => {
jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
data: {
ocs: {
data: [shareFolder],
},
},
}))
const shares = await getContents(false, true, false, false)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(shares.contents).toHaveLength(1)
const folder = shares.contents[0] as Folder
expect(folder).toBeInstanceOf(Folder)
expect(folder.fileid).toBe(531080)
expect(folder.source).toBe('http://localhost/remote.php/dav/files/test/Folder')
expect(folder.owner).toBe('test')
expect(folder.mime).toBe('httpd/unix-directory')
expect(folder.mtime).toBeInstanceOf(Date)
expect(folder.size).toBe(0)
expect(folder.permissions).toBe(31)
expect(folder.root).toBe('/files/test')
expect(folder.attributes).toBeInstanceOf(Object)
expect(folder.attributes['has-preview']).toBe(false)
expect(folder.attributes.previewUrl).toBeUndefined()
expect(folder.attributes.favorite).toBe(1)
})
test('Error', async () => {
jest.spyOn(logger, 'error').mockImplementationOnce(() => {})
jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({
data: {
ocs: {
data: [{}],
},
},
}))
const shares = await getContents(false, true, false, false)
expect(shares.contents).toHaveLength(0)
expect(logger.error).toHaveBeenCalledTimes(1)
})
})

45
apps/files_sharing/src/services/SharingService.ts

@ -26,11 +26,12 @@ import type { ContentsWithRoot } from '../../../files/src/services/Navigation'
import { Folder, File } from '@nextcloud/files'
import { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { rootPath } from '../../../files/src/services/WebdavClient'
import axios from '@nextcloud/axios'
import logger from './logger'
type OCSResponse = {
export const rootPath = `/files/${getCurrentUser()?.uid}`
export type OCSResponse = {
ocs: {
meta: {
status: string
@ -47,19 +48,20 @@ const headers = {
const ocsEntryToNode = function(ocsEntry: any): Folder | File | null {
try {
const Node = ocsEntry?.item_type === 'folder' ? Folder : File
const isFolder = ocsEntry?.item_type === 'folder'
const hasPreview = ocsEntry?.has_preview === true
const Node = isFolder ? Folder : File
// Sometimes it's an int, sometimes it contains the identifier like "ocinternal:123"
const fileid = ocsEntry.file_source
const previewUrl = generateUrl('/core/preview?fileId={fileid}&x=32&y=32&forceIcon=0', { fileid })
const previewUrl = hasPreview ? generateUrl('/core/preview?fileId={fileid}&x=32&y=32&forceIcon=0', { fileid }) : undefined
// Generate path and strip double slashes
const path = ocsEntry?.path || ocsEntry.file_target
const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replace(/\/\//, '/'))
const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replaceAll(/\/\//gm, '/'))
// Prefer share time if more recent than mtime
let mtime = ocsEntry?.mtime ? new Date((ocsEntry.mtime) * 1000) : undefined
if (ocsEntry?.stime > (ocsEntry?.mtime || 0)) {
// Prefer share time if more recent than item mtime
let mtime = ocsEntry?.item_mtime ? new Date((ocsEntry.item_mtime) * 1000) : undefined
if (ocsEntry?.stime > (ocsEntry?.item_mtime || 0)) {
mtime = new Date((ocsEntry.stime) * 1000)
}
@ -69,12 +71,13 @@ const ocsEntryToNode = function(ocsEntry: any): Folder | File | null {
owner: ocsEntry?.uid_owner,
mime: ocsEntry?.mimetype,
mtime,
size: ocsEntry?.size || undefined,
permissions: ocsEntry?.permissions,
size: ocsEntry?.item_size,
permissions: ocsEntry?.item_permissions || ocsEntry?.permissions,
root: rootPath,
attributes: {
...ocsEntry,
previewUrl,
'has-preview': hasPreview,
favorite: ocsEntry?.tags?.includes(window.OC.TAG_FAVORITE) ? 1 : 0,
},
})
@ -86,8 +89,7 @@ const ocsEntryToNode = function(ocsEntry: any): Folder | File | null {
const getShares = function(shared_with_me = false): AxiosPromise<OCSResponse> {
const url = generateOcsUrl('apps/files_sharing/api/v1/shares')
return axios({
url,
return axios.get(url, {
headers,
params: {
shared_with_me,
@ -101,13 +103,12 @@ const getSharedWithYou = function(): AxiosPromise<OCSResponse> {
}
const getSharedWithOthers = function(): AxiosPromise<OCSResponse> {
return getShares(false)
return getShares()
}
const getRemoteShares = function(): AxiosPromise<OCSResponse> {
const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares')
return axios({
url,
return axios.get(url, {
headers,
params: {
include_tags: true,
@ -117,8 +118,7 @@ const getRemoteShares = function(): AxiosPromise<OCSResponse> {
const getPendingShares = function(): AxiosPromise<OCSResponse> {
const url = generateOcsUrl('apps/files_sharing/api/v1/shares/pending')
return axios({
url,
return axios.get(url, {
headers,
params: {
include_tags: true,
@ -128,8 +128,7 @@ const getPendingShares = function(): AxiosPromise<OCSResponse> {
const getRemotePendingShares = function(): AxiosPromise<OCSResponse> {
const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares/pending')
return axios({
url,
return axios.get(url, {
headers,
params: {
include_tags: true,
@ -139,8 +138,7 @@ const getRemotePendingShares = function(): AxiosPromise<OCSResponse> {
const getDeletedShares = function(): AxiosPromise<OCSResponse> {
const url = generateOcsUrl('apps/files_sharing/api/v1/deletedshares')
return axios({
url,
return axios.get(url, {
headers,
params: {
include_tags: true,
@ -176,8 +174,9 @@ export const getContents = async (sharedWithYou = true, sharedWithOthers = true,
folder: new Folder({
id: 0,
source: generateRemoteUrl('dav' + rootPath),
owner: getCurrentUser()?.uid || '',
owner: getCurrentUser()?.uid || null,
}),
contents,
}
}

125
apps/files_sharing/src/views/shares.spec.ts

@ -0,0 +1,125 @@
/**
* @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* eslint-disable n/no-extraneous-import */
import { expect } from '@jest/globals'
import axios from '@nextcloud/axios'
import { type Navigation } from '../../../files/src/services/Navigation'
import { type OCSResponse } from '../services/SharingService'
import NavigationService from '../../../files/src/services/Navigation'
import registerSharingViews from './shares'
import '../main'
import { Folder } from '@nextcloud/files'
describe('Sharing views definition', () => {
let Navigation
beforeEach(() => {
Navigation = new NavigationService()
window.OCP = { Files: { Navigation } }
})
afterAll(() => {
delete window.OCP
})
test('Default values', () => {
jest.spyOn(Navigation, 'register')
expect(Navigation.views.length).toBe(0)
registerSharingViews()
const shareOverviewView = Navigation.views.find(view => view.id === 'shareoverview') as Navigation
const sharesChildViews = Navigation.views.filter(view => view.parent === 'shareoverview') as Navigation[]
expect(Navigation.register).toHaveBeenCalledTimes(6)
// one main view and no children
expect(Navigation.views.length).toBe(6)
expect(shareOverviewView).toBeDefined()
expect(sharesChildViews.length).toBe(5)
expect(shareOverviewView?.id).toBe('shareoverview')
expect(shareOverviewView?.name).toBe('Shares')
expect(shareOverviewView?.caption).toBe('Overview of shared files.')
expect(shareOverviewView?.icon).toBe('<svg>SvgMock</svg>')
expect(shareOverviewView?.order).toBe(20)
expect(shareOverviewView?.columns).toStrictEqual([])
expect(shareOverviewView?.getContents).toBeDefined()
const dataProvider = [
{ id: 'sharingin', name: 'Shared with you', caption: 'List of files that are shared with you.' },
{ id: 'sharingout', name: 'Shared with others', caption: 'List of files that you shared with others.' },
{ id: 'sharinglinks', name: 'Shared by link', caption: 'List of files that are shared by link.' },
{ id: 'deletedshares', name: 'Deleted shares', caption: 'List of shares that you removed yourself from.' },
{ id: 'pendingshares', name: 'Pending shares', caption: 'List of unapproved shares.' },
]
sharesChildViews.forEach((view, index) => {
expect(view?.id).toBe(dataProvider[index].id)
expect(view?.parent).toBe('shareoverview')
expect(view?.name).toBe(dataProvider[index].name)
expect(view?.caption).toBe(dataProvider[index].caption)
expect(view?.icon).toBe('<svg>SvgMock</svg>')
expect(view?.order).toBe(index + 1)
expect(view?.columns).toStrictEqual([])
expect(view?.getContents).toBeDefined()
})
})
})
describe('Sharing views contents', () => {
let Navigation
beforeEach(() => {
Navigation = new NavigationService()
window.OCP = { Files: { Navigation } }
})
afterAll(() => {
delete window.OCP
})
test('Sharing overview get contents', async () => {
jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => {
return {
data: {
ocs: {
meta: {
status: 'ok',
statuscode: 200,
message: 'OK',
},
data: [],
},
} as OCSResponse,
}
})
registerSharingViews()
expect(Navigation.views.length).toBe(6)
Navigation.views.forEach(async (view: Navigation) => {
const content = await view.getContents('/')
expect(content.contents).toStrictEqual([])
expect(content.folder).toBeInstanceOf(Folder)
})
})
})

14
apps/files_sharing/src/views/shares.ts

@ -33,8 +33,8 @@ import ShareVariantSvg from '@mdi/svg/svg/share-variant.svg?raw'
import { getContents } from '../services/SharingService'
export const sharesViewId = 'shareoverview'
export const pendingSharesViewId = 'pendingshares'
export const deletedSharesViewId = 'deletedshares'
export const pendingSharesViewId = 'pendingshares'
export default () => {
const Navigation = window.OCP.Files.Navigation as NavigationService
@ -57,7 +57,7 @@ export default () => {
caption: t('files_sharing', 'List of files that are shared with you.'),
icon: AccountSvg,
order: 20,
order: 1,
parent: sharesViewId,
columns: [],
@ -71,7 +71,7 @@ export default () => {
caption: t('files_sharing', 'List of files that you shared with others.'),
icon: AccountGroupSvg,
order: 20,
order: 2,
parent: sharesViewId,
columns: [],
@ -82,10 +82,10 @@ export default () => {
Navigation.register({
id: 'sharinglinks',
name: t('files_sharing', 'Shared by link'),
caption: t('files_sharing', 'List of files that you shared with a share link.'),
caption: t('files_sharing', 'List of files that are shared by link.'),
icon: LinkSvg,
order: 20,
order: 3,
parent: sharesViewId,
columns: [],
@ -99,7 +99,7 @@ export default () => {
caption: t('files_sharing', 'List of shares that you removed yourself from.'),
icon: DeleteSvg,
order: 20,
order: 4,
parent: sharesViewId,
columns: [],
@ -113,7 +113,7 @@ export default () => {
caption: t('files_sharing', 'List of unapproved shares.'),
icon: AccountClockSvg,
order: 20,
order: 5,
parent: sharesViewId,
columns: [],

120
apps/files_sharing/tests/Controller/ShareAPIControllerTest.php

@ -576,6 +576,8 @@ class ShareAPIControllerTest extends TestCase {
$file->method('getPath')->willReturn('file');
$file->method('getStorage')->willReturn($storage);
$file->method('getParent')->willReturn($parentFolder);
$file->method('getSize')->willReturn(123465);
$file->method('getMTime')->willReturn(1234567890);
$file->method('getMimeType')->willReturn('myMimeType');
$folder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
@ -583,6 +585,8 @@ class ShareAPIControllerTest extends TestCase {
$folder->method('getPath')->willReturn('folder');
$folder->method('getStorage')->willReturn($storage);
$folder->method('getParent')->willReturn($parentFolder);
$folder->method('getSize')->willReturn(123465);
$folder->method('getMTime')->willReturn(1234567890);
$folder->method('getMimeType')->willReturn('myFolderMimeType');
[$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
@ -637,6 +641,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'status' => [],
'item_size' => 123465,
'item_mtime' => 1234567890,
'attributes' => null,
];
$data[] = [$share, $expected];
@ -689,6 +695,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123465,
'item_mtime' => 1234567890,
'attributes' => null,
];
$data[] = [$share, $expected];
@ -747,6 +755,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123465,
'item_mtime' => 1234567890,
'attributes' => null,
];
$data[] = [$share, $expected];
@ -3735,6 +3745,13 @@ class ShareAPIControllerTest extends TestCase {
$folder->method('getParent')->willReturn($parent);
$fileWithPreview->method('getParent')->willReturn($parent);
$file->method('getSize')->willReturn(123456);
$folder->method('getSize')->willReturn(123456);
$fileWithPreview->method('getSize')->willReturn(123456);
$file->method('getMTime')->willReturn(1234567890);
$folder->method('getMTime')->willReturn(1234567890);
$fileWithPreview->method('getMTime')->willReturn(1234567890);
$cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
$cache->method('getNumericStorageId')->willReturn(100);
$storage = $this->createMock(Storage::class);
@ -3772,7 +3789,7 @@ class ShareAPIControllerTest extends TestCase {
// User backend down
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_USER,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -3796,7 +3813,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipient',
'share_with_displayname_unique' => 'recipient',
'note' => 'personal note',
'label' => null,
'label' => '',
'mail_send' => 0,
'mimetype' => 'myMimeType',
'has_preview' => false,
@ -3804,13 +3821,15 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'status' => [],
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]',
], $share, [], false
];
// User backend up
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_USER,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiatorDN',
@ -3823,7 +3842,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'ownerDN',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -3842,6 +3861,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'status' => [],
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]',
], $share, [
['owner', $owner],
@ -3864,7 +3885,7 @@ class ShareAPIControllerTest extends TestCase {
// User backend down
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_USER,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -3877,7 +3898,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -3896,6 +3917,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'status' => [],
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -3914,7 +3937,7 @@ class ShareAPIControllerTest extends TestCase {
// User backend down
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_USER,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -3927,7 +3950,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'currentUser',
'displayname_file_owner' => 'currentUser',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -3946,6 +3969,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => true,
'can_delete' => true,
'status' => [],
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -3966,7 +3991,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_GROUP,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -3979,7 +4004,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -3996,6 +4021,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4014,7 +4041,7 @@ class ShareAPIControllerTest extends TestCase {
->setId(42);
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_GROUP,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4026,7 +4053,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -4043,6 +4070,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4064,7 +4093,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_LINK,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4097,6 +4126,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4119,7 +4150,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_LINK,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4151,6 +4182,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4170,7 +4203,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_REMOTE,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4182,7 +4215,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4199,6 +4232,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4218,7 +4253,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_REMOTE_GROUP,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4230,7 +4265,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4247,6 +4282,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4267,7 +4304,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_CIRCLE,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4280,7 +4317,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => '',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4298,6 +4335,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4316,7 +4355,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_CIRCLE,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4328,7 +4367,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => '',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4346,6 +4385,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4364,7 +4405,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_CIRCLE,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4376,7 +4417,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => '',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4394,6 +4435,8 @@ class ShareAPIControllerTest extends TestCase {
'hide_download' => 0,
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4427,7 +4470,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_EMAIL,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4439,7 +4482,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => '',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4459,6 +4502,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'password_expiration_time' => null,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4478,7 +4523,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_EMAIL,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4490,7 +4535,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
'note' => '',
'label' => null,
'label' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@ -4510,6 +4555,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => false,
'can_delete' => false,
'password_expiration_time' => null,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4529,7 +4576,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_USER,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4541,7 +4588,7 @@ class ShareAPIControllerTest extends TestCase {
'uid_file_owner' => 'currentUser',
'displayname_file_owner' => 'currentUser',
'note' => 'personal note',
'label' => null,
'label' => '',
'path' => 'fileWithPreview',
'item_type' => 'file',
'storage_id' => 'storageId',
@ -4560,6 +4607,8 @@ class ShareAPIControllerTest extends TestCase {
'can_edit' => true,
'can_delete' => true,
'status' => [],
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, [], false
];
@ -4659,6 +4708,9 @@ class ShareAPIControllerTest extends TestCase {
$file->method('getParent')->willReturn($parent);
$file->method('getSize')->willReturn(123456);
$file->method('getMTime')->willReturn(1234567890);
$cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
$cache->method('getNumericStorageId')->willReturn(100);
$storage = $this->createMock(Storage::class);
@ -4683,7 +4735,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_ROOM,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4712,6 +4764,8 @@ class ShareAPIControllerTest extends TestCase {
'label' => '',
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, false, []
];
@ -4730,7 +4784,7 @@ class ShareAPIControllerTest extends TestCase {
$result[] = [
[
'id' => 42,
'id' => '42',
'share_type' => IShare::TYPE_ROOM,
'uid_owner' => 'initiator',
'displayname_owner' => 'initiator',
@ -4759,6 +4813,8 @@ class ShareAPIControllerTest extends TestCase {
'label' => '',
'can_edit' => false,
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
'attributes' => null,
], $share, true, [
'share_with_displayname' => 'recipientRoomName'

125
apps/files_sharing/tests/js/appSpec.js

@ -1,125 +0,0 @@
/**
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* @author Jan-Christoph Borchardt <hey@jancborchardt.net>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Vincent Petry <vincent@nextcloud.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('OCA.Sharing.App tests', function() {
var App = OCA.Sharing.App;
var fileListIn;
var fileListOut;
beforeEach(function() {
$('#testArea').append(
'<div id="app-navigation">' +
'<ul><li data-id="files"><a>Files</a></li>' +
'<li data-id="sharingin"><a></a></li>' +
'<li data-id="sharingout"><a></a></li>' +
'</ul></div>' +
'<div id="app-content">' +
'<div id="app-content-files" class="hidden">' +
'</div>' +
'<div id="app-content-sharingin" class="hidden">' +
'</div>' +
'<div id="app-content-sharingout" class="hidden">' +
'</div>' +
'</div>' +
'</div>'
);
fileListIn = App.initSharingIn($('#app-content-sharingin'));
fileListOut = App.initSharingOut($('#app-content-sharingout'));
});
afterEach(function() {
App.destroy();
});
describe('initialization', function() {
it('inits sharing-in list on show', function() {
expect(fileListIn._sharedWithUser).toEqual(true);
});
it('inits sharing-out list on show', function() {
expect(fileListOut._sharedWithUser).toBeFalsy();
});
});
describe('file actions', function() {
it('provides default file actions', function() {
_.each([fileListIn, fileListOut], function(fileList) {
var fileActions = fileList.fileActions;
expect(fileActions.actions.all).toBeDefined();
expect(fileActions.actions.all.Delete).toBeDefined();
expect(fileActions.actions.all.Rename).toBeDefined();
expect(fileActions.actions.all.Download).toBeDefined();
expect(fileActions.defaults.dir).toEqual('Open');
});
});
it('provides custom file actions', function() {
var actionStub = sinon.stub();
// regular file action
OCA.Files.fileActions.register(
'all',
'RegularTest',
OC.PERMISSION_READ,
OC.imagePath('core', 'actions/shared'),
actionStub
);
App._inFileList = null;
fileListIn = App.initSharingIn($('#app-content-sharingin'));
expect(fileListIn.fileActions.actions.all.RegularTest).toBeDefined();
});
it('redirects to files app when opening a directory', function() {
var oldList = OCA.Files.App.fileList;
// dummy new list to make sure it exists
OCA.Files.App.fileList = new OCA.Files.FileList($('<table><thead></thead><tbody></tbody></table>'));
var setActiveViewStub = sinon.stub(OCA.Files.App, 'setActiveView');
// create dummy table so we can click the dom
var $table = '<table><thead></thead><tbody class="files-fileList"></tbody></table>';
$('#app-content-sharingin').append($table);
App._inFileList = null;
fileListIn = App.initSharingIn($('#app-content-sharingin'));
fileListIn.setFiles([{
name: 'testdir',
type: 'dir',
path: '/somewhere/inside/subdir',
counterParts: ['user2'],
shareOwner: 'user2'
}]);
fileListIn.findFileEl('testdir').find('td .nametext').click();
expect(OCA.Files.App.fileList.getCurrentDirectory()).toEqual('/somewhere/inside/subdir/testdir');
expect(setActiveViewStub.calledOnce).toEqual(true);
expect(setActiveViewStub.calledWith('files')).toEqual(true);
setActiveViewStub.restore();
// restore old list
OCA.Files.App.fileList = oldList;
});
});
});

41
build/integration/sharing_features/sharing-v1-part4.feature

@ -0,0 +1,41 @@
Feature: sharing
Background:
Given using api version "1"
Given using new dav path
# See sharing-v1-part3.feature
Scenario: Creating a new share of a file shows size and mtime
Given user "user0" exists
And user "user1" exists
And As an "user0"
And parameter "shareapi_default_permissions" of app "core" is set to "7"
When creating a share with
| path | welcome.txt |
| shareWith | user1 |
| shareType | 0 |
And the OCS status code should be "100"
And the HTTP status code should be "200"
And Getting info of last share
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And Share fields of last share match with
| item_size | A_NUMBER |
| item_mtime | A_NUMBER |
Scenario: Creating a new share of a file you own shows the file permissions
Given user "user0" exists
And user "user1" exists
And As an "user0"
And parameter "shareapi_default_permissions" of app "core" is set to "7"
When creating a share with
| path | welcome.txt |
| shareWith | user1 |
| shareType | 0 |
And the OCS status code should be "100"
And the HTTP status code should be "200"
And Getting info of last share
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And Share fields of last share match with
| item_permissions | 27 |
Loading…
Cancel
Save