cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.71k stars 3.16k forks source link

Cypress can hang when pageLoadTimeout event fired when redirecting back to our app after logging in using Microsoft AAD #30238

Open blackgrouse opened 5 days ago

blackgrouse commented 5 days ago

Current behavior

Cypress can hang when a pageLoadTimeout event is received when redirecting back to our app after logging in using Microsoft AAD which is causing issues in our CI/CD environment (Azure DevOps (ADO) ubuntu-22.04).

Our app uses MS AAD to authenticate users and we are automating this using v13.8.1 cy.session() and cy.origin() commands with code based on this blog. I have had to tweak the code slightly as our login page is hosted by Microsoft.

Here is my version of the login code via the custom command cy.loginWithMicrosoftAccountAndSelectOrg(): ```js declare global { namespace Cypress { interface Chainable { loginWithMicrosoftAccountAndSelectOrg(options: { username: string; password: string; clickAadTile?: boolean; clickDontRemainSignedIn?: boolean; orgButtonText?: string; postLoginSelector?: string; sessionName?: string; visit?: { url: string; failOnStatusCode?: boolean }; }): Chainable; } } } const msLogin = (options: { username: string; password: string; clickAadTile?: boolean; clickDontRemainSignedIn?: boolean; orgButtonText?: string; postLoginSelector?: string; useCachedSession?: boolean; visit?: { url: string; failOnStatusCode?: boolean }; }) => { const sentArgs = { username: options.username, password: options.password, clickAadTile: options.clickAadTile, clickDontRemainSignedIn: options.clickDontRemainSignedIn }; const urlToVisit = options.visit?.url ? options.visit?.url : '/'; const failOnStatusCode = options.visit?.failOnStatusCode ? options.visit?.failOnStatusCode : false; cy.visit(urlToVisit, { failOnStatusCode: failOnStatusCode }); cy.origin(`${getAuthHostName()}..com`, () => { cy.contains('Microsoft').click(); }); // Enter credentials on MS login pages cy.origin( 'login.microsoftonline.com', { args: sentArgs }, ({ username, password, clickAadTile, clickDontRemainSignedIn }: { username: string; password: string; clickAadTile?: boolean; clickDontRemainSignedIn?: boolean; }) => { cy.get('input[type="email"]').should('be.visible').type(username); cy.get('input[type=submit]').should('be.visible').click(); if (clickAadTile) { cy.get('#aadTile').should('be.visible').click(); } cy.get('input[type="password"]').should('be.visible').type(password, { log: false }); cy.get('input[type=submit]').should('be.visible').click(); if (clickDontRemainSignedIn) { cy.get('input[value="No"]').should('be.visible').click(); } } ); if (options.orgButtonText) { const orgButtonText = options.orgButtonText; waitForElementToBeVisible({ selector: '[data-testid="selectTenantPage"]' }).then((elementVisible) => { if (elementVisible) { cy.contains(orgButtonText).click(); } else { cy.logTestProgress('Tenant selection screen not visible, continuing...'); } }); } options.postLoginSelector ? cy.get(options.postLoginSelector).should('be.visible') : cy.get('nav').should('be.visible'); }; Cypress.Commands.add('loginWithMicrosoftAccountAndSelectOrg', (options) => { if (Cypress._.isString(options.sessionName)) { cy.session( options.sessionName, () => { msLogin(options); }, { validate: () => { cy.wrap(localStorage.getItem('msal.idtoken'), { log: false }).should('exist'); }, cacheAcrossSpecs: true } ); } else { msLogin(options); } }); ```

The UI flow is:

  1. Click the 'Microsoft' button to login
  2. Enter creds on MS AAD pages when prompted
  3. Click the 'No' button to not remain signed in
  4. Redirect back to our app and retrieve data from AWS S3 to be displayed

Most of the time this works fine, but sometimes, after step 3, Cypress hangs and doesn't redirect to our app. On debugging, we are not receiving a load event so that Cypress fires a pageLoadTimeout event, which should cause the test to fail. Unfortunately it does not, Cypress hangs at this point and continues running infinitely until stopped - by the user locally, or by ADO after a predefined amount of time. In the latter case, this fails the build, which obviously impacts our delivery efficiency as we have to rerun any builds which have failed in this way.

The last line executed was:

cy.get('input[value="No"]').should('be.visible').click();

and then there is no more activity in the test runner.

I have been able to reproduce this on my Mac 14.6.1 and the latest version of Cypress. Here is a screenshot of the test runner when failing locally: CypressPageLoadTimeout

Desired behavior

The desired behaviour is that Cypress should not hang but should allow the test to fail as expected.

Test code to reproduce

I have not had time to provide a failing test, but provide example code

Cypress Version

13.8.1

Node version

20.16.0

Operating System

macOS 14.6.1 and ubuntu 20.04

Debug Logs

Happy to provide logs if you tell me which ones would be helpful.

Other

No response

DeepanMondal commented 5 days ago

Hi Team,

I came across this issue related to Cypress hanging during Microsoft AAD login in the CI/CD environment (Azure DevOps on Ubuntu 22.04), and I’d like to contribute to the resolution.

I have some suggestions to troubleshoot and resolve the problem:

Before I start working on this, could you guide me on how to contribute effectively to this project? Are there any specific coding guidelines or contribution practices I should be aware of?

I'm happy to share any further details or logs that might be useful.

Looking forward to your response!

Best regards,
Deepan Mondal

MikeMcC399 commented 3 days ago

@DeepanMondal

Before I start working on this, could you guide me on how to contribute effectively to this project? Are there any specific coding guidelines or contribution practices I should be aware of?

You should read the CONTRIBUTING document.

jennifer-shehane commented 2 days ago

@blackgrouse Does this code work in non-Chrome browsers? Like Electron or Firefox?

It reminds me of this issue, which we have a workaround for if that is the case.

blackgrouse commented 2 days ago

@jennifer-shehane Thanks for getting back to me.

Yes, I'm able to reproduce in Electron.

image