From 87cb199745ae4ae9d73f3dfdf5c2bd95acfb9c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 17 Jun 2024 13:41:49 +0200 Subject: [PATCH] fix(editor): Use BroadcastChannel instead of window.opener for OAuth callback window (#9779) --- cypress/e2e/43-oauth-flow.cy.ts | 46 +++++++++++++++++++ cypress/pages/modals/credentials-modal.ts | 12 ++++- .../cli/templates/oauth-callback.handlebars | 3 +- .../templates/oauth-error-callback.handlebars | 5 +- .../CredentialEdit/CredentialConfig.vue | 2 + .../CredentialEdit/CredentialEdit.vue | 12 ++--- 6 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 cypress/e2e/43-oauth-flow.cy.ts diff --git a/cypress/e2e/43-oauth-flow.cy.ts b/cypress/e2e/43-oauth-flow.cy.ts new file mode 100644 index 0000000000..300a202540 --- /dev/null +++ b/cypress/e2e/43-oauth-flow.cy.ts @@ -0,0 +1,46 @@ +import { CredentialsPage, CredentialsModal } from '../pages'; + +const credentialsPage = new CredentialsPage(); +const credentialsModal = new CredentialsModal(); + +describe('Credentials', () => { + it('create and connect with Google OAuth2', () => { + // Open credentials page + cy.visit(credentialsPage.url, { + onBeforeLoad(win) { + cy.stub(win, 'open').as('windowOpen'); + }, + }); + + // Add a new Google OAuth2 credential + credentialsPage.getters.emptyListCreateCredentialButton().click(); + credentialsModal.getters.newCredentialTypeOption('Google OAuth2 API').click(); + credentialsModal.getters.newCredentialTypeButton().click(); + + // Fill in the key/secret and save + credentialsModal.actions.fillField('clientId', 'test-key'); + credentialsModal.actions.fillField('clientSecret', 'test-secret'); + credentialsModal.actions.save(); + + // Connect to Google + credentialsModal.getters.oauthConnectButton().click(); + cy.get('@windowOpen').should( + 'have.been.calledOnceWith', + Cypress.sinon.match( + 'https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent&client_id=test-key&redirect_uri=http%3A%2F%2Flocalhost%3A5678%2Frest%2Foauth2-credential%2Fcallback&response_type=code', + ), + 'OAuth Authorization', + 'scrollbars=no,resizable=yes,status=no,titlebar=noe,location=no,toolbar=no,menubar=no,width=500,height=700', + ); + + // Emulate successful save using BroadcastChannel + cy.window().then(() => { + const channel = new BroadcastChannel('oauth-callback'); + channel.postMessage('success'); + }); + + // Check that the credential was saved and connected successfully + credentialsModal.getters.saveButton().should('contain.text', 'Saved'); + credentialsModal.getters.oauthConnectSuccessBanner().should('be.visible'); + }); +}); diff --git a/cypress/pages/modals/credentials-modal.ts b/cypress/pages/modals/credentials-modal.ts index dff38d035f..f14f6be0b7 100644 --- a/cypress/pages/modals/credentials-modal.ts +++ b/cypress/pages/modals/credentials-modal.ts @@ -9,15 +9,16 @@ export class CredentialsModal extends BasePage { newCredentialTypeOption: (credentialType: string) => cy.getByTestId('new-credential-type-select-option').contains(credentialType), newCredentialTypeButton: () => cy.getByTestId('new-credential-type-button'), - connectionParameters: () => cy.getByTestId('credential-connection-parameter'), connectionParameter: (fieldName: string) => - this.getters.connectionParameters().find(`:contains('${fieldName}') .n8n-input input`), + this.getters.credentialInputs().find(`:contains('${fieldName}') .n8n-input input`), name: () => cy.getByTestId('credential-name'), nameInput: () => cy.getByTestId('credential-name').find('input'), // Saving of the credentials takes a while on the CI so we need to increase the timeout saveButton: () => cy.getByTestId('credential-save-button', { timeout: 5000 }), deleteButton: () => cy.getByTestId('credential-delete-button'), closeButton: () => this.getters.editCredentialModal().find('.el-dialog__close').first(), + oauthConnectButton: () => cy.getByTestId('oauth-connect-button'), + oauthConnectSuccessBanner: () => cy.getByTestId('oauth-connect-success-banner'), credentialsEditModal: () => cy.getByTestId('credential-edit-dialog'), credentialsAuthTypeSelector: () => cy.getByTestId('node-auth-type-selector'), credentialAuthTypeRadioButtons: () => @@ -69,6 +70,13 @@ export class CredentialsModal extends BasePage { this.getters.closeButton().click(); } }, + fillField: (fieldName: string, value: string) => { + this.getters + .credentialInputs() + .getByTestId(`parameter-input-${fieldName}`) + .find('input') + .type(value); + }, createNewCredential: (type: string, closeModal = true) => { this.getters.newCredentialModal().should('be.visible'); this.getters.newCredentialTypeSelect().should('be.visible'); diff --git a/packages/cli/templates/oauth-callback.handlebars b/packages/cli/templates/oauth-callback.handlebars index 44e1f72ccc..c0d8a0cfab 100644 --- a/packages/cli/templates/oauth-callback.handlebars +++ b/packages/cli/templates/oauth-callback.handlebars @@ -1,7 +1,8 @@ diff --git a/packages/cli/templates/oauth-error-callback.handlebars b/packages/cli/templates/oauth-error-callback.handlebars index 5c718ff398..5a6770162a 100644 --- a/packages/cli/templates/oauth-error-callback.handlebars +++ b/packages/cli/templates/oauth-error-callback.handlebars @@ -17,7 +17,10 @@ {{/if}} Failed to connect. The window can be closed now. \ No newline at end of file diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue index b1e5dfa07b..c679e02fb4 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue @@ -39,6 +39,7 @@ :button-label="$locale.baseText('credentialEdit.credentialConfig.reconnect')" :button-title="$locale.baseText('credentialEdit.credentialConfig.reconnectOAuth2Credential')" @click="$emit('oauth')" + data-test-id="oauth-connect-success-banner" >