Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

window.stop() at onBeforeLoad #6596

Closed
EtienneBruines opened this issue Feb 28, 2020 · 2 comments
Closed

window.stop() at onBeforeLoad #6596

EtienneBruines opened this issue Feb 28, 2020 · 2 comments

Comments

@EtienneBruines
Copy link

EtienneBruines commented Feb 28, 2020

It would be great if there were a way to cancel the navigation, to be able to stop loading the page at any point and still be able to continue testing.

Current behavior:

Cypress test fails / timeout when calling window.stop() within onBeforeLoad.

Desired behavior:

Cypress test succeeding

Test code to reproduce

TL;DR call window.stop() inside the onBeforeLoad callback.

Assume ./cypress/fixtures/demo.html is any page (including an empty html file).

window_stop_spec.js

describe('window.stop() on onBeforeLoad', () => {
  it('should visit() successfully', () => {
    cy.visit('./cypress/fixtures/demo.html', {
      /** @param {Window} win */
      onBeforeLoad: (win) => {
        // Let's assume we now have added our credentials into localStorage / indexedDB,
        // and we don't care about this page anymore and want to move on as soon as possible
        win.stop()

        // This "workaround" makes Cypress hang, because it messes with Cypress too much
        // Cypress.emit('window:load', win)

        // This "workaround" makes Cypress go crazy as well
        // const fakeOnLoadEvent = new Event('HTMLEvents')
        // fakeOnLoadEvent.initEvent('load', false, false)
        // win.dispatchEvent(fakeOnLoadEvent)

        // This "workaround" does not make any difference either
        // const loadedEvent = new Event('HTMLEvents')
        // loadedEvent.initEvent('DOMContentLoaded', true, true)
        // win.document.dispatchEvent(loadedEvent)

        // There is no way to call trigger on any object
        // `win.trigger('load')` does not exist
        // and `cy.window().trigger('load')` complains about Promise-usage

        // Calling any of the above within a `setTimeout()` does not yield results either
      }
    })
  })
})

Versions

Should be unrelated.

Cypress 4.0.2
Linux 64-bit
Browsers: all (Electron, Chrome, Firefox - on all versions)

Current workaround

Our current workaround is to actually load a blank page on which we load our localStorage and indexedDB, afterwards adding some "logged in" element to the page (win.document.body.innerText = 'logged-in') and waiting for that to appear after navigating to it (cy.visit('./blank.html').contains('logged-in')). Because it is an empty page, no resources are wasted trying to load anything else.

@jennifer-shehane
Copy link
Member

@EtienneBruines cy.visit() will not resolve until the load event fires on the page. Since you are essentially hitting the stop button in the browser - the page never finishes loading and will timeout the visit.

We've had a discussion about window.stop() internally - thinking this may be an elegant solution to stop XHR requests/clear some state, but you can't call this in the onbeforeload of the cy.visit() because your visit will never resolve.

You could potentially utilize window.stop() within a cy.window() call depending on what you want to do - since cy.window() resolves immediately.

cy.window((win) => {
  win.stop()
})

@EtienneBruines Can you explain a bit about what you are trying to achieve in the state of your application with the attempted workarounds? My guess it you're looking for this feature: #788

Closing though as this is not a bug in Cypress currently.

Also, check out our community chat, it can be helpful for debugging or answering questions on how to use Cypress.

@EtienneBruines
Copy link
Author

EtienneBruines commented Feb 28, 2020

@jennifer-shehane Our issue is that we need to set values in both window.localStorage as well as indexedDB. This we cannot do (1) without a page loaded, and (2) before the page actually loads*.

Right now, we are loading the login-page, setting the localStorage and indexedDB, and then navigating onto the page we actually want to test. But since this happens on beforeEach we want to minimize the time wasted here. Hence the cancelling of the page as soon as we've saved the credentials.

*To (2) there seemed to be some kind of race-conditions going on. The onBeforeLoad handler does not block, so we cannot reliably save the credentials before the page is being processed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants