Skip to content

Commit 6d855bb

Browse files
committed
chore(cypress): Try to analyze failures
Assisted-by: ClaudeCode:claude-fable-5 Signed-off-by: David Dreschner <david.dreschner@nextcloud.com>
1 parent 8e59426 commit 6d855bb

4 files changed

Lines changed: 52 additions & 7 deletions

File tree

build/psalm-baseline.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,7 @@
22092209
<code><![CDATA[unlink]]></code>
22102210
<code><![CDATA[unlockFile]]></code>
22112211
<code><![CDATA[unlockFile]]></code>
2212+
<code><![CDATA[unlockFile]]></code>
22122213
</InternalMethod>
22132214
</file>
22142215
<file src="apps/files_versions/lib/Versions/LegacyVersionsBackend.php">

cypress/e2e/files/FilesUtils.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,13 @@ export function moveFile(fileName: string, dirPath: string) {
230230
.findByRole('button', { name: 'All files' })
231231
.should('be.visible')
232232
.click()
233-
// [picker-diag] log the exact button texts to see the root label
234-
cy.get('button').then(($b) => cy.task('log', '[picker-diag] move buttons=' + JSON.stringify(Array.from($b).map((x) => (x as HTMLElement).textContent)), { log: false }))
235233
// Click move. Match the confirm button EXACTLY as "Move": the picker
236234
// labels it "Move to {folder}" while inside a folder and only "Move"
237235
// once it has navigated to the home root. A loose `contains('Move')`
238236
// would match the stale "Move to {folder}" button before the "All
239237
// files" navigation above has landed, moving the file into the wrong
240238
// folder. The exact match makes cypress wait for the root button.
241-
cy.contains('button', /^\s*Move\s*$/).should('be.visible').click()
239+
cy.contains('button', /^Move\s*$/).should('be.visible').click()
242240
} else if (dirPath === '.') {
243241
// click move
244242
cy.contains('button', 'Copy').should('be.visible').click()
@@ -276,16 +274,14 @@ export function copyFile(fileName: string, dirPath: string) {
276274
.findByRole('button', { name: 'All files' })
277275
.should('be.visible')
278276
.click()
279-
// [picker-diag] log the exact button texts to see the root label
280-
cy.get('button').then(($b) => cy.task('log', '[picker-diag] copy buttons=' + JSON.stringify(Array.from($b).map((x) => (x as HTMLElement).textContent)), { log: false }))
281277
// Click copy. Match the confirm button EXACTLY as "Copy": the picker
282278
// labels it "Copy to {folder}" while inside a folder and only "Copy"
283279
// once it has navigated to the home root. A loose `contains('Copy')`
284280
// would match the stale "Copy to {folder}" button before the "All
285281
// files" navigation above has landed, copying the file into the wrong
286282
// folder (deduplicated as "… (1)"). The exact match makes cypress
287283
// wait for the root button.
288-
cy.contains('button', /^\s*Copy\s*$/).should('be.visible').click()
284+
cy.contains('button', /^Copy\s*$/).should('be.visible').click()
289285
} else if (dirPath === '.') {
290286
// click copy
291287
cy.contains('button', 'Copy').should('be.visible').click()

cypress/e2e/files_versions/login_flake_repro.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
* --spec cypress/e2e/files_versions/login_flake_repro.cy.ts
1414
*/
1515

16-
import { setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
1716
import { randomString } from '../../support/utils/randomString.ts'
17+
import { setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
1818

1919
describe('[login-diag] login flake repro', () => {
2020
const folderName = 'shared_folder'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*
5+
* [menu-verify] THROWAWAY probe. Does a plain single open-click on a file-row
6+
* actions toggle get LOST on a slow (0.2 CPU) runner? A lost click leaves
7+
* aria-expanded="false" and the menu never opens — which the raised
8+
* defaultCommandTimeout cannot fix (it would just wait the full timeout on a
9+
* menu that will never open). This is what the openActionsMenu re-click poll
10+
* exists to handle. If aria-expanded stays "false" here, the poll is still
11+
* needed even with the timeout raise.
12+
*/
13+
14+
import { getActionButtonForFile } from '../files/FilesUtils.ts'
15+
16+
describe('[menu-verify] single-click actions-menu open', () => {
17+
it('detects lost open-clicks (no re-click)', () => {
18+
const files = Array.from({ length: 12 }, (_, i) => `mv${i}.txt`)
19+
cy.createRandomUser().then((user) => {
20+
files.forEach((f) => cy.uploadContent(user, new Blob([f], { type: 'text/plain' }), 'text/plain', `/${f}`))
21+
cy.login(user)
22+
cy.visit('/apps/files')
23+
24+
const lost: string[] = []
25+
cy.wrap(files).each((f: string) => {
26+
getActionButtonForFile(f).scrollIntoView()
27+
// A single, plain click — exactly what master's helper did before
28+
// the openActionsMenu re-click poll was added.
29+
getActionButtonForFile(f).click({ force: true })
30+
// Give the click's handler ample time to fire (1s is plenty on any
31+
// runner if the click actually registered), then inspect the toggle.
32+
// eslint-disable-next-line cypress/no-unnecessary-waiting
33+
cy.wait(1000)
34+
getActionButtonForFile(f).then(($t) => {
35+
const exp = $t.attr('aria-expanded')
36+
cy.task('log', `[menu-verify] ${f}: aria-expanded=${exp} 1s after single click`)
37+
if (exp !== 'true') {
38+
lost.push(f)
39+
}
40+
})
41+
// Reset for the next file (close the menu if it did open).
42+
cy.get('body').type('{esc}')
43+
}).then(() => {
44+
cy.task('log', `[menu-verify] LOST OPEN-CLICKS: ${lost.length}/${files.length} -> [${lost.join(', ')}]`)
45+
})
46+
})
47+
})
48+
})

0 commit comments

Comments
 (0)