Learn Cross-Origin Testing in Cypress

Learn in detail about cross-origin testing in Cypress and how to run it effectively on BrowserStack.

Get Started free
Home Guide Cross-Origin Testing in Cypress

Cross-Origin Testing in Cypress

By Priyanka Bhat, Community Contributor -

Cypress is an advanced test automation tool, but it limits cross-origin testing. Cross-origin testing is when users test whether an app works correctly when resources (like scripts or APIs) are requested from a different domain, port, or protocol.

However, Cypress provides a workaround via the cy.origin function, allowing the user to perform the action in a different domain and then continue with the previous domain as required.

This guide explores Cypress’s cross-origin testing, use cases, and implementation.

What is Cross-Origin Testing (cy.origin) in Cypress

Cross-origin testing in Cypress typically refers to testing the functionalities in different domains. By default, Cypress enforces the same-origin policy, meaning it can only interact with resources from the same domain to prevent cross-site scripting (XSS) and other vulnerabilities.

The cy.origin() function allows the user to bypass this behavior and validate the scenarios that fall under different origins.

Cy.origin() Syntax

Cy.origin() has two types of syntax

cy.origin(url, callbackFn)

cy.origin(url, options, callbackFn)

URL: It is the URL that differs from the origin URL or URL on which you intend to perform operations.

Options: It’s an object that allows you to configure specific behaviors for the command, such as timeout and log

Callback Function: A function containing Cypress commands that can be executed in the context of the specified origin.

Example

   it('Example cross origin', () => {

        cy.visit("https://www.browserstack.com ");

        //do some operation

        cy.origin("https://percy.io/login", () => {

            //do something else

        })

    });

Use Cases of Cross-Origin Testing

Below are some of the real-life examples of why cross-origin testing is important

  • Login to the Application with SSO authentication: SSO authentication is widely used in many platforms; for example, if you navigate to the LinkedIn login page it allows you to log in using the Google or Apple authentication.
    In such scenarios, the web page navigates to the respective company domains to validate the credentials. Cy.origin() can help in validating such authentication.
  • Validate the Footer links: Most of the marketing pages contain footer links where their privacy policy, cookie policy, and product pages are listed.
    These footer links can redirect to different domains or subdomains. Cypress cross-origin testing can be used to validate such scenarios.
  • Payment System Integration Testing: Most companies rely on third-party payment systems for payment processing. When the user clicks on proceed to checkout, the page will be redirected to the payment gateway website to complete the transaction. The origin of the URL differs and by default Cypress blocks such scenarios. To overcome such challenges you need to use cy.origin() function.
  • OAuth Validation: Larger companies own multiple domains. However, they will have centralized authentication systems that may belong to different domains.
    As soon as you hit the login button, the page might redirect to the central login domain to enter the credentials, leading to a cross-origin scenario.
  • Third-Party Widgets: Third-party widgets and other third-party tools are often integrated into a website. By clicking a link, you might be redirected to the corresponding widget pages that are owned by the respective company (of a third-party widget or tool). This creates a scenario where the cy.origin function is needed.
  • Multi-Language Websites: If the website supports multiple regions and languages the website URL may change as you change the language. For example, xyz.com may redirect to xyz.in if you select Hindi, xyz.cn if you select Chinese, etc. This also points to a cross-origin scenario where you have to use cy.origin function.

When to Use cy.origin in Testing [With Examples]

Here are the instances when you will have to use cy.origin while testing your application

1. SSO/oAuth Authentication for your Application

Consider your application navigates to a different domain upon clicking the sign-in page. In such scenarios you can use the cy.origin

describe('Cross origin demo', () => {

    it('Login with github', () => {

        cy.visit("https://cloud.cypress.io/login");

        cy.get("button span").contains("Log in").first().click()

        cy.origin("https://github.com", () => {

            cy.get("#login_field").type("test")

            cy.get("#password").type("test123")

        })

    });

});

