summaryrefslogtreecommitdiffstats
path: root/cypress
diff options
context:
space:
mode:
authorLouis Chemineau <louis@chmn.me>2024-03-26 12:21:56 +0100
committerLouis Chemineau <louis@chmn.me>2024-03-26 17:40:31 +0100
commit369274c9ee82eed6010a1a3b9cc5bac1a9926e2c (patch)
tree1a480e3b6ce1ae1536f284bc51ee53f269e6fdcc /cypress
parent1a55084930cbdd89e349cc0c9f4a2c2aeedb1e3c (diff)
downloadnextcloud-server-369274c9ee82eed6010a1a3b9cc5bac1a9926e2c.tar.gz
nextcloud-server-369274c9ee82eed6010a1a3b9cc5bac1a9926e2c.zip
feat(files_versions): Add listener and interfaces to allow versions migration across storages
Signed-off-by: Louis Chemineau <louis@chmn.me>
Diffstat (limited to 'cypress')
-rw-r--r--cypress/e2e/files/FilesUtils.ts49
-rw-r--r--cypress/e2e/files/live_photos.cy.ts28
-rw-r--r--cypress/e2e/files_versions/filesVersionsUtils.ts11
-rw-r--r--cypress/e2e/files_versions/version_cross_share_move_and_copy.cy.ts119
-rw-r--r--cypress/e2e/files_versions/version_download.cy.ts12
-rw-r--r--cypress/e2e/files_versions/version_expiration.cy.ts6
-rw-r--r--cypress/e2e/files_versions/version_restoration.cy.ts12
-rw-r--r--cypress/support/commands.ts2
8 files changed, 182 insertions, 57 deletions
diff --git a/cypress/e2e/files/FilesUtils.ts b/cypress/e2e/files/FilesUtils.ts
index 3ec3f93fd37..0467f79c53f 100644
--- a/cypress/e2e/files/FilesUtils.ts
+++ b/cypress/e2e/files/FilesUtils.ts
@@ -45,7 +45,7 @@ export const triggerInlineActionForFile = (filename: string, actionId: string) =
getActionsForFile(filename).get(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
}
-export const moveFile = (fileName: string, dirName: string) => {
+export const moveFile = (fileName: string, dirPath: string) => {
getRowForFile(fileName).should('be.visible')
triggerActionForFile(fileName, 'move-copy')
@@ -53,26 +53,30 @@ export const moveFile = (fileName: string, dirName: string) => {
// intercept the copy so we can wait for it
cy.intercept('MOVE', /\/remote.php\/dav\/files\//).as('moveFile')
- if (dirName === '/') {
+ if (dirPath === '/') {
// select home folder
cy.get('button[title="Home"]').should('be.visible').click()
// click move
cy.contains('button', 'Move').should('be.visible').click()
- } else if (dirName === '.') {
+ } else if (dirPath === '.') {
// click move
cy.contains('button', 'Copy').should('be.visible').click()
} else {
- // select the folder
- cy.get(`[data-filename="${dirName}"]`).should('be.visible').click()
+ const directories = dirPath.split('/')
+ directories.forEach((directory) => {
+ // select the folder
+ cy.get(`[data-filename="${directory}"]`).should('be.visible').click()
+ })
+
// click move
- cy.contains('button', `Move to ${dirName}`).should('be.visible').click()
+ cy.contains('button', `Move to ${directories.at(-1)}`).should('be.visible').click()
}
cy.wait('@moveFile')
})
}
-export const copyFile = (fileName: string, dirName: string) => {
+export const copyFile = (fileName: string, dirPath: string) => {
getRowForFile(fileName).should('be.visible')
triggerActionForFile(fileName, 'move-copy')
@@ -80,19 +84,23 @@ export const copyFile = (fileName: string, dirName: string) => {
// intercept the copy so we can wait for it
cy.intercept('COPY', /\/remote.php\/dav\/files\//).as('copyFile')
- if (dirName === '/') {
+ if (dirPath === '/') {
// select home folder
cy.get('button[title="Home"]').should('be.visible').click()
// click copy
cy.contains('button', 'Copy').should('be.visible').click()
- } else if (dirName === '.') {
+ } else if (dirPath === '.') {
// click copy
cy.contains('button', 'Copy').should('be.visible').click()
} else {
- // select folder
- cy.get(`[data-filename="${CSS.escape(dirName)}"]`).should('be.visible').click()
+ const directories = dirPath.split('/')
+ directories.forEach((directory) => {
+ // select the folder
+ cy.get(`[data-filename="${CSS.escape(directory)}"]`).should('be.visible').click()
+ })
+
// click copy
- cy.contains('button', `Copy to ${dirName}`).should('be.visible').click()
+ cy.contains('button', `Copy to ${directories.at(-1)}`).should('be.visible').click()
}
cy.wait('@copyFile')
@@ -112,10 +120,21 @@ export const renameFile = (fileName: string, newFileName: string) => {
cy.wait('@moveFile')
}
-export const navigateToFolder = (folderName: string) => {
- getRowForFile(folderName).should('be.visible').find('[data-cy-files-list-row-name-link]').click()
+export const navigateToFolder = (dirPath: string) => {
+ const directories = dirPath.split('/')
+ directories.forEach((directory) => {
+ getRowForFile(directory).should('be.visible').find('[data-cy-files-list-row-name-link]').click()
+ })
+
}
export const closeSidebar = () => {
- cy.get('[cy-data-sidebar] .app-sidebar__close').click()
+ // {force: true} as it might be hidden behind toasts
+ cy.get('[cy-data-sidebar] .app-sidebar__close').click({ force: true })
+}
+
+export const clickOnBreadcumbs = (label: string) => {
+ cy.intercept('PROPFIND', /\/remote.php\/dav\//).as('propfind')
+ cy.get('[data-cy-files-content-breadcrumbs]').contains(label).click()
+ cy.wait('@propfind')
}
diff --git a/cypress/e2e/files/live_photos.cy.ts b/cypress/e2e/files/live_photos.cy.ts
index 98babb86941..91b30f1cce5 100644
--- a/cypress/e2e/files/live_photos.cy.ts
+++ b/cypress/e2e/files/live_photos.cy.ts
@@ -21,17 +21,7 @@
*/
import type { User } from '@nextcloud/cypress'
-import { closeSidebar, copyFile, getRowForFile, getRowForFileId, renameFile, triggerActionForFile, triggerInlineActionForFileId } from './FilesUtils'
-
-/**
- *
- * @param label
- */
-function refreshView(label: string) {
- cy.intercept('PROPFIND', /\/remote.php\/dav\//).as('propfind')
- cy.get('[data-cy-files-content-breadcrumbs]').contains(label).click()
- cy.wait('@propfind')
-}
+import { clickOnBreadcumbs, closeSidebar, copyFile, getRowForFile, getRowForFileId, renameFile, triggerActionForFile, triggerInlineActionForFileId } from './FilesUtils'
/**
*
@@ -123,7 +113,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Copies both files when copying the .jpg', () => {
copyFile(`${randomFileName}.jpg`, '.')
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFile(`${randomFileName}.jpg`).should('have.length', 1)
getRowForFile(`${randomFileName}.mov`).should('have.length', 1)
@@ -133,7 +123,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Copies both files when copying the .mov', () => {
copyFile(`${randomFileName}.mov`, '.')
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFile(`${randomFileName}.mov`).should('have.length', 1)
getRowForFile(`${randomFileName} (copy).jpg`).should('have.length', 1)
@@ -142,7 +132,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Moves files when moving the .jpg', () => {
renameFile(`${randomFileName}.jpg`, `${randomFileName}_moved.jpg`)
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFileId(jpgFileId).invoke('attr', 'data-cy-files-list-row-name').should('equal', `${randomFileName}_moved.jpg`)
getRowForFileId(movFileId).invoke('attr', 'data-cy-files-list-row-name').should('equal', `${randomFileName}_moved.mov`)
@@ -150,7 +140,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Moves files when moving the .mov', () => {
renameFile(`${randomFileName}.mov`, `${randomFileName}_moved.mov`)
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFileId(jpgFileId).invoke('attr', 'data-cy-files-list-row-name').should('equal', `${randomFileName}_moved.jpg`)
getRowForFileId(movFileId).invoke('attr', 'data-cy-files-list-row-name').should('equal', `${randomFileName}_moved.mov`)
@@ -158,7 +148,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Deletes files when deleting the .jpg', () => {
triggerActionForFile(`${randomFileName}.jpg`, 'delete')
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFile(`${randomFileName}.jpg`).should('have.length', 0)
getRowForFile(`${randomFileName}.mov`).should('have.length', 0)
@@ -171,7 +161,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
it('Block deletion when deleting the .mov', () => {
triggerActionForFile(`${randomFileName}.mov`, 'delete')
- refreshView('All files')
+ clickOnBreadcumbs('All files')
getRowForFile(`${randomFileName}.jpg`).should('have.length', 1)
getRowForFile(`${randomFileName}.mov`).should('have.length', 1)
@@ -186,7 +176,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
triggerActionForFile(`${randomFileName}.jpg`, 'delete')
cy.visit('/apps/files/trashbin')
triggerInlineActionForFileId(jpgFileId, 'restore')
- refreshView('Deleted files')
+ clickOnBreadcumbs('Deleted files')
getRowForFile(`${randomFileName}.jpg`).should('have.length', 0)
getRowForFile(`${randomFileName}.mov`).should('have.length', 0)
@@ -201,7 +191,7 @@ describe('Files: Live photos', { testIsolation: true }, () => {
triggerActionForFile(`${randomFileName}.jpg`, 'delete')
cy.visit('/apps/files/trashbin')
triggerInlineActionForFileId(movFileId, 'restore')
- refreshView('Deleted files')
+ clickOnBreadcumbs('Deleted files')
getRowForFileId(jpgFileId).should('have.length', 1)
getRowForFileId(movFileId).should('have.length', 1)
diff --git a/cypress/e2e/files_versions/filesVersionsUtils.ts b/cypress/e2e/files_versions/filesVersionsUtils.ts
index 7f655d2c303..4ea47162f0b 100644
--- a/cypress/e2e/files_versions/filesVersionsUtils.ts
+++ b/cypress/e2e/files_versions/filesVersionsUtils.ts
@@ -89,14 +89,11 @@ export function doesNotHaveAction(index: number, actionName: string) {
toggleVersionMenu(index)
}
-export function assertVersionContent(filename: string, index: number, expectedContent: string) {
- const downloadsFolder = Cypress.config('downloadsFolder')
-
+export function assertVersionContent(index: number, expectedContent: string) {
+ cy.intercept({ method: 'GET', times: 1, url: 'remote.php/**' }).as('downloadVersion')
triggerVersionAction(index, 'download')
-
- return cy.readFile(path.join(downloadsFolder, filename))
- .then((versionContent) => expect(versionContent).to.equal(expectedContent))
- .then(() => cy.exec(`rm ${downloadsFolder}/${filename}`))
+ cy.wait('@downloadVersion')
+ .then(({ response }) => expect(response?.body).to.equal(expectedContent))
}
export function setupTestSharedFileFromUser(owner: User, randomFileName: string, shareOptions: Partial<ShareSetting>) {
diff --git a/cypress/e2e/files_versions/version_cross_share_move_and_copy.cy.ts b/cypress/e2e/files_versions/version_cross_share_move_and_copy.cy.ts
new file mode 100644
index 00000000000..90381120d87
--- /dev/null
+++ b/cypress/e2e/files_versions/version_cross_share_move_and_copy.cy.ts
@@ -0,0 +1,119 @@
+/**
+ * @copyright Copyright (c) 2024 Louis Chmn <louis@chmn.me>
+ *
+ * @author Louis Chmn <louis@chmn.me>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import { assertVersionContent, openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions, nameVersion } from './filesVersionsUtils'
+import { clickOnBreadcumbs, closeSidebar, copyFile, moveFile, navigateToFolder } from '../files/FilesUtils'
+import type { User } from '@nextcloud/cypress'
+
+/**
+ *
+ * @param filePath
+ */
+function assertVersionsContent(filePath: string) {
+ const path = filePath.split('/').slice(0, -1).join('/')
+
+ clickOnBreadcumbs('All files')
+
+ if (path !== '') {
+ navigateToFolder(path)
+ }
+
+ openVersionsPanel(filePath)
+
+ cy.get('[data-files-versions-version]').should('have.length', 3)
+ assertVersionContent(0, 'v3')
+ assertVersionContent(1, 'v2')
+ assertVersionContent(2, 'v1')
+}
+
+describe('Versions cross share move and copy', () => {
+ let randomSharedFolderName = ''
+ let randomFileName = ''
+ let randomFilePath = ''
+ let alice: User
+ let bob: User
+
+ before(() => {
+ randomSharedFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
+
+ cy.createRandomUser()
+ .then((user) => {
+ alice = user
+ cy.mkdir(alice, `/${randomSharedFolderName}`)
+ setupTestSharedFileFromUser(alice, randomSharedFolderName, {})
+ })
+ .then((user) => { bob = user })
+ })
+
+ beforeEach(() => {
+ randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
+ randomFilePath = `${randomSharedFolderName}/${randomFileName}`
+ uploadThreeVersions(alice, randomFilePath)
+
+ cy.login(bob)
+ cy.visit('/apps/files')
+ navigateToFolder(randomSharedFolderName)
+ openVersionsPanel(randomFilePath)
+ nameVersion(2, 'v1')
+ closeSidebar()
+ })
+
+ it('Also moves versions when bob moves the file out of a received share', () => {
+ moveFile(randomFileName, '/')
+ assertVersionsContent(randomFileName)
+ // TODO: move that in assertVersionsContent when copying files keeps the versions' metadata
+ cy.get('[data-files-versions-version]').eq(2).contains('v1')
+ })
+
+ it('Also copies versions when bob copies the file out of a received share', () => {
+ copyFile(randomFileName, '/')
+ assertVersionsContent(randomFileName)
+ })
+
+ context('When a file is in a subfolder', () => {
+ let randomSubFolderName
+ let randomSubSubFolderName
+
+ beforeEach(() => {
+ randomSubFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
+ randomSubSubFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
+ clickOnBreadcumbs('All files')
+ cy.mkdir(bob, `/${randomSharedFolderName}/${randomSubFolderName}`)
+ cy.mkdir(bob, `/${randomSharedFolderName}/${randomSubFolderName}/${randomSubSubFolderName}`)
+ cy.login(bob)
+ navigateToFolder(randomSharedFolderName)
+ moveFile(randomFileName, `${randomSubFolderName}/${randomSubSubFolderName}`)
+ })
+
+ it('Also moves versions when bob moves the containing folder out of a received share', () => {
+ moveFile(randomSubFolderName, '/')
+ assertVersionsContent(`${randomSubFolderName}/${randomSubSubFolderName}/${randomFileName}`)
+ // TODO: move that in assertVersionsContent when copying files keeps the versions' metadata
+ cy.get('[data-files-versions-version]').eq(2).contains('v1')
+ })
+
+ it('Also copies versions when bob copies the containing folder out of a received share', () => {
+ copyFile(randomSubFolderName, '/')
+ assertVersionsContent(`${randomSubFolderName}/${randomSubSubFolderName}/${randomFileName}`)
+ })
+ })
+})
diff --git a/cypress/e2e/files_versions/version_download.cy.ts b/cypress/e2e/files_versions/version_download.cy.ts
index f6a994322a8..0e4301654f0 100644
--- a/cypress/e2e/files_versions/version_download.cy.ts
+++ b/cypress/e2e/files_versions/version_download.cy.ts
@@ -42,9 +42,9 @@ describe('Versions download', () => {
})
it('Download versions and assert their content', () => {
- assertVersionContent(randomFileName, 0, 'v3')
- assertVersionContent(randomFileName, 1, 'v2')
- assertVersionContent(randomFileName, 2, 'v1')
+ assertVersionContent(0, 'v3')
+ assertVersionContent(1, 'v2')
+ assertVersionContent(2, 'v1')
})
context('Download versions of shared file', () => {
@@ -52,9 +52,9 @@ describe('Versions download', () => {
setupTestSharedFileFromUser(user, randomFileName, { download: true })
openVersionsPanel(randomFileName)
- assertVersionContent(randomFileName, 0, 'v3')
- assertVersionContent(randomFileName, 1, 'v2')
- assertVersionContent(randomFileName, 2, 'v1')
+ assertVersionContent(0, 'v3')
+ assertVersionContent(1, 'v2')
+ assertVersionContent(2, 'v1')
})
it('Does not show action without download permission', () => {
diff --git a/cypress/e2e/files_versions/version_expiration.cy.ts b/cypress/e2e/files_versions/version_expiration.cy.ts
index a3b2eea83e1..1c1c6fc70ae 100644
--- a/cypress/e2e/files_versions/version_expiration.cy.ts
+++ b/cypress/e2e/files_versions/version_expiration.cy.ts
@@ -49,7 +49,7 @@ describe('Versions expiration', () => {
cy.get('[data-files-versions-version]').eq(0).contains('Current version')
})
- assertVersionContent(randomFileName, 0, 'v3')
+ assertVersionContent(0, 'v3')
})
it('Expire versions v2', () => {
@@ -67,7 +67,7 @@ describe('Versions expiration', () => {
cy.get('[data-files-versions-version]').eq(1).contains('v1')
})
- assertVersionContent(randomFileName, 0, 'v3')
- assertVersionContent(randomFileName, 1, 'v1')
+ assertVersionContent(0, 'v3')
+ assertVersionContent(1, 'v1')
})
})
diff --git a/cypress/e2e/files_versions/version_restoration.cy.ts b/cypress/e2e/files_versions/version_restoration.cy.ts
index d9d983b0d09..72295003bba 100644
--- a/cypress/e2e/files_versions/version_restoration.cy.ts
+++ b/cypress/e2e/files_versions/version_restoration.cy.ts
@@ -56,9 +56,9 @@ describe('Versions restoration', () => {
})
it('Downloads versions and assert there content', () => {
- assertVersionContent(randomFileName, 0, 'v1')
- assertVersionContent(randomFileName, 1, 'v3')
- assertVersionContent(randomFileName, 2, 'v2')
+ assertVersionContent(0, 'v1')
+ assertVersionContent(1, 'v3')
+ assertVersionContent(2, 'v2')
})
context('Restore versions of shared file', () => {
@@ -76,9 +76,9 @@ describe('Versions restoration', () => {
})
it('Downloads versions and assert there content', () => {
- assertVersionContent(randomFileName, 0, 'v1')
- assertVersionContent(randomFileName, 1, 'v3')
- assertVersionContent(randomFileName, 2, 'v2')
+ assertVersionContent(0, 'v1')
+ assertVersionContent(1, 'v3')
+ assertVersionContent(2, 'v2')
})
})
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
index 1d7efe52075..8d78c3db166 100644
--- a/cypress/support/commands.ts
+++ b/cypress/support/commands.ts
@@ -184,7 +184,7 @@ Cypress.Commands.add('mkdir', (user: User, target: string) => {
cy.log(`Created directory ${target}`, response)
} catch (error) {
cy.log('error', error)
- throw new Error('Unable to process fixture')
+ throw new Error('Unable to create directory')
}
})
})