diff --git a/cypress/e2e/files_sharing/ShareOptionsType.ts b/cypress/e2e/files_sharing/ShareOptionsType.ts new file mode 100644 index 0000000000000..7c7807c23791d --- /dev/null +++ b/cypress/e2e/files_sharing/ShareOptionsType.ts @@ -0,0 +1,6 @@ +export type ShareOptions = { + enforcePassword?: boolean + enforceExpirationDate?: boolean + alwaysAskForPassword?: boolean + defaultExpirationDateSet?: boolean +} diff --git a/cypress/e2e/files_sharing/public-share/required-before-create.cy.ts b/cypress/e2e/files_sharing/public-share/required-before-create.cy.ts new file mode 100644 index 0000000000000..ec526c6f2e372 --- /dev/null +++ b/cypress/e2e/files_sharing/public-share/required-before-create.cy.ts @@ -0,0 +1,208 @@ +/*! + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import type { ShareContext } from './setup-public-share.ts' +import { setupData, createShare } from './setup-public-share.ts' + +describe('files_sharing: Before create checks', () => { + + let shareContext: ShareContext + + before(() => { + // Setup data for the shared folder once before all tests + cy.createRandomUser().then((randomUser) => { + shareContext = { + user: randomUser, + } + }) + }) + + afterEach(() => { + cy.runOccCommand('config:app:delete core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:delete core shareapi_default_expire_date') + cy.runOccCommand('config:app:delete core shareapi_enforce_expire_date') + cy.runOccCommand('config:app:delete core shareapi_expire_after_n_days') + }) + + it('Checks if user can create share when both password and expiration date are enforced', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_expire_date') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + + const shareName = 'passwordAndExpireEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforcePassword: true, + enforceExpirationDate: true, + defaultExpirationDateSet: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share when password is enforced and expiration date has a default set', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + + const shareName = 'passwordEnforcedDefaultExpire' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforcePassword: true, + defaultExpirationDateSet: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share when password is optionally requested and expiration date is enforced', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_expire_date') + + const shareName = 'defaultPasswordExpireEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforceExpirationDate: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share when password is optionally requested and expiration date have defaults set', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + + const shareName = 'defaultPasswordAndExpire' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + defaultExpirationDateSet: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with password enforced and expiration date set but not enforced', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_expire_date') + + const shareName = 'passwordEnforcedExpireSetNotEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforcePassword: true, + defaultExpirationDateSet: true, + enforceExpirationDate: false, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with both password and expiration date not enforced, but defaults set', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_expire_date') + + const shareName = 'defaultPasswordExpireNotEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + enforcePassword: false, + enforceExpirationDate: false, + defaultExpirationDateSet: true, + alwaysAskForPassword: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with password not enforced but expiration date enforced', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_expire_date') + + const shareName = 'noPasswordExpireEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforcePassword: false, + defaultExpirationDateSet: true, + enforceExpirationDate: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with password not enforced and expiration date has a default set', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_links_password') + + const shareName = 'defaultExpireNoPasswordEnforced' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + enforcePassword: false, + defaultExpirationDateSet: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with expiration date set and password not enforced', () => { + cy.runOccCommand('config:app:set --value yes core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value yes core shareapi_default_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_expire_after_n_days') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_links_password') + + const shareName = 'noPasswordExpireDefault' + setupData(shareContext, shareName) + createShare(shareContext, shareName, { + alwaysAskForPassword: true, + enforcePassword: false, + defaultExpirationDateSet: true, + }).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + + it('Checks if user can create share with password not enforced, expiration date not enforced, and no defaults set', () => { + cy.runOccCommand('config:app:set --value no core shareapi_enforce_links_password') + cy.runOccCommand('config:app:set --value no core shareapi_enforce_expire_date') + cy.runOccCommand('config:app:set --value no core shareapi_enable_link_password_by_default') + cy.runOccCommand('config:app:set --value no core shareapi_default_expire_date') + + const shareName = 'noPasswordNoExpireNoDefaults' + setupData(shareContext, shareName) + createShare(shareContext, shareName, null).then((shareUrl) => { + shareContext.url = shareUrl + cy.log(`Created share with URL: ${shareUrl}`) + }) + }) + +}) diff --git a/cypress/e2e/files_sharing/public-share/setup-public-share.ts b/cypress/e2e/files_sharing/public-share/setup-public-share.ts index d56c7dd188551..70c09f01c4b4b 100644 --- a/cypress/e2e/files_sharing/public-share/setup-public-share.ts +++ b/cypress/e2e/files_sharing/public-share/setup-public-share.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { User } from '@nextcloud/cypress' +import type { ShareOptions } from '../ShareOptionsType.ts' import { openSharingPanel } from '../FilesSharingUtils.ts' export interface ShareContext { @@ -42,18 +43,66 @@ export function setupData(context: ShareContext, shareName: string): void { cy.uploadContent(context.user, new Blob(['bar']), 'text/plain', `/${shareName}/subfolder/bar.txt`) } +/** + * Check the password state based on enforcement and default presence. + * + * @param enforced Whether the password is enforced. + * @param alwaysAskForPassword Wether the password should always be asked for. + */ +function checkPasswordState(enforced: boolean, alwaysAskForPassword: boolean) { + if (enforced) { + cy.contains('Password protection (enforced)').should('exist') + cy.contains('Enter a password') + .should('exist') + .and('not.be.disabled') + } else if (alwaysAskForPassword) { + cy.contains('Password protection').should('exist') + cy.contains('Enter a password') + .should('exist') + .and('not.be.disabled') + } +} + +/** + * Check the expiration date state based on enforcement and default presence. + * + * @param enforced Whether the expiration date is enforced. + * @param hasDefault Whether a default expiration date is set. + */ +function checkExpirationDateState(enforced: boolean, hasDefault: boolean) { + if (enforced) { + cy.contains('Enable link expiration (enforced)').should('exist') + cy.contains('Enter expiration date') + .should('exist') + .and('not.be.disabled') + } else if (hasDefault) { + cy.contains('Enable link expiration').should('exist') + cy.contains('Enter expiration date') + .should('exist') + .and('not.be.disabled') + } +} + /** * Create a public link share * @param context The current share context * @param shareName The name of the shared folder + * @param options The share options */ -export function createShare(context: ShareContext, shareName: string) { +export function createShare(context: ShareContext, shareName: string, options: ShareOptions | null = null) { cy.login(context.user) cy.visit('/apps/files') // Open the files app openSharingPanel(shareName) // Open the sharing sidebar cy.intercept('POST', '**/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createShare') cy.findByRole('button', { name: 'Create a new share link' }).click() + // Conduct optional checks based on the provided options + if (options) { + cy.get('.sharing-entry__actions').should('be.visible') // Wait for the dialog to open + checkPasswordState(options.enforcePassword ?? false, options.alwaysAskForPassword ?? false) + checkExpirationDateState(options.enforceExpirationDate ?? false, options.defaultExpirationDateSet ?? false) + cy.findByRole('button', { name: 'Create share' }).should('be.visible').click() + } // Extract the share link return cy.wait('@createShare')