In the above example, the cy.visit() is used to navigate to the login page that is of a primary origin; upon clicking the Log in button, it navigates to the GitHub sign-in page, where github.com becomes the cross-origin. cy.origin(“https://github.com “) is used to ease the restriction.

2. Dynamic data in a Secondary Origin

The above test case may be specific to the user. In real-time, you may need to create a custom function that dynamically accepts the username and password.

describe('Dynamic Data Cross Origin', () => {

    const ssologin = (userName,password) => {

        const sentArgs = { username: userName, password: password }

        cy.origin("https://github.com/", { args: sentArgs }, ({ username, password }) => {

            cy.get("#login_field").type(username)

            cy.get("#password").type(password)

            cy.get("input[name='commit']").click()

        })

      }

      it('Dynamic data cross origin test', () => {

        cy.visit("https://cloud.cypress.io/login");

        cy.get("button span").contains("Log in").first().click()

        ssologin("bstack@browsertack.com","$3osod");

    });

});

In the above code, the helper function with the name ssologin() is created, which accepts the username and password. These parameters are saved in sentArgs variable and passed into cy.origin(). This helps to dynamically pass the username and password based on the use cases

3. Navigating to the Secondary Origin

There may be use cases where you need to explicitly navigate to the secondary origin using cy.visit(). In such cases, you must include the cy.visit() within the cy.origin(), as shown below.

describe('Example cross origin', () => {

    it('Example cross origin', () => {

        cy.visit("https://www.browserstack.com");

        cy.get('h1').should('have.text', 'App & Browser Testing Made Easy');

        cy.origin("https://percy.io/", () => {

            cy.visit("https://percy.io");

            cy.get('h1').first().should('have.text', 'Your all-in-one visual review platform');

        })

    });

});

In the above code, you can explicitly navigate to the secondary domain using the cy.visit(). First, you navigate to www.browserstack.com, which becomes the primary domain. To ease the cross-origin restriction for the secondary domain, the cy.origin (“https://percy.io/”) is used, after which you navigate to the Percy website.

Try BrowserStack for Free

Output

Using cy.origin to navigate to the secondary origin

4. Login to SSO using the Custom Command

Cypress allows the creation of a custom command to perform any operation. Rather than rewriting the same code each time you log in, you can simply add the custom command in the cypress/support/commands.js.

Cypress.Commands.add('githubLogin', (userName, password) => {

    const sentArgs = { username: userName, password: password }

    cy.visit("https://cloud.cypress.io/login");

    cy.get("button span").contains("Log in").first().click()

    cy.origin("https://github.com/", { args: sentArgs }, ({ username, password }) => {

        cy.get("#login_field").type(username)

        cy.get("#password").type(password)

        cy.get("input[name='commit']").click()

    })

})

In the above code, the custom command is being added in the command.js file. The custom command is named ‘githubLogin’, which accepts username and password as parameters to allow the dynamic login with different credentials.

The below code shows how you can use the custom commands in your test scripts:

describe('Example cross origin', () => {

    it('Example cross origin', () => {

      cy.githubLogin('test','testsook')

    });

});

Output

Using cy.origin to Login to SSO

5. Navigating to Multiple Secondary Origins in Succession

If you are navigating to multiple secondary origins, you need to use the cy.origin() multiple times

describe('Example cross origin', () => {

    it('Example cross origin', () => {

        cy.visit("https://www.browserstack.com");

        cy.get('h1').should('have.text', 'App & Browser Testing Made Easy');

        cy.origin('https://nightwatchjs.org/', () => {

            cy.visit('https://nightwatchjs.org/about/community/')

            cy.url().should('contain', 'about/community')

          })

          

          cy.origin('https://percy.io', () => {

            cy.visit('https://percy.io/features')

            cy.url().should('contain', 'features')

          })

    });

});

In the above example, multiple domains are navigated. It illustrates the usage of multiple cy.origin() as you navigate to multiple origins.

How to Run cy.origin in Cypress

Running the cy.origin tests in Cypress is the same as running any other test.

Consider an example where you have created one test in the

cypress-demo/e2e/crossorigin/crossorign.test.cy.js

Below is the example code.

describe('Example cross origin', () => {

    it('Example cross origin', () => {

        cy.visit("https://www.browserstack.com");

        cy.get('h1').should('have.text', 'App & Browser Testing Made Easy');

        cy.origin('https://nightwatchjs.org/', () => {

            cy.visit('https://nightwatchjs.org/about/community/')

            cy.url().should('contain', 'about/community')

          })

          

          cy.origin('https://percy.io', () => {

            cy.visit('https://percy.io/features')

            cy.url().should('contain', 'features')

          })

    });

});

The above test is located inside the cypress-demo/e2e/crossorigin folder, where cypress-demo is the project root folder. Once you have the test created, you have two options to execute the test.

Using UI

Cypress UI can be invoked using the command

npx cypress open

Once you hit the above command, you will be prompted with a welcome window. Then you can:

  1. Choose the “E2E Testing
  2. Then Click on the desired browser (Example: Chrome)
  3. Click on ” Start E2E Testing in Chrome
  4. Now, the test explorer window opens. Navigate to cypress-demo/e2e/crossorigin folder to execute the “crossorigin.test.cy.js

Running cy.origin in Cypress Using UI

Using CLI

Cypress CLI allows you to quickly execute the tests using the command line. Use the below command to execute Cypress tests

Syntax

npx cypress run --spec "path_to_spec_file"

Example

npx cypress run --spec "cypress/e2e/crossorigin/crossorigin.test.cy.js"

Running cy.origin in Cypress Using CLI

How to Run Cross-origin tests in Cypress using BrowserStack Automate

Though a developer-friendly framework, Cypress has its limitations. While one is the restriction concerning cross-origin testing, the other is the limitation of running parallel tests in local.

This is a challenge for companies as they need scalable environments to meet the fluctuating demand.

Tools like BrowserStack Automate can help in such scenarios by letting you easily execute tests on a cloud without code changes.

Moreover, it provides access to 3500+ real device-browser combinations to test across various real device, browser, and OS combinations.

Integrating Browserstack Automate is simple. Please follow our help documentation to quickly set up Cypress.

Talk to an Expert

Conclusion

Cypress restricts cross-origin testing by default for security reasons. However, there are many use cases where cross-origin testing is crucial. Cypress supports a workaround for cross-origin testing using the cy.origin() command where the user can navigate to different domains implicitly or explicitly to perform validation.

Like cross-origin, Cypress also restricts parallel execution and multi-browser parallel execution locally. BrowserStack integration helps to achieve this without any hassle. BrowserStack has a vast real device cloud of 3500+ devices and browsers, which accelerates and improves the accuracy of your tests by maximizing test coverage.

BrowserStack Automate Banner

Frequently Asked Questions

1. What is Cy root?

Cy.root is a command in Cypress that allows fetching the HTML document root. Given below is the command for cy.root

cy.root().should('have.prop', 'nodeName', 'HTML');

2. Why do use cy in Cypress?

Cy object is a foundational global object in Cypress. It is used to perform any actions including the browser interactions, and validations in Cypress. It can be used for fetching the elements, implicit assertions, performing browser simulation, etc.

Tags
Automation Testing Cypress

Featured Articles

How to run specific test in Cypress

Cypress Web Testing Framework: Getting Started

Automation Tests on Real Devices & Browsers

Seamlessly Run Automation Tests on 3500+ real Devices & Browsers