Skip to content

Commit 48dc04b

Browse files
authored
Merge pull request #54237 from nextcloud/test/fix-cypress
2 parents 7c69862 + 88be308 commit 48dc04b

File tree

8 files changed

+96
-73
lines changed

8 files changed

+96
-73
lines changed

cypress/e2e/files/FilesUtils.ts

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,65 +15,63 @@ export const getActionsForFile = (filename: string) => getRowForFile(filename).f
1515
export const getActionButtonForFileId = (fileid: number) => getActionsForFileId(fileid).findByRole('button', { name: 'Actions' })
1616
export const getActionButtonForFile = (filename: string) => getActionsForFile(filename).findByRole('button', { name: 'Actions' })
1717

18-
const searchForActionInRow = (row: JQuery<HTMLElement>, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
19-
const action = row.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
20-
if (action.length > 0) {
21-
cy.log('Found action in row')
22-
return cy.wrap(action)
23-
}
24-
25-
// Else look in the action menu
26-
const menuButtonId = row.find('button[aria-controls]').attr('aria-controls')
27-
if (menuButtonId === undefined) {
28-
return cy.wrap(Cypress.$())
29-
}
18+
export const getActionEntryForFileId = (fileid: number, actionId: string) => {
19+
return getActionButtonForFileId(fileid)
20+
.should('have.attr', 'aria-controls')
21+
.then((menuId) => cy.get(`#${menuId}`).find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`))
22+
}
3023

31-
// eslint-disable-next-line no-unused-expressions
32-
expect(menuButtonId).not.to.be.undefined
33-
return cy.get(`#${menuButtonId} [data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
24+
export const getActionEntryForFile = (file: string, actionId: string) => {
25+
return getActionButtonForFile(file)
26+
.should('have.attr', 'aria-controls')
27+
.then((menuId) => cy.get(`#${menuId}`).find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`))
3428
}
3529

36-
export const getActionEntryForFileId = (fileid: number, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
37-
// If we cannot find the action in the row, it might be in the action menu
38-
return getRowForFileId(fileid).should('be.visible')
39-
.then((row) => searchForActionInRow(row, actionId))
30+
export const getInlineActionEntryForFileId = (fileid: number, actionId: string) => {
31+
return getActionsForFileId(fileid)
32+
.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
4033
}
41-
export const getActionEntryForFile = (filename: string, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
42-
// If we cannot find the action in the row, it might be in the action menu
43-
return getRowForFile(filename).should('be.visible')
44-
.then((row) => searchForActionInRow(row, actionId))
34+
35+
export const getInlineActionEntryForFile = (file: string, actionId: string) => {
36+
return getActionsForFile(file)
37+
.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
4538
}
4639

4740
export const triggerActionForFileId = (fileid: number, actionId: string) => {
48-
// Even if it's inline, we open the action menu to get all actions visible
49-
getActionButtonForFileId(fileid).click({ force: true })
50-
// wait for the actions menu to be visible
51-
cy.findByRole('menu').findAllByRole('menuitem').first().should('be.visible')
52-
getActionEntryForFileId(fileid, actionId)
53-
.find('button').last().as('actionButton')
41+
getActionButtonForFileId(fileid)
42+
.as('actionButton')
5443
.scrollIntoView()
5544
cy.get('@actionButton')
45+
.click({ force: true }) // force to avoid issues with overlaying file list header
46+
getActionEntryForFileId(fileid, actionId)
47+
.find('button')
5648
.should('be.visible')
57-
.click({ force: true })
49+
.click()
5850
}
51+
5952
export const triggerActionForFile = (filename: string, actionId: string) => {
60-
// Even if it's inline, we open the action menu to get all actions visible
61-
getActionButtonForFile(filename).click({ force: true })
62-
// wait for the actions menu to be visible
63-
cy.findByRole('menu').findAllByRole('menuitem').first().should('be.visible')
64-
getActionEntryForFile(filename, actionId)
65-
.find('button').last().as('actionButton')
53+
getActionButtonForFile(filename)
54+
.as('actionButton')
6655
.scrollIntoView()
6756
cy.get('@actionButton')
57+
.click({ force: true }) // force to avoid issues with overlaying file list header
58+
getActionEntryForFile(filename, actionId)
59+
.find('button')
6860
.should('be.visible')
69-
.click({ force: true })
61+
.click()
7062
}
7163

7264
export const triggerInlineActionForFileId = (fileid: number, actionId: string) => {
73-
getActionsForFileId(fileid).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
65+
getActionsForFileId(fileid)
66+
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
67+
.should('exist')
68+
.click()
7469
}
7570
export const triggerInlineActionForFile = (filename: string, actionId: string) => {
76-
getActionsForFile(filename).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
71+
getActionsForFile(filename)
72+
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
73+
.should('exist')
74+
.click()
7775
}
7876

7977
export const selectAllFiles = () => {
@@ -176,12 +174,17 @@ export const copyFile = (fileName: string, dirPath: string) => {
176174

177175
export const renameFile = (fileName: string, newFileName: string) => {
178176
getRowForFile(fileName)
177+
.should('exist')
178+
.scrollIntoView()
179+
179180
triggerActionForFile(fileName, 'rename')
180181

181182
// intercept the move so we can wait for it
182183
cy.intercept('MOVE', /\/(remote|public)\.php\/dav\/files\//).as('moveFile')
183184

184-
getRowForFile(fileName).find('[data-cy-files-list-row-name] input').type(`{selectAll}${newFileName}{enter}`)
185+
getRowForFile(fileName)
186+
.find('[data-cy-files-list-row-name] input')
187+
.type(`{selectAll}${newFileName}{enter}`)
185188

186189
cy.wait('@moveFile')
187190
}

cypress/e2e/files/files-actions.cy.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { getActionButtonForFileId, getActionEntryForFileId, getRowForFile, getSe
1010
import { ACTION_COPY_MOVE } from '../../../apps/files/src/actions/moveOrCopyAction'
1111
import { ACTION_DELETE } from '../../../apps/files/src/actions/deleteAction'
1212
import { ACTION_DETAILS } from '../../../apps/files/src/actions/sidebarAction'
13-
import { ACTION_SHARING_STATUS } from '../../../apps/files_sharing/src/files_actions/sharingStatusAction'
1413

1514
declare global {
1615
interface Window {
@@ -24,7 +23,6 @@ const expectedDefaultActionsIDs = [
2423
ACTION_COPY_MOVE,
2524
ACTION_DELETE,
2625
ACTION_DETAILS,
27-
ACTION_SHARING_STATUS,
2826
]
2927
const expectedDefaultSelectionActionsIDs = [
3028
ACTION_COPY_MOVE,
@@ -90,11 +88,13 @@ describe('Files: Actions', { testIsolation: true }, () => {
9088
win._nc_fileactions.push(parent)
9189
win._nc_fileactions.push(child1)
9290
win._nc_fileactions.push(child2)
93-
}
91+
},
9492
})
9593

9694
// Open the menu
97-
getActionButtonForFileId(fileId).click({ force: true })
95+
getActionButtonForFileId(fileId)
96+
.scrollIntoView()
97+
.click({ force: true })
9898

9999
// Check we have the parent action but not the children
100100
getActionEntryForFileId(fileId, 'nested-action').should('be.visible')
@@ -104,8 +104,8 @@ describe('Files: Actions', { testIsolation: true }, () => {
104104

105105
// Click on the parent action
106106
getActionEntryForFileId(fileId, 'nested-action')
107-
.find('button').last()
108-
.should('exist').click({ force: true })
107+
.should('be.visible')
108+
.click()
109109

110110
// Check we have the children and the back button but not the parent
111111
getActionEntryForFileId(fileId, 'nested-action').should('not.exist')
@@ -115,8 +115,8 @@ describe('Files: Actions', { testIsolation: true }, () => {
115115

116116
// Click on the back button
117117
getActionEntryForFileId(fileId, 'menu-back')
118-
.find('button').last()
119-
.should('exist').click({ force: true })
118+
.should('be.visible')
119+
.click()
120120

121121
// Check we have the parent action but not the children
122122
getActionEntryForFileId(fileId, 'nested-action').should('be.visible')
@@ -177,7 +177,7 @@ describe('Files: Actions', { testIsolation: true }, () => {
177177
win._nc_fileactions.push(parent)
178178
win._nc_fileactions.push(child1)
179179
win._nc_fileactions.push(child2)
180-
}
180+
},
181181
})
182182

183183
selectRowForFile('image.jpg')

cypress/e2e/files/files-renaming.cy.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,16 @@ describe('files: Rename nodes', { testIsolation: true }, () => {
181181

182182
cy.visit('/apps/files')
183183

184-
getRowForFile('file.txt').should('be.visible')
184+
getRowForFile('file.txt')
185+
.should('be.visible')
185186
// Z so it is shown last
186187
renameFile('file.txt', 'zzz.txt')
187188
// not visible any longer
188-
getRowForFile('zzz.txt').should('not.exist')
189+
getRowForFile('zzz.txt')
190+
.should('not.exist')
189191
// scroll file list to bottom
190-
cy.get('[data-cy-files-list]').scrollTo('bottom')
192+
cy.get('[data-cy-files-list]')
193+
.scrollTo('bottom')
191194
cy.screenshot()
192195
// The file is no longer in rename state
193196
getRowForFile('zzz.txt')

cypress/e2e/files_external/files-user-credentials.cy.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { User } from '@nextcloud/cypress'
77
import { AuthBackend, createStorageWithConfig, StorageBackend } from './StorageUtils'
8-
import { getActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils'
8+
import { getInlineActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils'
99

1010
import { ACTION_CREDENTIALS_EXTERNAL_STORAGE } from '../../../apps/files_external/src/actions/enterCredentialsAction'
1111
import { handlePasswordConfirmation } from '../settings/usersUtils'
@@ -72,7 +72,8 @@ describe('Files user credentials', { testIsolation: true }, () => {
7272
// Auth dialog should be closed and the set credentials button should be gone
7373
cy.get('@authDialog').should('not.exist', { timeout: 2000 })
7474

75-
getActionEntryForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
75+
getInlineActionEntryForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE)
76+
.should('not.exist')
7677

7778
// Finally, the storage should be accessible
7879
cy.visit('/apps/files')
@@ -112,7 +113,7 @@ describe('Files user credentials', { testIsolation: true }, () => {
112113

113114
// Auth dialog should be closed and the set credentials button should be gone
114115
cy.get('@authDialog').should('not.exist', { timeout: 2000 })
115-
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
116+
getInlineActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
116117

117118
// Finally, the storage should be accessible
118119
cy.visit('/apps/files')
@@ -131,8 +132,8 @@ describe('Files user credentials', { testIsolation: true }, () => {
131132
getRowForFile('storage2').should('be.visible')
132133

133134
// Since we already have set the credentials, the action should not be present
134-
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
135-
getActionEntryForFile('storage2', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
135+
getInlineActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
136+
getInlineActionEntryForFile('storage2', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
136137

137138
// Finally, the storage should be accessible
138139
cy.visit('/apps/files')

cypress/e2e/files_sharing/FilesSharingUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ export function updateShare(fileName: string, index: number, shareSettings: Part
125125
export function openSharingPanel(fileName: string) {
126126
triggerActionForFile(fileName, 'details')
127127

128-
cy.get('#app-sidebar-vue')
129-
.get('[aria-controls="tab-sharing"]')
128+
cy.get('[data-cy-sidebar]')
129+
.find('[aria-controls="tab-sharing"]')
130130
.click()
131131
}
132132

cypress/e2e/files_sharing/files-download.cy.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import type { User } from '@nextcloud/cypress'
66
import { createShare } from './FilesSharingUtils.ts'
77
import {
8+
getActionButtonForFile,
89
getActionEntryForFile,
910
getRowForFile,
1011
} from '../files/FilesUtils.ts'
@@ -41,8 +42,13 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
4142
// visit shared files view
4243
cy.visit('/apps/files')
4344
// see the shared folder
44-
getRowForFile('folder').should('be.visible')
45-
getActionEntryForFile('folder', 'download').should('not.exist')
45+
getActionButtonForFile('folder')
46+
.should('be.visible')
47+
// open the action menu
48+
.click({ force: true })
49+
// see no download action
50+
getActionEntryForFile('folder', 'download')
51+
.should('not.exist')
4652

4753
// Disable view without download option
4854
cy.runOccCommand('config:app:set --value no core shareapi_allow_view_without_download')
@@ -51,6 +57,10 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
5157
cy.visit('/apps/files')
5258
// see the shared folder
5359
getRowForFile('folder').should('be.visible')
60+
getActionButtonForFile('folder')
61+
.should('be.visible')
62+
// open the action menu
63+
.click({ force: true })
5464
getActionEntryForFile('folder', 'download').should('not.exist')
5565
})
5666

@@ -68,8 +78,13 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
6878
// visit shared files view
6979
cy.visit('/apps/files')
7080
// see the shared folder
71-
getRowForFile('file.txt').should('be.visible')
72-
getActionEntryForFile('file.txt', 'download').should('not.exist')
81+
getActionButtonForFile('file.txt')
82+
.should('be.visible')
83+
// open the action menu
84+
.click({ force: true })
85+
// see no download action
86+
getActionEntryForFile('file.txt', 'download')
87+
.should('not.exist')
7388

7489
// Disable view without download option
7590
cy.runOccCommand('config:app:set --value no core shareapi_allow_view_without_download')
@@ -78,6 +93,10 @@ describe('files_sharing: Download forbidden', { testIsolation: true }, () => {
7893
cy.visit('/apps/files')
7994
// see the shared folder
8095
getRowForFile('file.txt').should('be.visible')
96+
getActionButtonForFile('file.txt')
97+
.should('be.visible')
98+
// open the action menu
99+
.click({ force: true })
81100
getActionEntryForFile('file.txt', 'download').should('not.exist')
82101
})
83102
})

cypress/e2e/files_sharing/note-to-recipient.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('files_sharing: Note to recipient', { testIsolation: true }, () => {
7272
createShare('folder', sharee.userId, { read: true, download: true, note: 'Hello, this is the note.' })
7373

7474
// reload just to be sure
75-
cy.reload()
75+
cy.visit('/apps/files')
7676

7777
// open the sharing tab
7878
openSharingPanel('folder')

cypress/e2e/files_sharing/share-status-action.cy.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import type { User } from '@nextcloud/cypress'
66
import { createShare } from './FilesSharingUtils.ts'
7-
import { closeSidebar, enableGridMode, getActionButtonForFile, getRowForFile } from '../files/FilesUtils.ts'
7+
import { closeSidebar, enableGridMode, getActionButtonForFile, getInlineActionEntryForFile, getRowForFile } from '../files/FilesUtils.ts'
88

99
describe('files_sharing: Sharing status action', { testIsolation: true }, () => {
1010
/**
@@ -78,10 +78,9 @@ describe('files_sharing: Sharing status action', { testIsolation: true }, () =>
7878
cy.login(user)
7979
cy.visit('/apps/files')
8080

81-
getRowForFile('folder')
82-
.should('be.visible')
83-
.find('[data-cy-files-list-row-actions]')
84-
.findByRole('button', { name: /^Shared with/i })
81+
getInlineActionEntryForFile('folder', 'sharing-status')
82+
.should('have.attr', 'aria-label', `Shared with ${sharee.userId}`)
83+
.should('have.attr', 'title', `Shared with ${sharee.userId}`)
8584
.should('be.visible')
8685
})
8786

@@ -103,10 +102,8 @@ describe('files_sharing: Sharing status action', { testIsolation: true }, () =>
103102
cy.login(sharee)
104103
cy.visit('/apps/files')
105104

106-
getRowForFile('folder')
107-
.should('be.visible')
108-
.find('[data-cy-files-list-row-actions]')
109-
.findByRole('button', { name: `Shared by ${user.userId}` })
105+
getInlineActionEntryForFile('folder', 'sharing-status')
106+
.should('have.attr', 'aria-label', `Shared by ${user.userId}`)
110107
.should('be.visible')
111108
})
112109

0 commit comments

Comments
 (0)