diff --git a/cypress/e2e/filesUtils.ts b/cypress/e2e/filesUtils.ts index 7edb83d81..48b1d9410 100644 --- a/cypress/e2e/filesUtils.ts +++ b/cypress/e2e/filesUtils.ts @@ -3,35 +3,110 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +export const getRowForFile = (filename: string) => cy.get(`[data-cy-files-list-row-name="${CSS.escape(filename)}"]`) +export const getActionsForFile = (filename: string) => getRowForFile(filename).find('[data-cy-files-list-row-actions]') +export const getActionButtonForFile = (filename: string) => getActionsForFile(filename).findByRole('button', { name: 'Actions' }) + +const searchForActionInRow = (row: JQuery, actionId: string): Cypress.Chainable> => { + const action = row.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`) + if (action.length > 0) { + cy.log('Found action in row') + return cy.wrap(action) + } + + // Else look in the action menu + const menuButtonId = row.find('button[aria-controls]').attr('aria-controls') + if (menuButtonId === undefined) { + return cy.wrap(Cypress.$()) + } + + // eslint-disable-next-line no-unused-expressions + expect(menuButtonId).not.to.be.undefined + return cy.get(`#${menuButtonId} [data-cy-files-list-row-action="${CSS.escape(actionId)}"]`) +} + +export const getActionEntryForFile = (filename: string, actionId: string): Cypress.Chainable> => { + // If we cannot find the action in the row, it might be in the action menu + return getRowForFile(filename).should('be.visible') + .then(row => searchForActionInRow(row, actionId)) +} + +export const triggerActionForFile = (filename: string, actionId: string) => { + // Even if it's inline, we open the action menu to get all actions visible + getActionButtonForFile(filename).click({ force: true }) + getActionEntryForFile(filename, actionId) + .find('button').last() + .should('exist').click({ force: true }) +} + export function renameFile(fileName: string, newName: string) { - toggleMenuAction(fileName, 'rename') - cy.get(`[data-cy-files-list] [data-cy-files-list-row-name="${fileName}"] .files-list__row-rename input`).clear() - cy.get(`[data-cy-files-list] [data-cy-files-list-row-name="${fileName}"] .files-list__row-rename input`).type(`${newName}.txt`) - cy.get(`[data-cy-files-list] [data-cy-files-list-row-name="${fileName}"] .files-list__row-rename`).submit() + getRowForFile(fileName) + triggerActionForFile(fileName, 'rename') + + // intercept the move so we can wait for it + cy.intercept('MOVE', /\/(remote|public)\.php\/dav\/files\//).as('moveFile') + + getRowForFile(fileName).find('[data-cy-files-list-row-name] input').clear() + getRowForFile(fileName).find('[data-cy-files-list-row-name] input').type(`${newName}{enter}`) cy.get('.toast-close').click() - cy.wait(500) + cy.wait('@moveFile') } -export function goToDir(dirName: string) { - cy.get(`[data-cy-files-list] [data-cy-files-list-row-name="${dirName}"]`).click() - cy.wait(500) +export function navigateToFolder(dirPath: string) { + cy.intercept('PROPFIND', /\/remote.php\/dav\/files\//).as('navigateFolder') + + const directories = dirPath.split('/') + for (const directory of directories) { + if (directory === '') { + continue + } + + getRowForFile(directory).should('be.visible').find('[data-cy-files-list-row-name-link]').click() + cy.wait('@navigateFolder') + } } export function createFolder (dirName: string) { - cy.get('.files-list__header .breadcrumb__actions button.action-item__menutoggle').click() - cy.get('.v-popper__popper').contains('New folder').click() - cy.contains('Folder name').siblings('input').clear() - cy.contains('Folder name').siblings('input').type(`${dirName}{enter}`) - cy.log('Created folder', dirName) - cy.wait(500) + cy.intercept('MKCOL', /\/remote.php\/dav\/files\//).as('createFolder') + + // TODO: replace by proper data-cy selectors + cy.get('[data-cy-upload-picker] .action-item__menutoggle').first().click() + cy.get('[data-cy-upload-picker-menu-entry="newFolder"] button').click() + cy.get('[data-cy-files-new-node-dialog]').should('be.visible') + cy.get('[data-cy-files-new-node-dialog-input]').type(`{selectall}${dirName}`) + cy.get('[data-cy-files-new-node-dialog-submit]').click() + + cy.wait('@createFolder') + + getRowForFile(dirName).should('be.visible') } export function moveFile (fileName: string, dirName: string) { toggleMenuAction(fileName, 'move-copy') cy.get('.file-picker').within(() => { - cy.get(`[data-filename="${dirName}"]`).click() - cy.contains(`Move to ${dirName}`).click() - cy.wait(500) + // intercept the copy so we can wait for it + cy.intercept('MOVE', /\/(remote|public)\.php\/dav\/files\//).as('moveFile') + + if (dirName === '/') { + // 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 === '.') { + // click move + cy.contains('button', 'Copy').should('be.visible').click() + } else { + const directories = dirName.split('/') + directories.forEach((directory) => { + // select the folder + cy.get(`[data-filename="${directory}"]`).should('be.visible').click() + }) + + // click move + cy.contains('button', `Move to ${directories.at(-1)}`).should('be.visible').click() + } + + cy.wait('@moveFile') }) } diff --git a/cypress/e2e/sidebar.cy.ts b/cypress/e2e/sidebar.cy.ts index 74c47ce6b..2e10965aa 100644 --- a/cypress/e2e/sidebar.cy.ts +++ b/cypress/e2e/sidebar.cy.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { createFolder, getFileListRow, goToDir, moveFile, renameFile } from './filesUtils' -import { addComment, addTag, createPublicShare, toggleFavorite, showActivityTab, closeSidebar } from './sidebarUtils' +import { createFolder, getFileListRow, navigateToFolder, moveFile, renameFile } from './filesUtils' +import { addComment, addTag, createPublicShare, toggleFavorite, showActivityTab } from './sidebarUtils' describe('Check activity listing in the sidebar', { testIsolation: true }, () => { beforeEach(function() { @@ -45,8 +45,8 @@ describe('Check activity listing in the sidebar', { testIsolation: true }, () => }) it('Has rename activity', () => { - renameFile('welcome.txt', 'new name') - renameFile('new name.txt', 'welcome') + renameFile('welcome.txt', 'new name.txt') + renameFile('new name.txt', 'welcome.txt') showActivityTab('welcome.txt') cy.get('.activity-entry').first().should('contains.text', 'You renamed') @@ -55,8 +55,7 @@ describe('Check activity listing in the sidebar', { testIsolation: true }, () => it('Has move activity', () => { createFolder('Test folder') moveFile('welcome.txt', 'Test folder') - cy.get('.toast-close').click({ multiple: true }) - goToDir('Test folder') + navigateToFolder('Test folder') showActivityTab('welcome.txt') cy.get('.activity-entry').first().should('contains.text', 'You moved') @@ -72,6 +71,7 @@ describe('Check activity listing in the sidebar', { testIsolation: true }, () => it('Has comment activity', () => { addComment('welcome.txt', 'A comment') + cy.visit('/apps/files') showActivityTab('welcome.txt') cy.get('.comments-activity').first().should('contains.text', 'A comment') diff --git a/cypress/e2e/sidebarUtils.ts b/cypress/e2e/sidebarUtils.ts index 4b98604e5..a1f01d641 100644 --- a/cypress/e2e/sidebarUtils.ts +++ b/cypress/e2e/sidebarUtils.ts @@ -15,13 +15,16 @@ export function closeSidebar() { cy.get('body') .then(($body) => { if ($body.find('.app-sidebar__close').length !== 0) { - cy.get('.app-sidebar__close').click({ force: true }) + // {force: true} as it might be hidden behind toasts + cy.get('[data-cy-sidebar] .app-sidebar__close').click({ force: true }) } }) cy.get('#app-sidebar-vue').should('not.exist') } export function showActivityTab(fileName: string) { + cy.intercept('GET', '/ocs/v2.php/apps/activity/api/v2/activity/filter**').as('getActivities') + showSidebarForFile(fileName) cy.get('#app-sidebar-vue') .findByRole('tab', { name: 'Activity' }) @@ -30,6 +33,8 @@ export function showActivityTab(fileName: string) { cy.get('#app-sidebar-vue') .findByRole('tabpanel', { name: 'Activity' }) .should('be.visible') + + cy.wait('@getActivities') } export function toggleFavorite(fileName: string) { @@ -47,6 +52,8 @@ export function toggleFavorite(fileName: string) { * @param fileName Name of the file to share */ export function createPublicShare(fileName: string) { + cy.intercept('POST', '/ocs/v2.php/apps/files_sharing/api/v1/shares').as('createPublicShare') + showSidebarForFile(fileName) cy.get('#app-sidebar-vue') .findByRole('tab', { name: 'Sharing' }) @@ -59,9 +66,11 @@ export function createPublicShare(fileName: string) { .should('be.visible') .findByRole('button', { name: "Create a new share link" }) .click({ force: true }) - + cy.wait('@createShare') closeSidebar() + + cy.wait('@createPublicShare') } export function addTag(fileName: string, tag: string) { @@ -76,7 +85,7 @@ export function addTag(fileName: string, tag: string) { .should('be.visible') .click() - cy.intercept('PUT', '**/remote.php/dav/systemtags-relations/files/**').as('tag') + cy.intercept('POST', '/remote.php/dav/systemtags').as('tag') cy.findByLabelText('Search or create collaborative tags') .type(`${tag}{enter}{esc}`) diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index 20bddf2b7..ad5fa26b9 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -6,7 +6,8 @@ "@testing-library/cypress", "cypress", "dockerode", - "node" + "node", + "@testing-library/cypress" ] } } \ No newline at end of file