Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: Add end-to-end test for share expiration date
Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed Jan 15, 2025
commit 105fa977d1d55c62fd48ca61d7b2b7922e8f8102
125 changes: 125 additions & 0 deletions cypress/e2e/files_sharing/expiry-date.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*!
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { User } from '@nextcloud/cypress'
import { randomBytes } from 'crypto'
import { closeSidebar } from '../files/FilesUtils.ts'
import { createShare, openSharingDetails, openSharingPanel, updateShare } from './filesSharingUtils.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 = prepareDirectory()

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 = prepareDirectory()

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 = prepareDirectory()
updateShare(dir, 0, { expiryDate: fortnight })
validateExpiryDate(dir, fortnightString)
})

it('Custom expiry date survives reload', () => {
const dir = prepareDirectory()
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 = prepareDirectory()
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
*/
function prepareDirectory(): string {
const name = randomBytes(4)
.toString('hex')
cy.mkdir(alice, `/${name}`)
cy.login(alice)
cy.visit('/apps/files')
createShare(name, bob.userId)
return name
}

/**
* 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)
}

})
27 changes: 24 additions & 3 deletions cypress/e2e/files_sharing/filesSharingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface ShareSetting {
delete: boolean
share: boolean
download: boolean
note: string
expiryDate: Date
}

export function createShare(fileName: string, username: string, shareSettings: Partial<ShareSetting> = {}) {
Expand All @@ -48,13 +50,18 @@ export function createShare(fileName: string, username: string, shareSettings: P
updateShare(fileName, 0, shareSettings)
}

export function updateShare(fileName: string, index: number, shareSettings: Partial<ShareSetting> = {}) {
openSharingPanel(fileName)

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<ShareSetting> = {}) {
openSharingPanel(fileName)
openSharingDetails(index)

cy.get('#app-sidebar-vue').within(() => {
if (shareSettings.download !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="download"]').find('input').as('downloadCheckbox')
if (shareSettings.download) {
Expand Down Expand Up @@ -99,8 +106,22 @@ export function updateShare(fileName: string, index: number, shareSettings: Part
}
}

if (shareSettings.note !== undefined) {
cy.findByRole('checkbox', { name: /note to recipient/i }).check({ force: true, scrollBehavior: 'nearest' })
cy.findByRole('textbox', { name: /note for the share 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' })
})
// close all toasts
cy.get('.toast-success').findAllByRole('button').click({ force: true, multiple: true })
}

export function openSharingPanel(fileName: string) {
Expand Down
2 changes: 1 addition & 1 deletion cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"extends": "../tsconfig.json",
"include": ["./**/*.ts"],
"compilerOptions": {
"types": ["cypress", "cypress-axe", "cypress-wait-until", "dockerode"],
"types": ["@testing-library/cypress", "cypress", "cypress-axe", "cypress-wait-until", "dockerode"],
}
}