From ca78653c4578d818b72ed5c6ed02d0dabf8c9c4f Mon Sep 17 00:00:00 2001 From: Elizabeth Danzberger Date: Thu, 29 Jan 2026 16:52:55 -0500 Subject: [PATCH 1/2] fix(test): stabilize save as test Signed-off-by: Elizabeth Danzberger --- cypress/e2e/integration.spec.js | 24 ++++++++++++------------ cypress/support/commands.js | 19 +++++++++++-------- src/view/FilesAppIntegration.js | 2 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/cypress/e2e/integration.spec.js b/cypress/e2e/integration.spec.js index 489c1edd67..e13aec3f32 100644 --- a/cypress/e2e/integration.spec.js +++ b/cypress/e2e/integration.spec.js @@ -81,22 +81,22 @@ describe('Nextcloud integration', function() { }) - cy.get('.saveas-dialog').should('be.visible') - cy.get('.saveas-dialog input[type=text]') - .should('be.visible') - .should('have.value', `/${exportFilename}`) + cy.get('.saveas-dialog').should('be.visible') + cy.get('.saveas-dialog input[type=text]') + .should('be.visible') + .should('have.value', `/${exportFilename}`) - cy.get('.saveas-dialog button.button-vue--vue-primary').click() + cy.get('.saveas-dialog button.button-vue--vue-primary').click() - cy.get('@loleafletframe').within(() => { - cy.get('#closebutton').click() - cy.waitForViewerClose() - }) + // Wait for confirmation from Collabora that the file was saved + cy.waitForPostMessage('Action_Save_Resp', { success: true, fileName: exportFilename }) - // FIXME: We should not need to reload - cy.get('.breadcrumb__crumbs a').eq(0).click({ force: true }) + cy.get('@loleafletframe').within(() => { + cy.get('#closebutton').click() + cy.waitForViewerClose() + }) - cy.openFile(exportFilename) + cy.openFile(exportFilename) }) it('Open locally', function() { diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 8000036a88..31235621bd 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -277,18 +277,22 @@ Cypress.Commands.add('waitForCollabora', (wrapped = false, federated = false) => return cy.get('@loleafletframe') }) -Cypress.Commands.add('waitForPostMessage', (messageId, values = undefined) => { +Cypress.Commands.add('waitForPostMessage', (messageId, expectedValues = undefined) => { cy.get('@postMessage', { timeout: 20000 }).should(spy => { - const calls = spy.getCalls() + const calls = spy.getCalls() const findMatchingCall = calls.find(call => call.args[0].indexOf('"MessageId":"' + messageId + '"') !== -1) + if (!findMatchingCall) { return expect(findMatchingCall).to.not.be.undefined } - if (!values) { - const object = JSON.parse(findMatchingCall.args[0]) - values.forEach(value => { - expect(object.Values).to.have.property(value, values[value]) - }) + + if (expectedValues) { + const message = JSON.parse(findMatchingCall.args[0]) + + for (const [key, value] of Object.entries(expectedValues)) { + expect(message.Values).to.have.property(key) + expect(message.Values[key]).to.equal(value) + } } }) }) @@ -404,7 +408,6 @@ Cypress.Commands.add('verifyTemplateFields', (fields, fileId) => { break default: expect.fail('Using a field type not yet supported') - break } } }) diff --git a/src/view/FilesAppIntegration.js b/src/view/FilesAppIntegration.js index abf4d95f28..e60b0be3bb 100644 --- a/src/view/FilesAppIntegration.js +++ b/src/view/FilesAppIntegration.js @@ -11,7 +11,7 @@ import axios from '@nextcloud/axios' import { emit } from '@nextcloud/event-bus' import { getCurrentDirectory } from '../helpers/filesApp.js' import { - getSidebar + getSidebar, } from '@nextcloud/files' import { getClient, From 6d3e013156d89c6e003e304ba6bba9bccda7431c Mon Sep 17 00:00:00 2001 From: Elizabeth Danzberger Date: Thu, 29 Jan 2026 19:30:57 -0500 Subject: [PATCH 2/2] fix(test): properly wait for post message Signed-off-by: Elizabeth Danzberger --- cypress/support/commands.js | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 31235621bd..84d5f927c0 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -278,21 +278,40 @@ Cypress.Commands.add('waitForCollabora', (wrapped = false, federated = false) => }) Cypress.Commands.add('waitForPostMessage', (messageId, expectedValues = undefined) => { - cy.get('@postMessage', { timeout: 20000 }).should(spy => { - const calls = spy.getCalls() - const findMatchingCall = calls.find(call => call.args[0].indexOf('"MessageId":"' + messageId + '"') !== -1) + const checkExpectedValues = (message, values) => { + for (const [key, value] of Object.entries(values)) { + if (!message.Values[key] || message.Values[key] !== value) { + return false + } + } + + return true + } - if (!findMatchingCall) { - return expect(findMatchingCall).to.not.be.undefined + cy.get('@postMessage', { timeout: 20000 }).should(spy => { + const calls = spy.getCalls() + const messagesMatchingId = [] + + // Find all messages matching the given ID + // We do it this way to avoid the shallow copy of Array.filter() + for (const call of calls) { + if (call.args[0].includes(`"MessageId":"${messageId}"`)) { + messagesMatchingId.push(JSON.parse(call.args[0])) + } } + expect(messagesMatchingId.length).to.be.greaterThan(0) + if (expectedValues) { - const message = JSON.parse(findMatchingCall.args[0]) + const messagesMatchingValues = [] - for (const [key, value] of Object.entries(expectedValues)) { - expect(message.Values).to.have.property(key) - expect(message.Values[key]).to.equal(value) + for (const message of messagesMatchingId) { + if (checkExpectedValues(message, expectedValues)) { + messagesMatchingValues.push(message) + } } + + expect(messagesMatchingValues.length).to.be.greaterThan(0) } }) })