Search code examples
javascriptcypresse2e-testinglit-element

Visit new url Cypress


I'm new to Cypress. My app as a "routing system" manually changes window.location.hash. At some point, I click on a button that changes the hash and consequently should change the page during the test. I can see a "new url" entry appearing during the execution, but how can I make cypress visit that url?

enter image description here

In few words, what the problem is: you can see I type the password and then {enter}. Running the test I can see the hash change in the address bar, but the page doesn't change in accord to the hash change.

This is the testing code

context("Workflow", () => {

    it("login", () => {

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demo").should("have.value", "demouser")
        cy.get("#password").type("demo{enter}").should("have.value", "demo") // this should redirect to "/#home"
        //cy.wait(10000)
        cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"
    })
})

EDIT: Following tons of failed attempts, I came up with a partially working, clunky and hacky solution. I think I shouldn't need to use reload() to solve that (there must be a better solution..), but to make it works I have to wait for all the remote requests to be done (otherwise reload() cancels them). I say partially working because you can see from the comments in the code if I try to visit #login first, then follow the redirect in #home and then change the page to #browser, the last one doesn't work (I can see the hash changing to #browser, but the page is still #home).

import 'cypress-wait-until';

let i = 0;

context("Workflow", () => {
    it("login", () => {
        cy.server( {
            onRequest: () => {
                i++;
            },
            onResponse: () => {
                i--;
            }
        });

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demouser").should("have.value", "demouser")
        cy.get("#password").type("demouser").should("have.value", "demouser")
        cy.get("form#formLogin").submit()

        cy.waitUntil(() => i > 0)
        cy.waitUntil(() => i === 0)
        cy.reload(); // it correctly change the hash AND the page to #home!

        cy.url().should("include", "#home") 
        cy.get(".version").contains( "v2.0.0-beta") // it works!!

        cy.get("a[data-id=browser]").click({force: true}) // it correctly changes the hash to #browser
        cy.waitUntil(() => i > 0)
        cy.waitUntil(() => i === 0)
        cy.reload();

        // the hash in the address bar is #browser, but the web page is #home
    })
})

Solution

  • Thanks for all the attempts to solve, but they were all tricky workarounds to something as simple as "trigger the related listener when window.location.hash changes".

    The root of the problem was a bug in Cypress. The bug on window.location.hash is present in 4.5.0, but it has been solved somewhere between 4.5.0 and 4.12.1.

    In 4.12.1 the problem is solved.