From 82f9a91f3dae0620adcfe2e76da9a0c5986b40c5 Mon Sep 17 00:00:00 2001 From: Louis Chemineau Date: Fri, 13 Sep 2024 15:33:35 +0200 Subject: [PATCH] = Signed-off-by: Louis Chemineau --- cypress.config.ts | 13 +++++ .../e2e/files_versions/filesVersionsUtils.ts | 51 ++++++++++++++++++- .../e2e/files_versions/version_creation.cy.ts | 34 ++----------- .../e2e/files_versions/version_deletion.cy.ts | 34 ++----------- .../e2e/files_versions/version_download.cy.ts | 34 ++----------- .../files_versions/version_expiration.cy.ts | 47 +++++------------ .../e2e/files_versions/version_naming.cy.ts | 34 ++----------- .../files_versions/version_restoration.cy.ts | 34 ++----------- cypress/support/commands.ts | 46 +++++++++++++++-- 9 files changed, 133 insertions(+), 194 deletions(-) diff --git a/cypress.config.ts b/cypress.config.ts index 69b4ba01b..0617017d4 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -45,6 +45,19 @@ export default defineConfig({ } }) + // This allows to store global data (e.g. the name of a snapshot) + // because Cypress.env() and other options are local to the current spec file. + const data = {} + on('task', { + setVariable({ key, value }) { + data[key] = value + return null + }, + getVariable({ key }) { + return data[key] ?? null + }, + }) + // Before the browser launches // starting Nextcloud testing container const ip = await startNextcloud(process.env.BRANCH) diff --git a/cypress/e2e/files_versions/filesVersionsUtils.ts b/cypress/e2e/files_versions/filesVersionsUtils.ts index c99d1f063..57fc9980f 100644 --- a/cypress/e2e/files_versions/filesVersionsUtils.ts +++ b/cypress/e2e/files_versions/filesVersionsUtils.ts @@ -22,7 +22,56 @@ */ import type { User } from '@nextcloud/cypress' -import path from 'path' +import { addUserToGroup, createGroup, createGroupFolder, PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE } from '../groupfoldersUtils' +import { navigateToFolder } from '../files/filesUtils' + +type SetupInfo = { + dataSnapshot: string + dbSnapshot: string + groupName: string + groupFolderName: string + fileName: string + filePath: string + user: User +} + +export function setupFilesVersions(): Cypress.Chainable { + return cy.task('getVariable', { key: 'files-versions-data' }) + .then((_setupInfo) => { + const setupInfo = _setupInfo as SetupInfo || {} + + if (setupInfo.dataSnapshot && setupInfo.dbSnapshot) { + cy.restoreDB(setupInfo.dbSnapshot) + cy.restoreData(setupInfo.dataSnapshot) + } else { + setupInfo.groupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + setupInfo.groupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + setupInfo.fileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' + setupInfo.filePath = `${setupInfo.groupFolderName}/${setupInfo.fileName}` + + cy.createRandomUser().then(_user => { setupInfo.user = _user }) + createGroup(setupInfo.groupName) + + cy.then(() => { + addUserToGroup(setupInfo.groupName, setupInfo.user.userId) + createGroupFolder(setupInfo.groupFolderName, setupInfo.groupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) + + uploadThreeVersions(setupInfo.user, setupInfo.filePath) + }) + .then(() => cy.backupDB().then((value) => { setupInfo.dbSnapshot = value })) + .then(() => cy.backupData([setupInfo.user.userId]).then((value) => { setupInfo.dataSnapshot = value })) + .then(() => cy.task('setVariable', { key: 'files-versions-data', value: setupInfo })) + } + + return cy.then(() => { + cy.login(setupInfo.user) + cy.visit('/apps/files') + navigateToFolder(setupInfo.groupFolderName) + openVersionsPanel(setupInfo.filePath) + return cy.wrap(setupInfo) + }) + }) +} export const uploadThreeVersions = (user: User, fileName: string) => { // A new version will not be created if the changes occur diff --git a/cypress/e2e/files_versions/version_creation.cy.ts b/cypress/e2e/files_versions/version_creation.cy.ts index 03282ae59..36b23326e 100644 --- a/cypress/e2e/files_versions/version_creation.cy.ts +++ b/cypress/e2e/files_versions/version_creation.cy.ts @@ -20,39 +20,11 @@ * */ -import type { User } from '@nextcloud/cypress' - -import { PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE, addUserToGroup, createGroup, createGroupFolder } from '../groupfoldersUtils' -import { openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils' -import { navigateToFolder } from '../files/filesUtils' +import { setupFilesVersions } from './filesVersionsUtils' describe('Versions creation', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string - let randomFilePath: string - let user1: User - - before(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) + beforeEach(() => { + setupFilesVersions() }) it('Opens the versions panel and sees the versions', () => { diff --git a/cypress/e2e/files_versions/version_deletion.cy.ts b/cypress/e2e/files_versions/version_deletion.cy.ts index 9c7804d9c..430e997cd 100644 --- a/cypress/e2e/files_versions/version_deletion.cy.ts +++ b/cypress/e2e/files_versions/version_deletion.cy.ts @@ -20,39 +20,11 @@ * */ -import type { User } from '@nextcloud/cypress' - -import { openVersionsPanel, uploadThreeVersions, deleteVersion } from './filesVersionsUtils' -import { navigateToFolder } from '../files/filesUtils' -import { PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE, addUserToGroup, createGroup, createGroupFolder } from '../groupfoldersUtils' +import { deleteVersion, setupFilesVersions } from './filesVersionsUtils' describe('Versions restoration', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string - let randomFilePath: string - let user1: User - - before(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) + beforeEach(() => { + setupFilesVersions() }) it('Delete initial version', () => { diff --git a/cypress/e2e/files_versions/version_download.cy.ts b/cypress/e2e/files_versions/version_download.cy.ts index 7bc48f501..24af66815 100644 --- a/cypress/e2e/files_versions/version_download.cy.ts +++ b/cypress/e2e/files_versions/version_download.cy.ts @@ -20,39 +20,11 @@ * */ -import type { User } from '@nextcloud/cypress' - -import { assertVersionContent, openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils' -import { PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE, addUserToGroup, createGroup, createGroupFolder } from '../groupfoldersUtils' -import { navigateToFolder } from '../files/filesUtils' +import { assertVersionContent, setupFilesVersions } from './filesVersionsUtils' describe('Versions download', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string - let randomFilePath: string - let user1: User - - before(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) + beforeEach(() => { + setupFilesVersions() }) it('Download versions and assert their content', () => { diff --git a/cypress/e2e/files_versions/version_expiration.cy.ts b/cypress/e2e/files_versions/version_expiration.cy.ts index fb3f6f343..261f2e2bd 100644 --- a/cypress/e2e/files_versions/version_expiration.cy.ts +++ b/cypress/e2e/files_versions/version_expiration.cy.ts @@ -3,48 +3,25 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import type { User } from '@nextcloud/cypress' - -import { assertVersionContent, nameVersion, openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils' -import { addUserToGroup, createGroup, createGroupFolder, PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE } from '../groupfoldersUtils' -import { navigateToFolder } from '../files/filesUtils' +import { closeSidebar } from '../files/filesUtils' +import { assertVersionContent, nameVersion, openVersionsPanel, setupFilesVersions } from './filesVersionsUtils' describe('Versions expiration', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string let randomFilePath: string - let user1: User beforeEach(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) - + setupFilesVersions() + .then(({ filePath }) => { + randomFilePath = filePath + }) }) it('Expire all versions', () => { cy.runOccCommand('config:system:set versions_retention_obligation --value "0, 0"') - cy.runOccCommand('versions:expire') + cy.runOccCommand('groupfolders:expire') cy.runOccCommand('config:system:set versions_retention_obligation --value auto') - cy.visit('/apps/files') - openVersionsPanel(randomFileName) + closeSidebar() + openVersionsPanel(randomFilePath) cy.get('#tab-version_vue').within(() => { cy.get('[data-files-versions-version]').should('have.length', 1) @@ -58,10 +35,10 @@ describe('Versions expiration', () => { nameVersion(2, 'v1') cy.runOccCommand('config:system:set versions_retention_obligation --value "0, 0"') - cy.runOccCommand('versions:expire') + cy.runOccCommand('groupfolders:expire') cy.runOccCommand('config:system:set versions_retention_obligation --value auto') - cy.visit('/apps/files') - openVersionsPanel(randomFileName) + closeSidebar() + openVersionsPanel(randomFilePath) cy.get('#tab-version_vue').within(() => { cy.get('[data-files-versions-version]').should('have.length', 2) diff --git a/cypress/e2e/files_versions/version_naming.cy.ts b/cypress/e2e/files_versions/version_naming.cy.ts index fec1a154a..328f1d434 100644 --- a/cypress/e2e/files_versions/version_naming.cy.ts +++ b/cypress/e2e/files_versions/version_naming.cy.ts @@ -20,39 +20,11 @@ * */ -import type { User } from '@nextcloud/cypress' - -import { nameVersion, openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils' -import { PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE, addUserToGroup, createGroup, createGroupFolder } from '../groupfoldersUtils' -import { navigateToFolder } from '../files/filesUtils' +import { nameVersion, setupFilesVersions } from './filesVersionsUtils' describe('Versions naming', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string - let randomFilePath: string - let user1: User - - before(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) + beforeEach(() => { + setupFilesVersions() }) it('Names the versions', () => { diff --git a/cypress/e2e/files_versions/version_restoration.cy.ts b/cypress/e2e/files_versions/version_restoration.cy.ts index 2ed806cab..8cf05496b 100644 --- a/cypress/e2e/files_versions/version_restoration.cy.ts +++ b/cypress/e2e/files_versions/version_restoration.cy.ts @@ -20,39 +20,11 @@ * */ -import type { User } from '@nextcloud/cypress' - -import { assertVersionContent, doesNotHaveAction, openVersionsPanel, restoreVersion, uploadThreeVersions } from './filesVersionsUtils' -import { PERMISSION_DELETE, PERMISSION_READ, PERMISSION_WRITE, addUserToGroup, createGroup, createGroupFolder } from '../groupfoldersUtils' -import { navigateToFolder } from '../files/filesUtils' +import { assertVersionContent, doesNotHaveAction, restoreVersion, setupFilesVersions } from './filesVersionsUtils' describe('Versions restoration', () => { - let randomGroupName: string - let randomGroupFolderName: string - let randomFileName: string - let randomFilePath: string - let user1: User - before(() => { - randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomGroupFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) - randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt' - randomFilePath = `${randomGroupFolderName}/${randomFileName}` - - cy.createRandomUser().then(_user => { user1 = _user }) - createGroup(randomGroupName) - - cy.then(() => { - addUserToGroup(randomGroupName, user1.userId) - createGroupFolder(randomGroupFolderName, randomGroupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE]) - - uploadThreeVersions(user1, randomFilePath) - cy.login(user1) - }) - - cy.visit('/apps/files') - navigateToFolder(randomGroupFolderName) - openVersionsPanel(randomFilePath) + setupFilesVersions() }) it('Current version does not have restore action', () => { @@ -69,7 +41,7 @@ describe('Versions restoration', () => { }) }) - it('Downloads versions and assert there content', () => { + it('Downloads versions and assert their content', () => { assertVersionContent(0, 'v1') assertVersionContent(1, 'v3') assertVersionContent(2, 'v2') diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 19c2f6840..6fd8a701b 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -38,6 +38,21 @@ declare global { * Run an occ command in the docker container. */ runOccCommand(command: string, options?: Partial): Cypress.Chainable, + + /** + * Create a snapshot of the current database + */ + backupDB(): Cypress.Chainable, + + /** + * Restore a snapshot of the database + * Default is the post-setup state + */ + restoreDB(snapshot?: string): Cypress.Chainable + + backupData(users?: string[]): Cypress.Chainable + + restoreData(snapshot?: string): Cypress.Chainable } } } @@ -45,11 +60,10 @@ declare global { const url = (Cypress.config('baseUrl') || '').replace(/\/index.php\/?$/g, '') Cypress.env('baseUrl', url) - Cypress.Commands.add('mkdir', (user: User, target: string) => { // eslint-disable-next-line cypress/unsafe-to-chain-command cy.clearCookies() - .then({timeout:8000}, async () => { + .then({ timeout: 8000 }, async () => { try { const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}` const filePath = target.split('/').map(encodeURIComponent).join('/') @@ -98,7 +112,7 @@ Cypress.Commands.add('uploadFile', (user, fixture = 'image.jpg', mimeType = 'ima */ Cypress.Commands.add('uploadContent', (user, blob, mimeType, target) => { cy.clearCookies() - .then({timeout:8000}, async () => { + .then({ timeout: 8000 }, async () => { const fileName = basename(target) // Process paths @@ -131,3 +145,29 @@ Cypress.Commands.add('runOccCommand', (command: string, options?: Partial `-e '${name}=${value}'`).join(' ') return cy.exec(`docker exec --user www-data ${env} nextcloud-cypress-tests_groupfolders php ./occ ${command}`, options) }) + +Cypress.Commands.add('backupDB', (): Cypress.Chainable => { + const randomString = Math.random().toString(36).substring(7) + cy.exec(`docker exec --user www-data nextcloud-cypress-tests_groupfolders cp /var/www/html/data/owncloud.db /var/www/html/data/owncloud.db-${randomString}`) + cy.log(`Created snapshot ${randomString}`) + return cy.wrap(randomString) +}) + +Cypress.Commands.add('restoreDB', (snapshot: string = 'init') => { + cy.exec(`docker exec --user www-data nextcloud-cypress-tests_groupfolders cp /var/www/html/data/owncloud.db-${snapshot} /var/www/html/data/owncloud.db`) + cy.log(`Restored snapshot ${snapshot}`) +}) + +Cypress.Commands.add('backupData', () => { + const snapshot = Math.random().toString(36).substring(7) + cy.exec(`docker exec --user www-data rm /var/www/html/data/data-${snapshot}.tar`, { failOnNonZeroExit: false }) + cy.exec(`docker exec --user www-data --workdir /var/www/html/data nextcloud-cypress-tests_groupfolders tar cf /var/www/html/data/data-${snapshot}.tar .`) + return cy.wrap(snapshot as string) +}) + +Cypress.Commands.add('restoreData', (snapshot?: string) => { + snapshot = snapshot ?? 'init' + snapshot.replaceAll('\\', '').replaceAll('"', '\\"') + cy.exec(`docker exec --user www-data --workdir /var/www/html/data nextcloud-cypress-tests_groupfolders rm -vfr $(tar --exclude='*/*' -tf '/var/www/html/data/data-${snapshot}.tar')`) + cy.exec(`docker exec --user www-data --workdir /var/www/html/data nextcloud-cypress-tests_groupfolders tar -xf '/var/www/html/data/data-${snapshot}.tar'`) +})