typescripttestingcypresse2ecypress-origin

Unable to get cypress new location/href after page load


I'm trying to execute this test on Cypress:

  1. get URL parameter/query with of the current page eg: localhost:3000/?redirect_link=X

  2. Click on skip button inside of the current page

  3. Redirects to another page (it's a page, not component so it's external/cross domain)

  4. Location should equal to X

But the assert on step 4 is failing, I want to test if new redirected page is equal to the same passed in query string param.

I'm doing:

  beforeEach(() => {
    cy.visit('/?redirect_link=X')
  })

  it('it skips and then redirects to another page', () => {
    cy.location().then((local) => {
      const arr = local.search.split('?')[1].split('&')
      const paramObj = {} as any
      arr.forEach((param) => {
        const [key, value] = param.split('=')
        if (key === 'redirect_link') {
          paramObj[key] = value
          cy.wrap(paramObj.redirect_link).as('redirect_link')
        }
      })
    })

    cy.get('[data-testid="button"]').click()

    cy.get('@redirect_link').then((redirect_link: string) => {
        cy.location('href').should('eq', '{PAGE X HERE}')
      })
    })

In cypress, this "should" is executing ealier than expected:

location
wrap redirect link
get button
click
location href
expected 'LOCALHOST' to equal PAGE X

If I put wait(10000) or timeout in location, after loading the PAGE X, it changes the value of LOCALHOST to null on location href stage while executing the wait, failing after the load: assert expected null to PAGE X

I also tried to use:

cy.url().then(() => )  // same return since it's same to cy location href
cy.on('window:load') // returns null when try to get the url
cy.on('url:changed) // returns null when try to get the url

Tried to put timeout in everything in the test, .then after the click but still not working.

Edit:

When I do:

cy.get('@redirect_link').then((redirect_link: string) => {
   cy.location('href').then((a) => console.log(a))
})
// it returns the current location href
wait(10000)
cy.get('@redirect_link').then((redirect_link: string) => {
   cy.location('href').then((a) => console.log(a))
})
// it returns null

Since it's cross domain, I also tried to put a event listener on window change, but it doesn't show PAGE X link in any field (path: null, target location null)

    cy.on('window:before:unload', (e) => {
      console.log(e)
    })
   // doesn't return any page X link

Solution

  • Since the redirect is to a cross-domain location, you will have to use cy.origin() wrapper to assert anything about the new domain. Waiting won't do enough.

    The problem then is that the new domain must be hard-coded, it can't be calculated from the old domain parameters as you try to do in the top of the test.

    For example, this works

    const redirect = 'http://example.com'
    
    it('it redirects to another page', () => {
    
      cy.visit(`/?redirect_link=${redirect}`)
    
      cy.get('[data-testid="button"]').click()
    
      // pass the expected url string in to the sandbox
      cy.origin(redirect, { args: {redirect} }, ({redirect}) => {
        cy.location()
          .should('eq', redirect)
      })
    })
    

    You can then test the location parameters separately, without doing the redirect, like this

    const redirect = 'http://example.com/'
    
    it('it has the redirect in the location parameter', () => {
    
      cy.visit(`/?redirect_link=${redirect}`)
    
      cy.location().then((local) => {
        const arr = local.search.split('?')[1].split('&')
        const paramObj = {} 
        arr.forEach((param) => {
          const [key, value] = param.split('=')
          if (key === 'redirect_link') {
            paramObj[key] = value
            cy.wrap(paramObj.redirect_link).as('redirect_link')
          }
        })
      })
    
      cy.get('@redirect_link')
        .should('eq', redirect)
    })