'Cypress: How to visit a url of a different origin?

I'm new to cypress and have ran into an issue. I have my base URL set to the domain I want to test, the issue is when I want to test the ability to login on my base url site I need to verify the user on another site, once I click apply on site number 2 the page on my base url reloads and I would then be able to test the rest of the site.

When I try to visit site 2 from my test I get an error

cy.visit() failed because you are attempting to visit a URL that is of a different origin.

The new URL is considered a different origin because the following parts of the URL are different:

superdomain

You may only cy.visit() same-origin URLs within a single test.

I read this https://docs.cypress.io/guides/guides/web-security.html#Set-chromeWebSecurity-to-false I've tried setting "chromeWebSecurity": false in cypress.json but I still get the same issue (I'm running in chrome)

Is there something I am missing?



Solution 1:[1]

As a temporary but solid work around, I was able to find this script in one of the Cypress Git issue threads (I don't remember where I found it so I can't link back to it)

Add the below to your cypress commands file

Cypress.Commands.add('forceVisit', url => {
    cy.window().then(win => {
        return win.open(url, '_self'); 
      });
});

and in your tests you can call

cy.forceVisit("www.google.com")

Solution 2:[2]

You can't!

But, maybe it will be possible soon. See Cypress ticket #944.

Meanwhile you can refer to my lighthearted comment in the same thread where I describe how I cope with the issue while Cypress devs are working on multi-domain support:

For everyone following this, I feel your pain! #944 (comment) really gives hope, so while we're patiently waiting, here's a workaround that I'm using to write multi-domain e2e cypress tests today. Yes, it is horrible, but I hope you will forgive me my sins. Here are the four easy steps:

  1. Given that you can only have one cy.visit() per it, write multiple its.
  2. Yes, your tests now depend on each other. Add cypress-fail-fast to make sure you don't even attempt to run other tests if something failed (your whole describe is a single test now, and it makes sense in this sick alternate reality).
  3. It is very likely that you will need to pass data between your its. Remember, we're already on this crazy “wrong” path, so nothing can stop us naughty people. Just use cy.writeFile() to save your state (whatever you might need), and use cy.readFile() to restore it at the beginning of your next it.
  4. Sue me.

All I care about at this point is that my system has tests. If cypress adds proper support for multiple domains, fantastic! I'll refactor my tests then. Until that happens, I'd have to live with horrible non-retriable tests. Better than not having proper e2e tests, right? Right?

Solution 3:[3]

You can stub the redirect from login site to base site, and assert the URL that was called.

Based on Cypress tips and tricks here is a custom command to do the stubbing.

The login page may be using one of several methods to redirect, so besides the replace(<new-url>) stub given in the tip I've added href = <new-url> and assign(<new-url>).

Stubbing command

Cypress.Commands.add('stubRedirect', () => {
  cy.once('window:before:load', (win) => {
    win.__location = {                           // set up the stub
      replace: cy.stub().as('replace'),
      assign: cy.stub().as('assign'),
      href: null,
    } 
    cy.stub(win.__location, 'href').set(cy.stub().as('href'))
  })

  cy.intercept('GET', '*.html', (req) => {   // catch the page as it loads
    req.continue(res => {
      res.body = res.body
      .replaceAll('window.location.replace', 'window.__location.replace')
      .replaceAll('window.location.assign', 'window.__location.assign')
      .replaceAll('window.location.href', 'window.__location.href')
    })
  }).as('index')
})

Test

it('checks that login page redirects to baseUrl', () => {

  cy.stubRedirect()
  cy.visit(<url-for-verifying-user>)   
  cy.wait('@index')                           // waiting for the window load

  cy.('button').contains('Apply').click()     // trigger the redirect 

  const alias = '@replace'  // or '@assign' or '@href'
                            // depending on the method used to redirect
                            // if you don't know which, try each one
  cy.get(alias)
    .should('have.been.calledOnceWith', <base-url-expected-in-redirect>)
})

Solution 4:[4]

You could set the window.location.href manually which triggers a page load, this works for me:

const url = 'http://localhost:8000';
cy.visit(url);

// second "visit"
cy.window().then(win => win.location.href = url);

You will also need to add "chromeWebSecurity": false to your cypress.json configuration.

Note: setting the window to navigate won't tell cypress to wait for the page load, you need to wait for the page to load yourself, or use timeout on get.

Solution 5:[5]

From version 9.6.0 of cypress, you can use cy.origin.

If you want to use it, you must first set the "experimentalSessionAndOrigin" record to true.

{
  "experimentalSessionAndOrigin": true
}

And here's how to use it.

cy.origin('www.example.com', () => {
    cy.visit('/')
})

cy.origin change the baseurl, so you can link to another external link via cy.visit('/').

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nikita Fedyashev
Solution 2 Aleks-Daniel Jakimenko-A.
Solution 3 Richard Matsen
Solution 4
Solution 5