test: Add end-to-end tests for new public share Vue UI
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