Cypress: window.location.replace not working - inserts `__` into url

Created on 18 Apr 2019  路  20Comments  路  Source: cypress-io/cypress

Current behavior:

Navigating within our application using location.replace("") in a chained promise handler throws a cross-origin error. In our actual application, we are waiting on a network request, then navigating using location.replace() in a then handler.

I've simplified the code to the most basic thing I can, and am able to reproduce by calling location.replace() in a simple setTimeout.

window.location.replace("") -- works

setTimeout(() =>{
  window.location.replace("");
});

-- gives the following error: SecurityError: Blocked a frame with origin "http://localhost:58236" from accessing a cross-origin frame.

Desired behavior:

I need to be able to call location.replace() in a chained promise handler.

Steps to reproduce: (app code and test code)

https://github.com/beckee/cypress-test-tiny

Versions

Cypress 3.2.0
Mac OSX
Chrome Version 73

bug

Most helpful comment

This fix is available starting in 4.6.0 as an experiment which you can access by setting this config option in your cypress.json or elsewhere:

{
    "experimentalSourceRewriting": true
}

The fix is experimental, so there may be some situations where the _/ rerouting is not fixed.

If you're still experiencing _/ rerouting while setting the experimentalSourceRewriting to true in 4.6.0 - open a new issue with a reproducible example + screenshots, etc - filling out our issue template.

All 20 comments

If you ever want to work on the window of your application under test, you'll want to use cy.window(), otherwise - you will be trying to access the actual Cypress Test Runner window.

Can you try:

describe('page', () => {
    it('works', () => {
    });

    it('location.replace', () => {
        cy.window().then((win) => {
            win.location.replace("");
        })
    })

    it('location.replace promise', () => {
        cy.window().then((win) => {
            setTimeout(() =>{
                win.location.replace("");
            });
        })
    })
})

Also - you'll want to visit an actual webpage before attempting to replace the window's location.

I may have simplified this too much then. It's actually my application making the call to window.location.replace. I'll try to update this test ... but the test would actually just click a button in my application. The code in my application behind that button press is what is calling either:

window.location.replace("")

or setTimeout(() => {window.location.replace("")})

Yeah, if you can, update the repo to reflect the application code + tests that reproduce this problem and we can reopen.

I added some very simple app code that gets closer to showing the problem.

In this most basic example, you can see that clicking Button 1 loads another site within the same site. Clicking Button 2 should do the same within a setTimeout.

If I run the uploaded app code on a simple local server, I will see the test pass, however the URL loaded is not correct. I expect to see identical behavior in clicking both buttons. This may help exhibit the problem enough. If not, I will need to elaborate on this example more next week. Thank you for looking again.

Thanks for providing a reproducible example. I can indeed reproduce this behavior, which should not be happening.

I can also see that the script renders correctly and is not modified by Cypress when rending within Cypress:

Screen Shot 2019-05-06 at 1 40 50 PM

But, when clicking the second button within Cypress, and when the location.replace is called within a setTimeout, the application attempts to navigate to the __/foo/index.html location instead of /foo/index.html as it should.

For anyone struggling with this in the meantime, a workaround is to reference the window object outside the timeout, and use that reference in the function called by the timeout, e.g:

let windowRef = window
setTimeout(() => {
  windowRef.location.replace('foo/bar.html')
})

I stumbled across this error today. i used history.replaceState as workaround

history.replaceState(null,'', 'foo/bar.html');

Workaround by change app code from

setTimeout(() => window.location.href = "#/some/route/1", 500)

to

setTimeout(() => window.location.hash = "#/some/route/1", 500)

_Originally posted by @njevdjo in https://github.com/cypress-io/cypress/issues/5731#issuecomment-555476018_

This is an issue for testing our EmberJS app with Cypress. Specifically affecting ember apps that use the hash routing strategy.

@jennifer-shehane Do you have any idea what package is responsible for this behavior? I'd like to work on a fix for it.

We believe this may be similar to (if not the same issue as) https://github.com/cypress-io/cypress/issues/3975 which is a really complex problem being sorted through in this PR. https://github.com/cypress-io/cypress/pull/5273

The code for this is done in cypress-io/cypress#5273, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

In what release and on what date can we expect this bugfix in cypress-io/cypress#5273?

Released in 4.6.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v4.6.0, please open a new issue.

This fix is available starting in 4.6.0 as an experiment which you can access by setting this config option in your cypress.json or elsewhere:

{
    "experimentalSourceRewriting": true
}

The fix is experimental, so there may be some situations where the _/ rerouting is not fixed.

If you're still experiencing _/ rerouting while setting the experimentalSourceRewriting to true in 4.6.0 - open a new issue with a reproducible example + screenshots, etc - filling out our issue template.

This fix is available starting in 4.6.0 as an experiment which you can access by setting this config option in your cypress.json or elsewhere:

{
  "experimentalSourceRewriting": true
}

The fix is experimental, so there may be some situations where the _/ rerouting is not fixed.

If you're still experiencing _/ rerouting while setting the experimentalSourceRewriting to true in 4.6.0 - open a new issue with a reproducible example + screenshots, etc - filling out our issue template.

@flotwig & @jennifer-shehane Thanks a lot, this fix indeed solves the issue with erroneous redirects (__/). However it slows down our tests significantly. A single page VISIT without experimentalSourceRewriting took 3 seconds. After enabling it, a singleVISIT takes 23 seconds. An unacceptable increase for our pipelines. HTTP requests to GET the page's resources seem to be significantly slower.

@laurentenhoor Can you open a new issue demonstrating this? This is definitely not the performance we're expecting and is something we'd like to improve upon. I'd also like to make sure we exclude any other changes from 4.6.0 as the cause.

@jennifer-shehane it has been filed here: https://github.com/cypress-io/cypress/issues/7565

If i add "experimentalSourceRewriting" : true in cypress.json my page is breaking not seeing expected elements on the page , the page i wanted to redirect without experimentalSourceRewriting in it . I am stuck i can't complete my test without fixing this issue . The page has iframes and those are broken . I am on Chrome

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jennifer-shehane picture jennifer-shehane  路  3Comments

zbigniewkalinowski picture zbigniewkalinowski  路  3Comments

tahayk picture tahayk  路  3Comments

carloscheddar picture carloscheddar  路  3Comments

jennifer-shehane picture jennifer-shehane  路  3Comments