From a8ac07ae2972074668730ae01c329dd888b2bafb Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 15 Jan 2025 15:47:33 +0100 Subject: [PATCH] test: Add end-to-end test for share expiration date Signed-off-by: Ferdinand Thiessen --- .../e2e/files_sharing/FilesSharingUtils.ts | 21 ++- cypress/e2e/files_sharing/expiry-date.cy.ts | 128 ++++++++++++++++++ 2 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 cypress/e2e/files_sharing/expiry-date.cy.ts diff --git a/cypress/e2e/files_sharing/FilesSharingUtils.ts b/cypress/e2e/files_sharing/FilesSharingUtils.ts index 6e97a757a1529..2e7c18f6213ac 100644 --- a/cypress/e2e/files_sharing/FilesSharingUtils.ts +++ b/cypress/e2e/files_sharing/FilesSharingUtils.ts @@ -12,6 +12,7 @@ export interface ShareSetting { share: boolean download: boolean note: string + expiryDate: Date } export function createShare(fileName: string, username: string, shareSettings: Partial = {}) { @@ -31,15 +32,20 @@ export function createShare(fileName: string, username: string, shareSettings: P updateShare(fileName, 0, shareSettings) } +export function openSharingDetails(index: number) { + cy.get('#app-sidebar-vue').within(() => { + cy.get('[data-cy-files-sharing-share-actions]').eq(index).click() + cy.get('[data-cy-files-sharing-share-permissions-bundle="custom"]').click() + }) +} + export function updateShare(fileName: string, index: number, shareSettings: Partial = {}) { openSharingPanel(fileName) + openSharingDetails(index) cy.intercept({ times: 1, method: 'PUT', url: '**/apps/files_sharing/api/v1/shares/*' }).as('updateShare') cy.get('#app-sidebar-vue').within(() => { - cy.get('[data-cy-files-sharing-share-actions]').eq(index).click() - cy.get('[data-cy-files-sharing-share-permissions-bundle="custom"]').click() - if (shareSettings.download !== undefined) { cy.get('[data-cy-files-sharing-share-permissions-checkbox="download"]').find('input').as('downloadCheckbox') if (shareSettings.download) { @@ -89,10 +95,19 @@ export function updateShare(fileName: string, index: number, shareSettings: Part cy.findByRole('textbox', { name: /note to recipient/i }).type(shareSettings.note) } + if (shareSettings.expiryDate !== undefined) { + cy.findByRole('checkbox', { name: /expiration date/i }) + .check({ force: true, scrollBehavior: 'nearest' }) + cy.get('#share-date-picker') + .type(`${shareSettings.expiryDate.getFullYear()}-${String(shareSettings.expiryDate.getMonth() + 1).padStart(2, '0')}-${String(shareSettings.expiryDate.getDate()).padStart(2, '0')}`) + } + cy.get('[data-cy-files-sharing-share-editor-action="save"]').click({ scrollBehavior: 'nearest' }) cy.wait('@updateShare') }) + // close all toasts + cy.get('.toast-success').findAllByRole('button').click({ force: true, multiple: true }) } export function openSharingPanel(fileName: string) { diff --git a/cypress/e2e/files_sharing/expiry-date.cy.ts b/cypress/e2e/files_sharing/expiry-date.cy.ts new file mode 100644 index 0000000000000..566e16dfe5398 --- /dev/null +++ b/cypress/e2e/files_sharing/expiry-date.cy.ts @@ -0,0 +1,128 @@ +/*! + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { User } from '@nextcloud/cypress' +import { createShare, openSharingDetails, openSharingPanel, updateShare } from './FilesSharingUtils.ts' +import { closeSidebar } from '../../../apps-extra/activity/cypress/e2e/sidebarUtils.ts' + +describe('files_sharing: Expiry date', () => { + const expectedDefaultDate = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000) + const expectedDefaultDateString = `${expectedDefaultDate.getFullYear()}-${String(expectedDefaultDate.getMonth() + 1).padStart(2, '0')}-${String(expectedDefaultDate.getDate()).padStart(2, '0')}` + const fortnight = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000) + const fortnightString = `${fortnight.getFullYear()}-${String(fortnight.getMonth() + 1).padStart(2, '0')}-${String(fortnight.getDate()).padStart(2, '0')}` + + let alice: User + let bob: User + + before(() => { + // Ensure we have the admin setting setup for default dates with 2 days in the future + cy.runOccCommand('config:app:set --value yes core shareapi_default_internal_expire_date') + cy.runOccCommand('config:app:set --value 2 core shareapi_internal_expire_after_n_days') + + cy.createRandomUser().then((user) => { + alice = user + cy.login(alice) + }) + cy.createRandomUser().then((user) => { + bob = user + }) + }) + + after(() => { + cy.runOccCommand('config:app:delete core shareapi_default_internal_expire_date') + cy.runOccCommand('config:app:delete core shareapi_enforce_internal_expire_date') + cy.runOccCommand('config:app:delete core shareapi_internal_expire_after_n_days') + }) + + beforeEach(() => { + cy.runOccCommand('config:app:delete core shareapi_enforce_internal_expire_date') + }) + + it('See default expiry date is set and enforced', () => { + // Enforce the date + cy.runOccCommand('config:app:set --value yes core shareapi_enforce_internal_expire_date') + const dir = 'defaultExpiryDateEnforced' + prepareDirectory(dir) + + validateExpiryDate(dir, expectedDefaultDateString) + cy.findByRole('checkbox', { name: /expiration date/i }) + .should('be.checked') + .and('be.disabled') + }) + + it('See default expiry date is set also if not enforced', () => { + const dir = 'defaultExpiryDate' + prepareDirectory(dir) + + validateExpiryDate(dir, expectedDefaultDateString) + cy.findByRole('checkbox', { name: /expiration date/i }) + .should('be.checked') + .and('not.be.disabled') + .check({ force: true, scrollBehavior: 'nearest' }) + }) + + it('Can set custom expiry date', () => { + const dir = 'customExpiryDate' + prepareDirectory(dir) + updateShare(dir, 0, { expiryDate: fortnight }) + validateExpiryDate(dir, fortnightString) + }) + + it('Custom expiry date survives reload', () => { + const dir = 'customExpiryDateReload' + prepareDirectory(dir) + updateShare(dir, 0, { expiryDate: fortnight }) + validateExpiryDate(dir, fortnightString) + + cy.visit('/apps/files') + validateExpiryDate(dir, fortnightString) + }) + + /** + * Regression test for https://github.com/nextcloud/server/pull/50192 + * Ensure that admin default settings do not always override the user set value. + */ + it('Custom expiry date survives unrelated update', () => { + const dir = 'customExpiryUnrelatedChanges' + prepareDirectory(dir) + updateShare(dir, 0, { expiryDate: fortnight }) + validateExpiryDate(dir, fortnightString) + + closeSidebar() + updateShare(dir, 0, { note: 'Only note changed' }) + validateExpiryDate(dir, fortnightString) + + cy.visit('/apps/files') + validateExpiryDate(dir, fortnightString) + }) + + /** + * Prepare directory, login and share to bob + * + * @param name The directory name + */ + function prepareDirectory(name: string) { + cy.mkdir(alice, `/${name}`) + cy.login(alice) + cy.visit('/apps/files') + createShare(name, bob.userId) + } + + /** + * Validate expiry date on a share + * + * @param filename The filename to validate + * @param expectedDate The expected date in YYYY-MM-dd + */ + function validateExpiryDate(filename: string, expectedDate: string) { + openSharingPanel(filename) + openSharingDetails(0) + + cy.get('#share-date-picker') + .should('exist') + .and('have.value', expectedDate) + } + +})