/*! * 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 { createShare, getShareUrl, openLinkShareDetails, setupPublicShare, type ShareContext } from './setup-public-share.ts' import { getRowForFile, getRowForFileId, triggerActionForFile, triggerActionForFileId } from '../../files/FilesUtils.ts' import { zipFileContains } from '../../../support/utils/assertions.ts' import type { User } from '@nextcloud/cypress' describe('files_sharing: Public share - downloading files', { testIsolation: true }, () => { // in general there is no difference except downloading // as file shares have the source of the share token but a different displayname describe('file share', () => { let fileId: number before(() => { cy.createRandomUser().then((user) => { const context: ShareContext = { user } cy.uploadContent(user, new Blob(['foo']), 'text/plain', '/file.txt') .then(({ headers }) => { fileId = Number.parseInt(headers['oc-fileid']) }) cy.login(user) createShare(context, 'file.txt') .then(() => cy.logout()) .then(() => cy.visit(context.url!)) }) }) it('can download the file', () => { getRowForFileId(fileId) .should('be.visible') getRowForFileId(fileId) .find('[data-cy-files-list-row-name]') .should((el) => expect(el.text()).to.match(/file\s*\.txt/)) // extension is sparated so there might be a space between triggerActionForFileId(fileId, 'download') // check a file is downloaded with the correct name const downloadsFolder = Cypress.config('downloadsFolder') cy.readFile(`${downloadsFolder}/file.txt`, 'utf-8', { timeout: 15000 }) .should('exist') .and('have.length.gt', 5) .and('contain', 'foo') }) }) describe('folder share', () => { 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}/download.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', 'foo') }) }) 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', 'foo') }) }) }) describe('download permission - link share', () => { let context: ShareContext beforeEach(() => { cy.createRandomUser().then((user) => { cy.mkdir(user, '/test') context = { user } createShare(context, 'test') cy.login(context.user) cy.visit('/apps/files') }) }) deleteDownloadsFolderBeforeEach() it('download permission is retained', () => { getRowForFile('test').should('be.visible') triggerActionForFile('test', 'details') openLinkShareDetails(0) cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('update') cy.findByRole('checkbox', { name: /hide download/i }) .should('exist') .and('not.be.checked') .check({ force: true }) cy.findByRole('checkbox', { name: /hide download/i }) .should('be.checked') cy.findByRole('button', { name: /update share/i }) .click() cy.wait('@update') openLinkShareDetails(0) cy.findByRole('checkbox', { name: /hide download/i }) .should('be.checked') cy.reload() getRowForFile('test').should('be.visible') triggerActionForFile('test', 'details') openLinkShareDetails(0) cy.findByRole('checkbox', { name: /hide download/i }) .should('be.checked') }) }) describe('download permission - mail share', () => { let user: User beforeEach(() => { cy.createRandomUser().then(($user) => { user = $user cy.mkdir(user, '/test') cy.login(user) cy.visit('/apps/files') }) }) it('download permission is retained', () => { getRowForFile('test').should('be.visible') triggerActionForFile('test', 'details') cy.findByRole('combobox', { name: /Enter external recipients/i }) .type('test@example.com') cy.get('.option[sharetype="4"][user="test@example.com"]') .parent('li') .click() cy.findByRole('button', { name: /advanced settings/i }) .should('be.visible') .click() cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('update') cy.findByRole('checkbox', { name: /hide download/i }) .should('exist') .and('not.be.checked') .check({ force: true }) cy.findByRole('button', { name: /save share/i }) .click() cy.wait('@update') openLinkShareDetails(1) cy.findByRole('button', { name: /advanced settings/i }) .click() cy.findByRole('checkbox', { name: /hide download/i }) .should('exist') .and('be.checked') }) }) })