Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>pull/45652/head
parent
be884eeaec
commit
4a90d5328c
@ -0,0 +1,49 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import { copyFile, getRowForFile, moveFile, navigateToFolder } from '../../files/FilesUtils.ts' |
||||
import { getShareUrl, setupPublicShare } from './setup-public-share.ts' |
||||
|
||||
describe('files_sharing: Public share - copy and move files', { testIsolation: true }, () => { |
||||
|
||||
beforeEach(() => { |
||||
setupPublicShare() |
||||
.then(() => cy.logout()) |
||||
.then(() => cy.visit(getShareUrl())) |
||||
}) |
||||
|
||||
it('Can copy a file to new folder', () => { |
||||
getRowForFile('foo.txt').should('be.visible') |
||||
getRowForFile('subfolder').should('be.visible') |
||||
|
||||
copyFile('foo.txt', 'subfolder') |
||||
|
||||
// still visible
|
||||
getRowForFile('foo.txt').should('be.visible') |
||||
navigateToFolder('subfolder') |
||||
|
||||
cy.url().should('contain', 'dir=/subfolder') |
||||
getRowForFile('foo.txt').should('be.visible') |
||||
getRowForFile('bar.txt').should('be.visible') |
||||
getRowForFile('subfolder').should('not.exist') |
||||
}) |
||||
|
||||
it('Can move a file to new folder', () => { |
||||
getRowForFile('foo.txt').should('be.visible') |
||||
getRowForFile('subfolder').should('be.visible') |
||||
|
||||
moveFile('foo.txt', 'subfolder') |
||||
|
||||
// wait until visible again
|
||||
getRowForFile('subfolder').should('be.visible') |
||||
|
||||
// file should be moved -> not exist anymore
|
||||
getRowForFile('foo.txt').should('not.exist') |
||||
navigateToFolder('subfolder') |
||||
|
||||
cy.url().should('contain', 'dir=/subfolder') |
||||
getRowForFile('foo.txt').should('be.visible') |
||||
getRowForFile('subfolder').should('not.exist') |
||||
}) |
||||
}) |
@ -0,0 +1,141 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
// @ts-expect-error The package is currently broken - but works...
|
||||
import { deleteDownloadsFolderBeforeEach } from 'cypress-delete-downloads-folder' |
||||
|
||||
import { zipFileContains } from '../../../support/utils/assertions.ts' |
||||
import { getRowForFile, triggerActionForFile } from '../../files/FilesUtils.ts' |
||||
import { getShareUrl, setupPublicShare } from './setup-public-share.ts' |
||||
|
||||
describe('files_sharing: Public share - downloading files', { testIsolation: true }, () => { |
||||
|
||||
const shareName = 'shared' |
||||
|
||||
before(() => setupPublicShare()) |
||||
|
||||
deleteDownloadsFolderBeforeEach() |
||||
|
||||
beforeEach(() => { |
||||
cy.logout() |
||||
cy.visit(getShareUrl()) |
||||
}) |
||||
|
||||
it('Can download all files', () => { |
||||
getRowForFile('foo.txt').should('be.visible') |
||||
|
||||
cy.get('[data-cy-files-list]').within(() => { |
||||
cy.findByRole('checkbox', { name: /Toggle selection for all files/i }) |
||||
.should('exist') |
||||
.check({ force: true }) |
||||
|
||||
// see that two files are selected
|
||||
cy.contains('2 selected').should('be.visible') |
||||
|
||||
// click download
|
||||
cy.findByRole('button', { name: 'Download (selected)' }) |
||||
.should('be.visible') |
||||
.click() |
||||
|
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/${shareName}.zip`, null, { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 30) |
||||
// Check all files are included
|
||||
.and(zipFileContains([ |
||||
'foo.txt', |
||||
'subfolder/', |
||||
'subfolder/bar.txt', |
||||
])) |
||||
}) |
||||
}) |
||||
|
||||
it('Can download selected files', () => { |
||||
getRowForFile('subfolder') |
||||
.should('be.visible') |
||||
|
||||
cy.get('[data-cy-files-list]').within(() => { |
||||
getRowForFile('subfolder') |
||||
.findByRole('checkbox') |
||||
.check({ force: true }) |
||||
|
||||
// see that two files are selected
|
||||
cy.contains('1 selected').should('be.visible') |
||||
|
||||
// click download
|
||||
cy.findByRole('button', { name: 'Download (selected)' }) |
||||
.should('be.visible') |
||||
.click() |
||||
|
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/subfolder.zip`, null, { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 30) |
||||
// Check all files are included
|
||||
.and(zipFileContains([ |
||||
'subfolder/', |
||||
'subfolder/bar.txt', |
||||
])) |
||||
}) |
||||
}) |
||||
|
||||
it('Can download folder by action', () => { |
||||
getRowForFile('subfolder') |
||||
.should('be.visible') |
||||
|
||||
cy.get('[data-cy-files-list]').within(() => { |
||||
triggerActionForFile('subfolder', 'download') |
||||
|
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/subfolder.zip`, null, { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 30) |
||||
// Check all files are included
|
||||
.and(zipFileContains([ |
||||
'subfolder/', |
||||
'subfolder/bar.txt', |
||||
])) |
||||
}) |
||||
}) |
||||
|
||||
it('Can download file by action', () => { |
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
|
||||
cy.get('[data-cy-files-list]').within(() => { |
||||
triggerActionForFile('foo.txt', 'download') |
||||
|
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/foo.txt`, 'utf-8', { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 5) |
||||
.and('contain', '<content>foo</content>') |
||||
}) |
||||
}) |
||||
|
||||
it('Can download file by selection', () => { |
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
|
||||
cy.get('[data-cy-files-list]').within(() => { |
||||
getRowForFile('foo.txt') |
||||
.findByRole('checkbox') |
||||
.check({ force: true }) |
||||
|
||||
cy.findByRole('button', { name: 'Download (selected)' }) |
||||
.click() |
||||
|
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/foo.txt`, 'utf-8', { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 5) |
||||
.and('contain', '<content>foo</content>') |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,32 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import { getRowForFile, haveValidity, triggerActionForFile } from '../../files/FilesUtils.ts' |
||||
import { getShareUrl, setupPublicShare } from './setup-public-share.ts' |
||||
|
||||
describe('files_sharing: Public share - renaming files', { testIsolation: true }, () => { |
||||
|
||||
beforeEach(() => { |
||||
setupPublicShare() |
||||
.then(() => cy.logout()) |
||||
.then(() => cy.visit(getShareUrl())) |
||||
}) |
||||
|
||||
it('can rename a file', () => { |
||||
// All are visible by default
|
||||
getRowForFile('foo.txt').should('be.visible') |
||||
|
||||
triggerActionForFile('foo.txt', 'rename') |
||||
|
||||
getRowForFile('foo.txt') |
||||
.findByRole('textbox', { name: 'Filename' }) |
||||
.should('be.visible') |
||||
.type('{selectAll}other.txt') |
||||
.should(haveValidity('')) |
||||
.type('{enter}') |
||||
|
||||
// See it is renamed
|
||||
getRowForFile('other.txt').should('be.visible') |
||||
}) |
||||
}) |
@ -0,0 +1,119 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import type { User } from '@nextcloud/cypress' |
||||
import { openSharingPanel } from '../FilesSharingUtils.ts' |
||||
|
||||
let user: User |
||||
let url: string |
||||
|
||||
/** |
||||
* URL of the share |
||||
*/ |
||||
export function getShareUrl() { |
||||
if (url === undefined) { |
||||
throw new Error('You need to setup the share first!') |
||||
} |
||||
return url |
||||
} |
||||
|
||||
/** |
||||
* Setup the available data |
||||
* @param shareName The name of the shared folder |
||||
*/ |
||||
function setupData(shareName: string) { |
||||
cy.mkdir(user, `/${shareName}`) |
||||
cy.mkdir(user, `/${shareName}/subfolder`) |
||||
cy.uploadContent(user, new Blob(['<content>foo</content>']), 'text/plain', `/${shareName}/foo.txt`) |
||||
cy.uploadContent(user, new Blob(['<content>bar</content>']), 'text/plain', `/${shareName}/subfolder/bar.txt`) |
||||
} |
||||
|
||||
/** |
||||
* Create a public link share |
||||
* @param shareName The name of the shared folder |
||||
*/ |
||||
function createShare(shareName: string) { |
||||
cy.login(user) |
||||
// open the files app
|
||||
cy.visit('/apps/files') |
||||
// open the sidebar
|
||||
openSharingPanel(shareName) |
||||
// create the share
|
||||
cy.intercept('POST', '**/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createShare') |
||||
cy.findByRole('button', { name: 'Create a new share link' }) |
||||
.click() |
||||
|
||||
// extract the link
|
||||
return cy.wait('@createShare') |
||||
.should(({ response }) => { |
||||
const { ocs } = response!.body |
||||
url = ocs?.data.url |
||||
expect(url).to.match(/^http:\/\//) |
||||
}) |
||||
.then(() => cy.wrap(url)) |
||||
} |
||||
|
||||
/** |
||||
* Adjust share permissions to be editable |
||||
*/ |
||||
function adjustSharePermission() { |
||||
// Update the share to be a file drop
|
||||
cy.findByRole('list', { name: 'Link shares' }) |
||||
.findAllByRole('listitem') |
||||
.first() |
||||
.findByRole('button', { name: /Actions/i }) |
||||
.click() |
||||
cy.findByRole('menuitem', { name: /Customize link/i }) |
||||
.should('be.visible') |
||||
.click() |
||||
|
||||
// Enable upload-edit
|
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle]') |
||||
.should('be.visible') |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle="upload-edit"]') |
||||
.click() |
||||
// save changes
|
||||
cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('updateShare') |
||||
cy.findByRole('button', { name: 'Update share' }) |
||||
.click() |
||||
cy.wait('@updateShare') |
||||
} |
||||
|
||||
/** |
||||
* Setup a public share and backup the state. |
||||
* If the setup was already done in another run, the state will be restored. |
||||
* |
||||
* @return The URL of the share |
||||
*/ |
||||
export function setupPublicShare(): Cypress.Chainable<string> { |
||||
const shareName = 'shared' |
||||
|
||||
return cy.task('getVariable', { key: 'public-share-data' }) |
||||
.then((data) => { |
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const { dataSnapshot, dbSnapshot, shareUrl } = data as any || {} |
||||
if (dataSnapshot && dbSnapshot) { |
||||
cy.restoreDB(dbSnapshot) |
||||
cy.restoreData(dataSnapshot) |
||||
url = shareUrl |
||||
return cy.wrap(shareUrl as string) |
||||
} else { |
||||
cy.restoreData() |
||||
cy.restoreDB() |
||||
|
||||
const shareData: Record<string, unknown> = {} |
||||
return cy.createRandomUser() |
||||
.then(($user) => { user = $user }) |
||||
.then(() => setupData(shareName)) |
||||
.then(() => createShare(shareName)) |
||||
.then((value) => { shareData.shareUrl = value }) |
||||
.then(() => adjustSharePermission()) |
||||
.then(() => cy.backupDB().then((value) => { shareData.dbSnapshot = value })) |
||||
.then(() => cy.backupData([user.userId]).then((value) => { shareData.dataSnapshot = value })) |
||||
.then(() => cy.task('setVariable', { key: 'public-share-data', value: shareData })) |
||||
.then(() => cy.log(`Public share setup, URL: ${shareData.shareUrl}`)) |
||||
.then(() => cy.wrap(url)) |
||||
} |
||||
}) |
||||
} |
@ -0,0 +1,169 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import { getRowForFile } from '../../files/FilesUtils.ts' |
||||
import { openSharingPanel } from '../FilesSharingUtils.ts' |
||||
|
||||
describe('files_sharing: Public share - File drop', { testIsolation: true }, () => { |
||||
|
||||
let shareUrl: string |
||||
let user: string |
||||
const shareName = 'shared' |
||||
|
||||
before(() => { |
||||
cy.createRandomUser().then(($user) => { |
||||
user = $user.userId |
||||
cy.mkdir($user, `/${shareName}`) |
||||
cy.uploadContent($user, new Blob(['content']), 'text/plain', `/${shareName}/foo.txt`) |
||||
cy.login($user) |
||||
// open the files app
|
||||
cy.visit('/apps/files') |
||||
// open the sidebar
|
||||
openSharingPanel(shareName) |
||||
// create the share
|
||||
cy.intercept('POST', '**/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createShare') |
||||
cy.findByRole('button', { name: 'Create a new share link' }) |
||||
.click() |
||||
// extract the link
|
||||
cy.wait('@createShare').should(({ response }) => { |
||||
const { ocs } = response?.body ?? {} |
||||
shareUrl = ocs?.data.url |
||||
expect(shareUrl).to.match(/^http:\/\//) |
||||
}) |
||||
|
||||
// Update the share to be a file drop
|
||||
cy.findByRole('list', { name: 'Link shares' }) |
||||
.findAllByRole('listitem') |
||||
.first() |
||||
.findByRole('button', { name: /Actions/i }) |
||||
.click() |
||||
cy.findByRole('menuitem', { name: /Customize link/i }) |
||||
.should('be.visible') |
||||
.click() |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle]') |
||||
.should('be.visible') |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle="file-drop"]') |
||||
.click() |
||||
|
||||
// save the update
|
||||
cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('updateShare') |
||||
cy.findByRole('button', { name: 'Update share' }) |
||||
.click() |
||||
cy.wait('@updateShare') |
||||
}) |
||||
}) |
||||
|
||||
beforeEach(() => { |
||||
cy.logout() |
||||
cy.visit(shareUrl) |
||||
}) |
||||
|
||||
it('Cannot see share content', () => { |
||||
cy.contains(`Upload files to ${shareName}`) |
||||
.should('be.visible') |
||||
|
||||
// foo exists
|
||||
cy.userFileExists(user, `${shareName}/foo.txt`).should('be.gt', 0) |
||||
// but is not visible
|
||||
getRowForFile('foo.txt') |
||||
.should('not.exist') |
||||
}) |
||||
|
||||
it('Can only see upload files and upload folders menu entries', () => { |
||||
cy.contains(`Upload files to ${shareName}`) |
||||
.should('be.visible') |
||||
|
||||
cy.findByRole('button', { name: 'New' }) |
||||
.should('be.visible') |
||||
.click() |
||||
// See upload actions
|
||||
cy.findByRole('menuitem', { name: 'Upload files' }) |
||||
.should('be.visible') |
||||
cy.findByRole('menuitem', { name: 'Upload folders' }) |
||||
.should('be.visible') |
||||
// But no other
|
||||
cy.findByRole('menu') |
||||
.findAllByRole('menuitem') |
||||
.should('have.length', 2) |
||||
}) |
||||
|
||||
it('Can only see dedicated upload button', () => { |
||||
cy.contains(`Upload files to ${shareName}`) |
||||
.should('be.visible') |
||||
|
||||
cy.findByRole('button', { name: 'Upload' }) |
||||
.should('be.visible') |
||||
.click() |
||||
// See upload actions
|
||||
cy.findByRole('menuitem', { name: 'Upload files' }) |
||||
.should('be.visible') |
||||
cy.findByRole('menuitem', { name: 'Upload folders' }) |
||||
.should('be.visible') |
||||
// But no other
|
||||
cy.findByRole('menu') |
||||
.findAllByRole('menuitem') |
||||
.should('have.length', 2) |
||||
}) |
||||
|
||||
it('Can upload files', () => { |
||||
cy.contains(`Upload files to ${shareName}`) |
||||
.should('be.visible') |
||||
|
||||
const { promise, resolve } = Promise.withResolvers() |
||||
cy.intercept('PUT', '**/public.php/dav/files/**', (request) => { |
||||
if (request.url.includes('first.txt')) { |
||||
// just continue the first one
|
||||
request.continue() |
||||
} else { |
||||
// We delay the second one until we checked that the progress bar is visible
|
||||
request.on('response', async () => { await promise }) |
||||
} |
||||
}).as('uploadFile') |
||||
|
||||
cy.get('[data-cy-files-sharing-file-drop] input[type="file"]') |
||||
.should('exist') |
||||
.selectFile([ |
||||
{ fileName: 'first.txt', contents: Buffer.from('8 bytes!') }, |
||||
{ fileName: 'second.md', contents: Buffer.from('x'.repeat(128)) }, |
||||
], { force: true }) |
||||
|
||||
cy.wait('@uploadFile') |
||||
|
||||
cy.findByRole('progressbar') |
||||
.should('be.visible') |
||||
.and((el) => { expect(Number.parseInt(el.attr('value') ?? '0')).be.gte(50) }) |
||||
// continue second request
|
||||
.then(() => resolve(null)) |
||||
|
||||
cy.wait('@uploadFile') |
||||
|
||||
// Check files uploaded
|
||||
cy.userFileExists(user, `${shareName}/first.txt`).should('eql', 8) |
||||
cy.userFileExists(user, `${shareName}/second.md`).should('eql', 128) |
||||
}) |
||||
|
||||
describe('Terms of service', { testIsolation: true }, () => { |
||||
before(() => cy.runOccCommand('config:app:set --value "TEST: Some disclaimer text" --type string core shareapi_public_link_disclaimertext')) |
||||
beforeEach(() => cy.visit(shareUrl)) |
||||
after(() => cy.runOccCommand('config:app:delete core shareapi_public_link_disclaimertext')) |
||||
|
||||
it('shows ToS on file-drop view', () => { |
||||
cy.contains(`Upload files to ${shareName}`) |
||||
.should('be.visible') |
||||
.should('contain.text', 'agree to the terms of service') |
||||
cy.findByRole('button', { name: /Terms of service/i }) |
||||
.should('be.visible') |
||||
.click() |
||||
|
||||
cy.findByRole('dialog', { name: 'Terms of service' }) |
||||
.should('contain.text', 'TEST: Some disclaimer text') |
||||
// close
|
||||
.findByRole('button', { name: 'Close' }) |
||||
.click() |
||||
|
||||
cy.findByRole('dialog', { name: 'Terms of service' }) |
||||
.should('not.exist') |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,104 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import { getActionButtonForFile, getRowForFile, navigateToFolder } from '../../files/FilesUtils.ts' |
||||
import { openSharingPanel } from '../FilesSharingUtils.ts' |
||||
|
||||
describe('files_sharing: Public share - View only', { testIsolation: true }, () => { |
||||
|
||||
let shareUrl: string |
||||
const shareName = 'shared' |
||||
|
||||
before(() => { |
||||
cy.createRandomUser().then(($user) => { |
||||
cy.mkdir($user, `/${shareName}`) |
||||
cy.mkdir($user, `/${shareName}/subfolder`) |
||||
cy.uploadContent($user, new Blob([]), 'text/plain', `/${shareName}/foo.txt`) |
||||
cy.uploadContent($user, new Blob([]), 'text/plain', `/${shareName}/subfolder/bar.txt`) |
||||
cy.login($user) |
||||
// open the files app
|
||||
cy.visit('/apps/files') |
||||
// open the sidebar
|
||||
openSharingPanel(shareName) |
||||
// create the share
|
||||
cy.intercept('POST', '**/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createShare') |
||||
cy.findByRole('button', { name: 'Create a new share link' }) |
||||
.click() |
||||
// extract the link
|
||||
cy.wait('@createShare').should(({ response }) => { |
||||
const { ocs } = response?.body ?? {} |
||||
shareUrl = ocs?.data.url |
||||
expect(shareUrl).to.match(/^http:\/\//) |
||||
}) |
||||
|
||||
// Update the share to be a view-only-no-download share
|
||||
cy.findByRole('list', { name: 'Link shares' }) |
||||
.findAllByRole('listitem') |
||||
.first() |
||||
.findByRole('button', { name: /Actions/i }) |
||||
.click() |
||||
cy.findByRole('menuitem', { name: /Customize link/i }) |
||||
.should('be.visible') |
||||
.click() |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle]') |
||||
.should('be.visible') |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle="read-only"]') |
||||
.click() |
||||
cy.findByRole('checkbox', { name: 'Hide download' }) |
||||
.check({ force: true }) |
||||
// save the update
|
||||
cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('updateShare') |
||||
cy.findByRole('button', { name: 'Update share' }) |
||||
.click() |
||||
cy.wait('@updateShare') |
||||
}) |
||||
}) |
||||
|
||||
beforeEach(() => { |
||||
cy.logout() |
||||
cy.visit(shareUrl) |
||||
}) |
||||
|
||||
it('Can see the files list', () => { |
||||
// foo exists
|
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
}) |
||||
|
||||
it('But no actions available', () => { |
||||
// foo exists
|
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
// but no actions
|
||||
getActionButtonForFile('foo.txt') |
||||
.should('not.exist') |
||||
|
||||
// TODO: We really need Viewer in the server repo.
|
||||
// So we could at least test viewing images
|
||||
}) |
||||
|
||||
it('Can navigate to subfolder', () => { |
||||
getRowForFile('subfolder') |
||||
.should('be.visible') |
||||
|
||||
navigateToFolder('subfolder') |
||||
|
||||
getRowForFile('bar.txt') |
||||
.should('be.visible') |
||||
|
||||
// but also no actions
|
||||
getActionButtonForFile('bar.txt') |
||||
.should('not.exist') |
||||
}) |
||||
|
||||
it('Cannot upload files', () => { |
||||
// wait for file list to be ready
|
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
|
||||
cy.contains('button', 'New') |
||||
.should('be.visible') |
||||
.and('be.disabled') |
||||
}) |
||||
}) |
@ -0,0 +1,107 @@ |
||||
/*! |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
import { getActionsForFile, getRowForFile, navigateToFolder } from '../../files/FilesUtils.ts' |
||||
import { openSharingPanel } from '../FilesSharingUtils.ts' |
||||
|
||||
describe('files_sharing: Public share - View only', { testIsolation: true }, () => { |
||||
|
||||
let shareUrl: string |
||||
const shareName = 'shared' |
||||
|
||||
before(() => { |
||||
cy.createRandomUser().then(($user) => { |
||||
cy.mkdir($user, `/${shareName}`) |
||||
cy.mkdir($user, `/${shareName}/subfolder`) |
||||
cy.uploadContent($user, new Blob(['content']), 'text/plain', `/${shareName}/foo.txt`) |
||||
cy.uploadContent($user, new Blob(['content']), 'text/plain', `/${shareName}/subfolder/bar.txt`) |
||||
cy.login($user) |
||||
// open the files app
|
||||
cy.visit('/apps/files') |
||||
// open the sidebar
|
||||
openSharingPanel(shareName) |
||||
// create the share
|
||||
cy.intercept('POST', '**/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createShare') |
||||
cy.findByRole('button', { name: 'Create a new share link' }) |
||||
.click() |
||||
// extract the link
|
||||
cy.wait('@createShare').should(({ response }) => { |
||||
const { ocs } = response?.body ?? {} |
||||
shareUrl = ocs?.data.url |
||||
expect(shareUrl).to.match(/^http:\/\//) |
||||
}) |
||||
|
||||
// Update the share to be a view-only-no-download share
|
||||
cy.findByRole('list', { name: 'Link shares' }) |
||||
.findAllByRole('listitem') |
||||
.first() |
||||
.findByRole('button', { name: /Actions/i }) |
||||
.click() |
||||
cy.findByRole('menuitem', { name: /Customize link/i }) |
||||
.should('be.visible') |
||||
.click() |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle]') |
||||
.should('be.visible') |
||||
cy.get('[data-cy-files-sharing-share-permissions-bundle="read-only"]') |
||||
.click() |
||||
// save the update
|
||||
cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('updateShare') |
||||
cy.findByRole('button', { name: 'Update share' }) |
||||
.click() |
||||
cy.wait('@updateShare') |
||||
}) |
||||
}) |
||||
|
||||
beforeEach(() => { |
||||
cy.logout() |
||||
cy.visit(shareUrl) |
||||
}) |
||||
|
||||
it('Can see the files list', () => { |
||||
// foo exists
|
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
}) |
||||
|
||||
it('Can navigate to subfolder', () => { |
||||
getRowForFile('subfolder') |
||||
.should('be.visible') |
||||
|
||||
navigateToFolder('subfolder') |
||||
|
||||
getRowForFile('bar.txt') |
||||
.should('be.visible') |
||||
}) |
||||
|
||||
it('Cannot upload files', () => { |
||||
// wait for file list to be ready
|
||||
getRowForFile('foo.txt') |
||||
.should('be.visible') |
||||
|
||||
cy.contains('button', 'New') |
||||
.should('be.visible') |
||||
.and('be.disabled') |
||||
}) |
||||
|
||||
it('Only download action is actions available', () => { |
||||
getActionsForFile('foo.txt') |
||||
.should('be.visible') |
||||
.click() |
||||
|
||||
// Only the download action
|
||||
cy.findByRole('menuitem', { name: 'Download' }) |
||||
.should('be.visible') |
||||
cy.findAllByRole('menuitem') |
||||
.should('have.length', 1) |
||||
|
||||
// Can download
|
||||
cy.findByRole('menuitem', { name: 'Download' }).click() |
||||
// check a file is downloaded
|
||||
const downloadsFolder = Cypress.config('downloadsFolder') |
||||
cy.readFile(`${downloadsFolder}/foo.txt`, 'utf-8', { timeout: 15000 }) |
||||
.should('exist') |
||||
.and('have.length.gt', 5) |
||||
.and('contain', 'content') |
||||
}) |
||||
}) |
Loading…
Reference in new issue