cypress icon indicating copy to clipboard operation
cypress copied to clipboard

DOM elements not found in origin block

Open scharoltaGB opened this issue 1 year ago • 6 comments

Current behavior

I am using cy.origin() to login with an external login provider. My case is very similar to this block (taken from this issue)

it('client redirects to login page', () => {
  cy.visit('https://mydomain.com/page') // server responds with a 2xx status code and client redirects to anotherdomain.com/login

  cy.origin('https://anotherdomain.com', () => {
    // no visit is needed here since we've already been redirected
    // cy.visit('https://mydomain.com/page')

    // perform login steps
    cy.get('#login-button').click() // clicking login button redirects back to mydomain.com
  })

  cy.get('#user').should('contain', 'username')
})

However, the cy.get in the origin block (in this example cy.get('#login-button').click()) always fails to find the relevant DOM element. If I run this statement outside of the origin block, the element is found successfully but the test fails later as I need this origin.

Desired behavior

cy.get should also be able to find the relevant element in the cy.origin block.

Test code to reproduce

const innerLogin = (url: string, username: string, password: string) => {
    cy.visit(`/Account/LogOn?returnUrl=${encodeURIComponent(url)}`); //will redirect to the Auth0 login page
    const args = { username, password };
    cy.origin(
        "_[auth0 tenant url]_",
        { args },
        ({ username, password }): void => {
            cy.get("input[id=username]").click().type(username); //this element cannot be found if statement is run in origin block
            cy.get("button[type=submit]").click();
            cy.get("input[id=password]").click().type(password);
            cy.get("button[type=submit]").click();
        }
    );
};

Cypress Version

10.3.1, 10.4.0

Other

No response

scharoltaGB avatar Aug 03 '22 09:08 scharoltaGB

Hi @scharoltaGB. Thank you for opening an issue. This one might be tricky to reproduce on my end, but what I am thinking is there is a race condition where the cy.origin block is being executed before the redirect fully occurs. What happens if you put an explicit wait in the cy.origin block before performing the cy.get? This seems like it might be similar to #22282

AtofStryker avatar Aug 03 '22 20:08 AtofStryker

Hi @scharoltaGB. Thank you for opening an issue. This one might be tricky to reproduce on my end, but what I am thinking is there is a race condition where the cy.origin block is being executed before the redirect fully occurs. What happens if you put an explicit wait in the cy.origin block before performing the cy.get? This seems like it might be similar to #22282

Hi! Thanks for your reply. I tried adding an explicit wait but unfortunately it did not fix this issue for me. The issue you linked absolutely sounds like a similar problem. Do you know when a fix is planned for this?

scharoltaGB avatar Aug 04 '22 07:08 scharoltaGB

Hi! Thanks for your reply. I tried adding an explicit wait but unfortunately it did not fix this issue for me. The issue you linked absolutely sounds like a similar problem. Do you know when a fix is planned for this?

I don't believe we have an ETA on a fix, but it is a known issue that we need to solve with redirects happening while transitioning origins. Did this code ever work for you and we introduced a regression or did you implement this originally in 10.3.1 and it never worked?

AtofStryker avatar Aug 04 '22 16:08 AtofStryker

Hi again! We implemented this originally in 10.3.1 (also tested in 10.4.0 - just updated the ticket to indicate this) as we recently changed our login logic to use an external login provider which requires this.

scharoltaGB avatar Aug 08 '22 07:08 scharoltaGB

Hi again! We implemented this originally in 10.3.1 (also tested in 10.4.0 - just updated the ticket to indicate this) as we recently changed our login logic to use an external login provider which requires this.

@scharoltaGB OK I believe that makes sense. That would make the most sense since the issue should still exist in 10.3.1 and earlier.

AtofStryker avatar Aug 08 '22 14:08 AtofStryker

possibly related to #22282

AtofStryker avatar Aug 09 '22 18:08 AtofStryker

Possibly some additional information...

I was experiencing the same behavior on 10.4.0 trying to test an emulated Firebase Auth flow. It turns out it was fixed by ensuring the redirect happened after the origin command had executed.

I originally got to this code trying to identify issues:

it('login by entering an email and clicking Next', function() {
    cy.visit('/login');
    cy.get(`input[name="email"]`).type(email);
    cy.get(`button[type="submit"]`).click();
    cy.wait(5000);

    // Redirect to Firebase Auth emulator
    cy.origin('http://localhost:9099/', { args: { email } }, ({ email }) => {
      cy.wait(5000);

      // Errors with: Timed out retrying after 4000ms: expected '' to include '/emulator/auth/handler'
      cy.url().should('include', '/emulator/auth/handler');

      // If `cy.url()` above is commented out, then `#accounts-list` is never found
      cy.get('#accounts-list').contains(email).click();
    });
    cy.wait(5000);

    cy.url().should('include', '/plan');
  });

For this, the cy.url() could not detect the URL correctly, even though I could clearly see the URL in the test location bar and the wait was plenty long enough to load the full page. In the log, I saw "page load" and "new url" events before origin was logged.

Removing the cy.wait before the cy.origin appears to have solved the issue. I now see this order in the logs:

  • page-load
  • origin
  • new url

Note that the cy.wait before cy.origin was there because I needed it to successfully do a live Sign In with Twitter flow, probably because there are multiple redirects in that flow, so if I didn't wait, the code executed at the wrong origin.

One idea that might solve some of these issues is to have origin wait until the origin has been reached before executing any code within it (or for there to be an option to enable this behavior). That way, no waiting would be needed before origin and if multiple redirects occur, it won't matter how long those redirects take as long as they eventually make it to the origin URL.

fastfedora avatar Aug 10 '22 13:08 fastfedora

@fastfedora my guess to what was happening with your issue is that cy.origin must proceed immediately after a navigation in order to work properly. If a wait is between the navigation and the origin command, cypress never achieves what we call stability, and the origin block likely indefinitely hangs. We are having discussions on how to improve this to make it more flexible, but right now this is a limitation.

AtofStryker avatar Aug 10 '22 14:08 AtofStryker

@scharoltaGB I forgot to ask... for the redirect, is it a client side or server side redirect (301/302)? Also, is your baseUrl set?

AtofStryker avatar Aug 11 '22 20:08 AtofStryker

@scharoltaGB I forgot to ask... for the redirect, is it a client side or server side redirect (301/302)? Also, is your baseUrl set?

It's a 302 redirect and yes, baseUrl is set :)

scharoltaGB avatar Aug 15 '22 09:08 scharoltaGB

We confirmed that https://github.com/cypress-io/cypress/pull/23297 should fix https://github.com/cypress-io/cypress/issues/22282. We can't 💯 confirm since we do not have a concrete reproduction, but we feel confident that https://github.com/cypress-io/cypress/pull/23297 should resolve this issue.

AtofStryker avatar Aug 17 '22 15:08 AtofStryker

We confirmed that #23297 should fix #22282. We can't 💯 confirm since we do not have a concrete reproduction, but we feel confident that #23297 should resolve this issue.

Great news! We'll be happy to test once this has been released :)

scharoltaGB avatar Aug 18 '22 08:08 scharoltaGB