Skip to content

Commit 1b90e1f

Browse files
committed
test(cypress): split helpers for files actions to make tests less flaky
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent 4ce1980 commit 1b90e1f

File tree

5 files changed

+64
-63
lines changed

5 files changed

+64
-63
lines changed

cypress/e2e/files/FilesUtils.ts

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,65 +15,65 @@ 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)}"]`)
33+
.should('be.visible')
4034
}
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))
35+
36+
export const getInlineActionEntryForFile = (file: string, actionId: string) => {
37+
return getActionsForFile(file)
38+
.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
39+
.should('be.visible')
4540
}
4641

4742
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')
43+
getActionButtonForFileId(fileid)
5444
.scrollIntoView()
55-
cy.get('@actionButton')
45+
getActionButtonForFileId(fileid)
5646
.should('be.visible')
57-
.click({ force: true })
47+
.click()
48+
getActionEntryForFileId(fileid, actionId)
49+
.find('button')
50+
.should('be.visible')
51+
.click()
5852
}
53+
5954
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')
55+
getActionButtonForFile(filename)
6656
.scrollIntoView()
67-
cy.get('@actionButton')
57+
getActionButtonForFile(filename)
6858
.should('be.visible')
69-
.click({ force: true })
59+
.click()
60+
getActionEntryForFile(filename, actionId)
61+
.find('button')
62+
.should('be.visible')
63+
.click()
7064
}
7165

7266
export const triggerInlineActionForFileId = (fileid: number, actionId: string) => {
73-
getActionsForFileId(fileid).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
67+
getActionsForFileId(fileid)
68+
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
69+
.should('exist')
70+
.click()
7471
}
7572
export const triggerInlineActionForFile = (filename: string, actionId: string) => {
76-
getActionsForFile(filename).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
73+
getActionsForFile(filename)
74+
.find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
75+
.should('exist')
76+
.click()
7777
}
7878

7979
export const selectAllFiles = () => {
@@ -176,12 +176,16 @@ export const copyFile = (fileName: string, dirPath: string) => {
176176

177177
export const renameFile = (fileName: string, newFileName: string) => {
178178
getRowForFile(fileName)
179+
.should('be.visible')
180+
.scrollIntoView()
179181
triggerActionForFile(fileName, 'rename')
180182

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

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

186190
cy.wait('@moveFile')
187191
}

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_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/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)