mirror of
https://github.com/nextcloud/server.git
synced 2026-02-26 03:11:28 -05:00
Merge pull request #54237 from nextcloud/test/fix-cypress
This commit is contained in:
commit
48dc04b571
8 changed files with 98 additions and 75 deletions
|
|
@ -15,65 +15,63 @@ export const getActionsForFile = (filename: string) => getRowForFile(filename).f
|
|||
export const getActionButtonForFileId = (fileid: number) => getActionsForFileId(fileid).findByRole('button', { name: 'Actions' })
|
||||
export const getActionButtonForFile = (filename: string) => getActionsForFile(filename).findByRole('button', { name: 'Actions' })
|
||||
|
||||
const searchForActionInRow = (row: JQuery<HTMLElement>, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
|
||||
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 getActionEntryForFileId = (fileid: number, actionId: string) => {
|
||||
return getActionButtonForFileId(fileid)
|
||||
.should('have.attr', 'aria-controls')
|
||||
.then((menuId) => cy.get(`#${menuId}`).find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`))
|
||||
}
|
||||
|
||||
export const getActionEntryForFileId = (fileid: number, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
|
||||
// If we cannot find the action in the row, it might be in the action menu
|
||||
return getRowForFileId(fileid).should('be.visible')
|
||||
.then((row) => searchForActionInRow(row, actionId))
|
||||
export const getActionEntryForFile = (file: string, actionId: string) => {
|
||||
return getActionButtonForFile(file)
|
||||
.should('have.attr', 'aria-controls')
|
||||
.then((menuId) => cy.get(`#${menuId}`).find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`))
|
||||
}
|
||||
export const getActionEntryForFile = (filename: string, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
|
||||
// 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 getInlineActionEntryForFileId = (fileid: number, actionId: string) => {
|
||||
return getActionsForFileId(fileid)
|
||||
.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
|
||||
}
|
||||
|
||||
export const getInlineActionEntryForFile = (file: string, actionId: string) => {
|
||||
return getActionsForFile(file)
|
||||
.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
|
||||
}
|
||||
|
||||
export const triggerActionForFileId = (fileid: number, actionId: string) => {
|
||||
// Even if it's inline, we open the action menu to get all actions visible
|
||||
getActionButtonForFileId(fileid).click({ force: true })
|
||||
// wait for the actions menu to be visible
|
||||
cy.findByRole('menu').findAllByRole('menuitem').first().should('be.visible')
|
||||
getActionButtonForFileId(fileid)
|
||||
.as('actionButton')
|
||||
.scrollIntoView()
|
||||
cy.get('@actionButton')
|
||||
.click({ force: true }) // force to avoid issues with overlaying file list header
|
||||
getActionEntryForFileId(fileid, actionId)
|
||||
.find('button').last().as('actionButton')
|
||||
.scrollIntoView()
|
||||
cy.get('@actionButton')
|
||||
.find('button')
|
||||
.should('be.visible')
|
||||
.click({ force: true })
|
||||
.click()
|
||||
}
|
||||
|
||||
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 })
|
||||
// wait for the actions menu to be visible
|
||||
cy.findByRole('menu').findAllByRole('menuitem').first().should('be.visible')
|
||||
getActionEntryForFile(filename, actionId)
|
||||
.find('button').last().as('actionButton')
|
||||
getActionButtonForFile(filename)
|
||||
.as('actionButton')
|
||||
.scrollIntoView()
|
||||
cy.get('@actionButton')
|
||||
.click({ force: true }) // force to avoid issues with overlaying file list header
|
||||
getActionEntryForFile(filename, actionId)
|
||||
.find('button')
|
||||
.should('be.visible')
|
||||
.click({ force: true })
|
||||
.click()
|
||||
}
|
||||
|
||||
export const triggerInlineActionForFileId = (fileid: number, actionId: string) => {
|
||||
getActionsForFileId(fileid).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
|
||||
getActionsForFileId(fileid)
|
||||
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
|
||||
.should('exist')
|
||||
.click()
|
||||
}
|
||||
export const triggerInlineActionForFile = (filename: string, actionId: string) => {
|
||||
getActionsForFile(filename).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
|
||||
getActionsForFile(filename)
|
||||
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
|
||||
.should('exist')
|
||||
.click()
|
||||
}
|
||||
|
||||
export const selectAllFiles = () => {
|
||||
|
|
@ -176,12 +174,17 @@ export const copyFile = (fileName: string, dirPath: string) => {
|
|||
|
||||
export const renameFile = (fileName: string, newFileName: string) => {
|
||||
getRowForFile(fileName)
|
||||
.should('exist')
|
||||
.scrollIntoView()
|
||||
|
||||
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').type(`{selectAll}${newFileName}{enter}`)
|
||||
getRowForFile(fileName)
|
||||
.find('[data-cy-files-list-row-name] input')
|
||||
.type(`{selectAll}${newFileName}{enter}`)
|
||||
|
||||
cy.wait('@moveFile')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { getActionButtonForFileId, getActionEntryForFileId, getRowForFile, getSe
|
|||
import { ACTION_COPY_MOVE } from '../../../apps/files/src/actions/moveOrCopyAction'
|
||||
import { ACTION_DELETE } from '../../../apps/files/src/actions/deleteAction'
|
||||
import { ACTION_DETAILS } from '../../../apps/files/src/actions/sidebarAction'
|
||||
import { ACTION_SHARING_STATUS } from '../../../apps/files_sharing/src/files_actions/sharingStatusAction'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
@ -24,7 +23,6 @@ const expectedDefaultActionsIDs = [
|
|||
ACTION_COPY_MOVE,
|
||||
ACTION_DELETE,
|
||||
ACTION_DETAILS,
|
||||
ACTION_SHARING_STATUS,
|
||||
]
|
||||
const expectedDefaultSelectionActionsIDs = [
|
||||
ACTION_COPY_MOVE,
|
||||
|
|
@ -90,11 +88,13 @@ describe('Files: Actions', { testIsolation: true }, () => {
|
|||
win._nc_fileactions.push(parent)
|
||||
win._nc_fileactions.push(child1)
|
||||
win._nc_fileactions.push(child2)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
// Open the menu
|
||||
getActionButtonForFileId(fileId).click({ force: true })
|
||||
getActionButtonForFileId(fileId)
|
||||
.scrollIntoView()
|
||||
.click({ force: true })
|
||||
|
||||
// Check we have the parent action but not the children
|
||||
getActionEntryForFileId(fileId, 'nested-action').should('be.visible')
|
||||
|
|
@ -104,8 +104,8 @@ describe('Files: Actions', { testIsolation: true }, () => {
|
|||
|
||||
// Click on the parent action
|
||||
getActionEntryForFileId(fileId, 'nested-action')
|
||||
.find('button').last()
|
||||
.should('exist').click({ force: true })
|
||||
.should('be.visible')
|
||||
.click()
|
||||
|
||||
// Check we have the children and the back button but not the parent
|
||||
getActionEntryForFileId(fileId, 'nested-action').should('not.exist')
|
||||
|
|
@ -115,8 +115,8 @@ describe('Files: Actions', { testIsolation: true }, () => {
|
|||
|
||||
// Click on the back button
|
||||
getActionEntryForFileId(fileId, 'menu-back')
|
||||
.find('button').last()
|
||||
.should('exist').click({ force: true })
|
||||
.should('be.visible')
|
||||
.click()
|
||||
|
||||
// Check we have the parent action but not the children
|
||||
getActionEntryForFileId(fileId, 'nested-action').should('be.visible')
|
||||
|
|
@ -177,7 +177,7 @@ describe('Files: Actions', { testIsolation: true }, () => {
|
|||
win._nc_fileactions.push(parent)
|
||||
win._nc_fileactions.push(child1)
|
||||
win._nc_fileactions.push(child2)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
selectRowForFile('image.jpg')
|
||||
|
|
|
|||
|
|
@ -181,13 +181,16 @@ describe('files: Rename nodes', { testIsolation: true }, () => {
|
|||
|
||||
cy.visit('/apps/files')
|
||||
|
||||
getRowForFile('file.txt').should('be.visible')
|
||||
getRowForFile('file.txt')
|
||||
.should('be.visible')
|
||||
// Z so it is shown last
|
||||
renameFile('file.txt', 'zzz.txt')
|
||||
// not visible any longer
|
||||
getRowForFile('zzz.txt').should('not.exist')
|
||||
getRowForFile('zzz.txt')
|
||||
.should('not.exist')
|
||||
// scroll file list to bottom
|
||||
cy.get('[data-cy-files-list]').scrollTo('bottom')
|
||||
cy.get('[data-cy-files-list]')
|
||||
.scrollTo('bottom')
|
||||
cy.screenshot()
|
||||
// The file is no longer in rename state
|
||||
getRowForFile('zzz.txt')
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { AuthBackend, createStorageWithConfig, StorageBackend } from './StorageUtils'
|
||||
import { getActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils'
|
||||
import { getInlineActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils'
|
||||
|
||||
import { ACTION_CREDENTIALS_EXTERNAL_STORAGE } from '../../../apps/files_external/src/actions/enterCredentialsAction'
|
||||
import { handlePasswordConfirmation } from '../settings/usersUtils'
|
||||
|
|
@ -72,7 +72,8 @@ describe('Files user credentials', { testIsolation: true }, () => {
|
|||
// Auth dialog should be closed and the set credentials button should be gone
|
||||
cy.get('@authDialog').should('not.exist', { timeout: 2000 })
|
||||
|
||||
getActionEntryForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
getInlineActionEntryForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE)
|
||||
.should('not.exist')
|
||||
|
||||
// Finally, the storage should be accessible
|
||||
cy.visit('/apps/files')
|
||||
|
|
@ -112,7 +113,7 @@ describe('Files user credentials', { testIsolation: true }, () => {
|
|||
|
||||
// Auth dialog should be closed and the set credentials button should be gone
|
||||
cy.get('@authDialog').should('not.exist', { timeout: 2000 })
|
||||
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
getInlineActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
|
||||
// Finally, the storage should be accessible
|
||||
cy.visit('/apps/files')
|
||||
|
|
@ -131,8 +132,8 @@ describe('Files user credentials', { testIsolation: true }, () => {
|
|||
getRowForFile('storage2').should('be.visible')
|
||||
|
||||
// Since we already have set the credentials, the action should not be present
|
||||
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
getActionEntryForFile('storage2', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
getInlineActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
getInlineActionEntryForFile('storage2', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
|
||||
|
||||
// Finally, the storage should be accessible
|
||||
cy.visit('/apps/files')
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ export function updateShare(fileName: string, index: number, shareSettings: Part
|
|||
export function openSharingPanel(fileName: string) {
|
||||
triggerActionForFile(fileName, 'details')
|
||||
|
||||
cy.get('#app-sidebar-vue')
|
||||
.get('[aria-controls="tab-sharing"]')
|
||||
cy.get('[data-cy-sidebar]')
|
||||
.find('[aria-controls="tab-sharing"]')
|
||||
.click()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import type { User } from '@nextcloud/cypress'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
import {
|
||||
getActionButtonForFile,
|
||||
getActionEntryForFile,
|
||||
getRowForFile,
|
||||
} from '../files/FilesUtils.ts'
|
||||
|
|
@ -41,8 +42,13 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
|
|||
// visit shared files view
|
||||
cy.visit('/apps/files')
|
||||
// see the shared folder
|
||||
getRowForFile('folder').should('be.visible')
|
||||
getActionEntryForFile('folder', 'download').should('not.exist')
|
||||
getActionButtonForFile('folder')
|
||||
.should('be.visible')
|
||||
// open the action menu
|
||||
.click({ force: true })
|
||||
// see no download action
|
||||
getActionEntryForFile('folder', 'download')
|
||||
.should('not.exist')
|
||||
|
||||
// Disable view without download option
|
||||
cy.runOccCommand('config:app:set --value no core shareapi_allow_view_without_download')
|
||||
|
|
@ -51,6 +57,10 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
|
|||
cy.visit('/apps/files')
|
||||
// see the shared folder
|
||||
getRowForFile('folder').should('be.visible')
|
||||
getActionButtonForFile('folder')
|
||||
.should('be.visible')
|
||||
// open the action menu
|
||||
.click({ force: true })
|
||||
getActionEntryForFile('folder', 'download').should('not.exist')
|
||||
})
|
||||
|
||||
|
|
@ -68,8 +78,13 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
|
|||
// visit shared files view
|
||||
cy.visit('/apps/files')
|
||||
// see the shared folder
|
||||
getRowForFile('file.txt').should('be.visible')
|
||||
getActionEntryForFile('file.txt', 'download').should('not.exist')
|
||||
getActionButtonForFile('file.txt')
|
||||
.should('be.visible')
|
||||
// open the action menu
|
||||
.click({ force: true })
|
||||
// see no download action
|
||||
getActionEntryForFile('file.txt', 'download')
|
||||
.should('not.exist')
|
||||
|
||||
// Disable view without download option
|
||||
cy.runOccCommand('config:app:set --value no core shareapi_allow_view_without_download')
|
||||
|
|
@ -78,6 +93,10 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
|
|||
cy.visit('/apps/files')
|
||||
// see the shared folder
|
||||
getRowForFile('file.txt').should('be.visible')
|
||||
getActionButtonForFile('file.txt')
|
||||
.should('be.visible')
|
||||
// open the action menu
|
||||
.click({ force: true })
|
||||
getActionEntryForFile('file.txt', 'download').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ describe('files_sharing: Note to recipient', { testIsolation: true }, () => {
|
|||
createShare('folder', sharee.userId, { read: true, download: true, note: 'Hello, this is the note.' })
|
||||
|
||||
// reload just to be sure
|
||||
cy.reload()
|
||||
cy.visit('/apps/files')
|
||||
|
||||
// open the sharing tab
|
||||
openSharingPanel('folder')
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
import { closeSidebar, enableGridMode, getActionButtonForFile, getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { closeSidebar, enableGridMode, getActionButtonForFile, getInlineActionEntryForFile, getRowForFile } from '../files/FilesUtils.ts'
|
||||
|
||||
describe('files_sharing: Sharing status action', { testIsolation: true }, () => {
|
||||
/**
|
||||
|
|
@ -78,10 +78,9 @@ describe('files_sharing: Sharing status action', { testIsolation: true }, () =>
|
|||
cy.login(user)
|
||||
cy.visit('/apps/files')
|
||||
|
||||
getRowForFile('folder')
|
||||
.should('be.visible')
|
||||
.find('[data-cy-files-list-row-actions]')
|
||||
.findByRole('button', { name: /^Shared with/i })
|
||||
getInlineActionEntryForFile('folder', 'sharing-status')
|
||||
.should('have.attr', 'aria-label', `Shared with ${sharee.userId}`)
|
||||
.should('have.attr', 'title', `Shared with ${sharee.userId}`)
|
||||
.should('be.visible')
|
||||
})
|
||||
|
||||
|
|
@ -103,10 +102,8 @@ describe('files_sharing: Sharing status action', { testIsolation: true }, () =>
|
|||
cy.login(sharee)
|
||||
cy.visit('/apps/files')
|
||||
|
||||
getRowForFile('folder')
|
||||
.should('be.visible')
|
||||
.find('[data-cy-files-list-row-actions]')
|
||||
.findByRole('button', { name: `Shared by ${user.userId}` })
|
||||
getInlineActionEntryForFile('folder', 'sharing-status')
|
||||
.should('have.attr', 'aria-label', `Shared by ${user.userId}`)
|
||||
.should('be.visible')
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue