cypress
cypress copied to clipboard
DOM elements not found in origin block
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
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 @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 thecy.origin
block before performing thecy.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?
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?
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.
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.
possibly related to #22282
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 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.
@scharoltaGB I forgot to ask... for the redirect, is it a client side or server side redirect (301/302)? Also, is your baseUrl
set?
@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 :)
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.
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 :)