Your One-Stop Guide to cy.visit() in Cypress: Usage, Examples, and Best Practices

Cypress and visit Command Overview:

Cypress: A JavaScript-based end-to-end (E2E) testing framework for modern web applications. It facilitates creating and running automated tests that interact with the browser UI, ensuring the application behaves as expected.

cy.visit() Command: This crucial Cypress command serves as the entry point for your tests. It navigates the browser to a specified URL, loading the corresponding web page. This action lays the groundwork for subsequent interactions with the page's elements.

Optional Parameters:

  • timeout (Number): Sets the maximum wait time (in milliseconds) for the page to load. The default is 30000 (30 seconds).
  • onBeforeLoad (Function): Executes a callback function before the page finishes loading. Useful for setting up test data or environment configurations.
  • onLoad (Function): Executes a callback function after the page finishes loading. Typically used for assertions or initial interactions.

Example Code:

  • Reloading Window: Visiting a new domain or subdomain necessitates the Cypress window to reload. To test across different domains, use the cy.origin() command.
  • Automatic baseUrl Prefixing: If you've set a baseUrl configuration in Cypress, cy.visit() will automatically prepend it to the provided URL.

Potential Errors:

  • Timeout Error: If the page loading exceeds the specified timeout, Cypress throws a timeout error.
  • Network Errors: Connectivity or server issues can lead to network errors, preventing successful page loading.
  • JavaScript Errors: Issues within the website's JavaScript code might interfere with the Cypress test execution.

Error Handling:

  • Use cy.on('uncaught:exception', (err) => { ... }) to handle expected or unexpected JavaScript errors.
  • Implement retries with cy.reload() or cy.wait() in case of temporary network failures.

Best Practices:

  • Employ descriptive URLs for clarity and maintainability.
  • Set appropriate timeouts based on page loading expectations.
  • Handle errors gracefully to prevent test failures due to external factors.

By effectively incorporating the cy.visit() command and considering the provided best practices, you can streamline your Cypress test writing experience and ensure your web applications function correctly across different scenarios.

Visit a remote URL.

Best Practice We recommend setting a baseUrl when using cy.visit() . Read about best practices here.

Correct Usage

url (String)

The URL to visit.

Cypress will prefix the URL with the baseUrl configured in your global configuration if set.

If the baseUrl has not been set, you will need to specify a fully qualified URL or Cypress will attempt to act as your web server. See the prefixes notes for more details.

Note: visiting a new domain requires the Test Runner window to reload. You cannot visit different super domains in a single test.

options (Object)

Pass in an options object to control the behavior of cy.visit() .

By default, the cy.visit() commands' will use the pageLoadTimeout and baseUrl set globally in your configuration .

You can also set all cy.visit() commands' pageLoadTimeout and baseUrl globally in configuration .

  • cy.visit() 'yields the window object after the page finishes loading'

Let's confirm the window.navigator.language after visiting the site:

Visit a local server running on http://localhost:8000

cy.visit() resolves when the remote page fires its load event.

Change the default timeout

Overrides the pageLoadTimeout set globally in your configuration for this page load.

Add basic auth headers

Cypress will automatically apply the right authorization headers if you're attempting to visit an application that requires Basic Authentication .

Provide the username and password in the auth object. Then all subsequent requests matching the origin you're testing will have these attached at the network level.

You can also provide the username and password directly in the URL.

Cypress will automatically attach this header at the network proxy level, outside of the browser. Therefore you will not see this header in the Dev Tools.

Provide an onBeforeLoad callback function

onBeforeLoad is called as soon as possible, before your page has loaded all of its resources. Your scripts will not be ready at this point, but it's a great hook to potentially manipulate the page.

Check out our example recipes using cy.visit() 's onBeforeLoad option to: Bootstrapping your App Set a token to localStorage for login during Single Sign On Stub window.fetch

Provide an onLoad callback function

onLoad is called once your page has fired its load event. All of the scripts, stylesheets, html and other resources are guaranteed to be available at this point.

Add query parameters

You can provide query parameters as an object to cy.visit() by passing qs to options .

The parameters passed to qs will be merged into existing query parameters on the url .

Submit a form

To send a request that looks like a user submitting an HTML form, use a POST method with a body containing the form values:

Visit is automatically prefixed with baseUrl

Cypress will prefix the URL with the baseUrl if it has been set. We recommending configuring the baseUrl in the your configuration file ( cypress.json by default) to prevent repeating yourself in every cy.visit() command.

If you would like to visit a different host when the baseUrl has been set, provide the fully qualified URL you would like to go to.

Visit local files

Cypress will automatically attempt to serve your files if you don't provide a host and the baseUrl is not defined . The path should be relative to your project's root folder (where the cypress.json file is generated by default).

Having Cypress serve your files is useful in smaller projects and example apps, but isn't recommended for production apps. It is always better to run your own server and provide the URL to Cypress.

Visit local file when baseUrl is set

If you have baseUrl set, but need to visit a local file in a single test or a group of tests, set the baseUrl to null by using a test configuration . Given our cypress.json file:

The first test visits the baseUrl , while the second test visits the local file.

Visit will automatically follow redirects

Protocol can be omitted from common hosts.

Cypress automatically prepends the http:// protocol to common hosts. If you're not using one of these 3 hosts, then make sure to provide the protocol.

Visit will always yield the remote page's window object when it resolves

Trying to change the User-Agent ? You can set the userAgent as a configuration value in your configuration file.

Prevent requests before a remote page initially loads

One common scenario Cypress supports is visiting a remote page and also preventing any Ajax requests from immediately going out.

You may think this works:

But if your app makes a request upon being initialized, the above code will not work . cy.visit() will resolve once its load event fires. The cy.intercept() command is not processed until after cy.visit() resolves.

Many applications will have already begun routing, initialization, and requests by the time the cy.visit() in the above code resolves. Therefore creating a cy.intercept() route will happen too late, and Cypress will not process the requests.

Luckily Cypress supports this use case. Reverse the order of the commands:

Cypress will automatically apply the routes to the very next cy.visit() and does so immediately before any of your application code runs.

Requirements

  • cy.visit() requires being chained off of cy .
  • cy.visit() requires the response to be content-type: text/html .
  • cy.visit() requires the response code to be 2xx after following redirects.
  • cy.visit() requires the load load event to eventually fire.
  • cy.visit() will automatically wait for assertions you have chained to pass
  • cy.visit() can time out waiting for the page to fire its load event.
  • cy.visit() can time out waiting for assertions you've added to pass.

Command Log

Visit example application in a beforeEach

The commands above will display in the Command Log as:

When clicking on visit within the command log, the console outputs the following:

  • cy.reload()
  • cy.request()
  • Recipe: Bootstrapping your App
  • Recipe: Logging In - Single Sign on
  • Recipe: Stubbing window.fetch

© 2017 Cypress.io Licensed under the MIT License. https://docs.cypress.io/api/commands/visit

Cypress vs. Other Testing Frameworks: Why Cypress Should Be Your Choice

What it is: Cypress. $ is a custom jQuery-like syntax used within Cypress test scripts to interact with web elements. It provides a familiar and concise way to locate and manipulate elements in the DOM

  • Cypress 101: A Beginner's Guide to Automated Testing for JavaScript Apps
  • Cypress: A Comprehensive Guide for End-to-End Web Application Testing
  • Unlocking the Power of Cypress: JavaScript-Based Testing for Modern Web Apps

cy.visit doesn't work

Leveraging Cypress Fixtures: Enhance Code Reusability and Maintainability

cy.visit doesn't work

Leveraging Cypress Pause for Debugging and Manual Interaction in Web Testing

Cypress scrollintoview : your toolkit for effective element scrolling.

cy.visit doesn't work

Visit a remote URL.

Best Practice We recommend setting a baseUrl when using cy.visit() . Read about best practices here.

Correct Usage

url (String)

The URL to visit.

Cypress will prefix the URL with the baseUrl configured in your network options if you’ve set one.

You may also specify the relative path of an html file. The path is relative to the root directory of the Cypress installation. Note that the file:// prefix is not needed.

options (Object)

Pass in an options object to control the behavior of cy.visit() .

You can also set all cy.visit() commands’ pageLoadTimeout and baseUrl globally in configuration .

cy.visit() yields the window object after the page finishes loading.

Visit a local server running on http://localhost:8000

cy.visit() resolves when the remote page fires its load event.

Change the default timeout

Add basic auth headers.

Cypress will automatically apply the right authorization headers if you’re attempting to visit an application that requires Basic Authentication .

Provide the username and password in the auth object. Then all subsequent requests matching the origin you’re testing will have these attached at the network level.

You can also provide the username and password directly in the URL.

Cypress will automatically attach this header at the network proxy level, outside of the browser. Therefore you will not see this header in the Dev Tools.

Provide an onBeforeLoad callback function

onBeforeLoad is called as soon as possible, before your page has loaded all of its resources. Your scripts will not be ready at this point, but it’s a great hook to potentially manipulate the page.

Check out our example recipes using cy.visit() ‘s onBeforeLoad option to: Bootstraping your App Set a token to localStorage for login during Single Sign On Stub window.fetch

Provide an onLoad callback function

onLoad is called once your page has fired its load event. All of the scripts, stylesheets, html and other resources are guaranteed to be available at this point.

Add query paramaters

You can provide query parameters as an object to cy.visit() by passing qs to options .

The parameters passed to qs will be merged into existing query parameters on the url .

Submit a form

To send a request that looks like a user submitting an HTML form, use a POST method with a body containing the form values:

Visit will automatically follow redirects

Protocol can be omitted from common hosts.

Cypress automatically prepends the http:// protocol to common hosts. If you’re not using one of these 3 hosts, then make sure to provide the protocol.

Cypress can optionally act as your web server

Cypress will automatically attempt to serve your files if you don’t provide a host and baseUrl is not defined . The path should be relative to your project’s root folder (where the cypress.json file is generated by default).

Having Cypress serve your files is useful in smaller projects and example apps, but isn’t recommended for production apps. It is always better to run your own server and provide the url to Cypress.

Visit is automatically prefixed with baseUrl

Configure baseUrl in the your configuration file ( cypress.json by default) to prevent repeating yourself in every cy.visit() command.

Visit will always yield the remote page’s window object when it resolves

Trying to change the User-Agent ? You can set the userAgent as a configuration value in your configuration file.

Prevent XHR / Ajax requests before a remote page initially loads

One common scenario Cypress supports is visiting a remote page and also preventing any Ajax requests from immediately going out.

You may think this works:

But if your app makes a request upon being initialized, the above code will not work . cy.visit() will resolve once its load event fires. The cy.server() and cy.route() commands are not processed until after cy.visit() resolves.

Many applications will have already begun routing, initialization, and requests by the time the cy.visit() in the above code resolves. Therefore creating a cy.server() will happen too late, and Cypress will not process the requests.

Luckily Cypress supports this use case. Reverse the order of the commands:

Cypress will automatically apply the server and routes to the very next cy.visit() and does so immediately before any of your application code runs.

Requirements

cy.visit() requires being chained off of cy .

cy.visit() requires the response to be content-type: text/html .

cy.visit() requires the response code to be 2xx after following redirects.

cy.visit() requires the load load event to eventually fire.

cy.visit() will automatically wait for assertions you've chained to pass.

cy.visit() can time out waiting for the page to fire its load event.

cy.visit() can time out waiting for assertions you've added to pass.

Command Log

Visit example application in a beforeEach

The commands above will display in the Command Log as:

When clicking on visit within the command log, the console outputs the following:

  • cy.reload()
  • cy.request()
  • Recipe: Bootstrapping your App
  • Recipe: Logging In - Single Sign on
  • Recipe: Stubbing window.fetch

© 2020 Cypress.io Licensed under the MIT License. https://docs.cypress.io/api/commands/visit.html

Cache and restore cookies , localStorage , and sessionStorage (i.e. session data) in order to recreate a consistent browser context between tests.

The cy.session() command will inherit the testIsolation value to determine whether or not the page is cleared when caching and restoring the browser context.

Correct Usage

Incorrect Usage

Arguments ​

id (String, Array, Object)

A unique identifier that will be used to cache and restore a given session. In simple cases, a String value is sufficient. In order to simplify generation of more complex ids, if you pass an Array or Object , Cypress will generate an id for you by deterministically stringifying the value you pass in. For example, if you pass ['Jane', '123', 'admin'] , an id of ["Jane","123","admin"] will be generated for you.

See the choosing the correct id to cache a session section for a more thorough explanation with examples.

Note that large or cyclical data structures may be slow or difficult to serialize into an identifier, so exercise care with the data you specify.

setup (Function)

This function is called whenever a session for the given id hasn't yet been cached, or if it's no longer valid (see the validate option). After setup and validate runs for the first time, Cypress will preserve all cookies, sessionStorage , and localStorage , so that subsequent calls to cy.session() with the same id will bypass setup and just restore and validate the cached session data.

The page is cleared before setup when testIsolation is enabled and is not cleared when testIsolation is disabled.

Cookies, local storage and session storage in all domains are always cleared before setup runs, regardless of the testIsolation configuration.

options (Object)

  • cy.session() yields null .

Updating an existing login custom command ​

You can add session caching to your login custom command . Wrap the inside of the command with a call to cy.session() .

With session validation

Updating an existing login helper function ​

You can add session caching to a login helper function by wrapping the inside of the function with a call to cy.session() .

Switching sessions inside tests ​

Because cy.session() clears the page and all session data before running setup , you can use it to easily switch between sessions without first needing to log the previous user out. This allows tests to more accurately represent real-world scenarios and helps keep test run times short.

Validating the session ​

The validate function is used to ensure the session has been correctly established. This is especially helpful when a cached session is being restored, because if the session is not valid, cy.session() will recreate the session by re-running setup .

The following scenarios will mark the session as invalid:

  • the validate function throws an exception
  • the validate function returns a Promise that resolves to false or rejects
  • the validate function contains failing Cypress command
  • the last Cypress command in the validate function yielded false

Here are a few validate examples:

Modifying session data before caching ​

If you want to change which session data is cached, you can modify cookies, localStorage , sessionStorage as-necessary in setup .

Caching session data across specs ​

If you want to use the same session across multiple specs in the same Cypress run on the same machine, add cacheAcrossSpecs=true to the session options to leverage the session through the run.

Multiple login commands ​

A more complex app may require multiple login commands, which may require multiple uses of cy.session() . However, because the id value is used as a unique identifier to save and restore sessions, it's very important that it's actually unique per session.

In the following example, if the resulting session data that loginByForm and loginByApi create is different in any way , it would be a mistake to specify [name, password] as the id for both, because there would be no way to distinguish between the sessions created by loginByForm("user", "p4ssw0rd") and loginByApi("user", "p4ssw0rd") . Instead, you can modify the id to differentiate its value between both login functions, so that each will always be cached uniquely.

Where to call cy.visit() ​

Intuitively it seems that you should call cy.visit() immediately after cy.session() in your login function or custom command, so it behaves (from the point of view of the subsequent test) exactly the same as a login function without cy.session() .

However, if you want to test something on a different page, you will need to call cy.visit() at the beginning of that test, which means you will be calling cy.visit() a second time in your test. Since cy.visit() waits for the visited page to become active before continuing, this could add up to an unacceptable waste of time.

Tests will obviously be faster if you call cy.visit() only when necessary. This can be easily realised by organizing tests into suites and calling cy.visit() after logging in, inside a beforeEach hook.

Updating a login function that returns a value ​

If your custom login command returns a value that you use to assert in a test, wrapping it with cy.session() will break that test. However, it's usually easy to solve this by refactoring the login code to assert directly inside setup .

Cross-domain sessions ​

It's possible to switch domains while caching sessions, just be sure to explicitly visit the domain in your login command before calling cy.session() .

When the page and session data are cleared ​

Test isolation enabled ​.

The page is cleared and cookies, local storage and session storage (session data) in all domains are cleared automatically when cy.session() runs and test isolation is enabled with testIsolation=true (default in Cypress 12), This guarantees consistent behavior whether a session is being created or restored and allows you to switch sessions without first having to explicitly log out.

Note: cy.visit() must be explicitly called afterwards to ensure the page to test is loaded.

Test Isolation Disabled ​

When test isolation is disabled with testIsolation=false , the page will not clear, however, the session data will clear when cy.session() runs.

cy.visit() does not need to be called afterwards to ensure the page to test is loaded.

NOTE: Disabling test isolation may improve performance of end-to-end tests, however, previous tests could impact the browser state of the next test and cause inconsistency when using .only(). Be mindful to write isolated tests when test isolation is disabled.

When test isolation is disabled, it is encouraged to setup your session in a before hook or in the first test to ensure a clean setup.

Session caching ​

Once created, a session for a given id is cached for the duration of the spec file. You can't modify a stored session after it has been cached, but you can always create a new session with a different id .

In order to reduce development time, when running Cypress in "open" mode, sessions will be cached for spec file reruns .

To persist a session across multiple specs, use the option cacheAcrossSpecs=true .

Explicitly clearing sessions ​

When running Cypress in "open" mode, you can explicitly clear all spec and global sessions and re-run the spec file by clicking the "Clear All Sessions" button in the Instrument Panel .

Sessions Instrument Panel

For debugging purposes, all spec and global sessions can be cleared with the Cypress.session.clearAllSavedSessions() method.

Where to call cy.session() ​

While it is possible to call cy.session() explicitly inside a test or beforeEach , it is considered a best practice to call cy.session() inside a login custom command or reusable wrapper function. See the Updating an existing login custom command and Updating an existing login helper function examples for more details.

Choosing the correct id to cache a session ​

In order for sessions to be cached uniquely, the id argument must be unique for each new session created. The id provided to cy.session() will display in the reporter, thus we do not recommend using sensitive data like passwords or tokens as unique identifiers.

If you have custom login code that uses multiple parameters (in this example, a name, a token, and a password), in order to be able to log in many different users, but the id only included one of them (in this example, name ):

If you ran this, user1 would be logged in with token1 and p4ssw0rd , and a session would be created and cached using "user1" as the id .

Now let's say you wanted to try to log in the same user, but with a different token and/or password, and expect a different session to be created and cached. You run this, but because cy.session() is only being passed name as its id , it won't create a new session, but will instead load the saved session for "user1" .

In summary, you need to ensure that the id is unique. Create it from all the parameters used inside the setup function that may change, otherwise id values may collide and create unexpected results.

In this example, setting the id to [name, uniqueKey] guarantees that calling login() with different name , token and password values will create and cache unique sessions.

The uuid npm package can be used to generate random unique ids if an arbitrary name-space does not meet your needs.

Common Questions ​

Why are all my cypress commands failing after calling cy.session() ​.

When testIsolation is enabled, ensure that you're calling cy.visit() after calling cy.session() , otherwise your tests will be running on a blank page.

Why am I seeing 401 errors after calling cy.session() ? ​

It's possible that your session is not valid or was not fully established before the session was saved and the command ended. Be sure to specify a validate function so that cy.session() can validate and recreate the session if necessary.

Command Log ​

The instrument panel ​.

Whenever a session is created or restored inside a test, an extra instrument panel is displayed at the top of the test to give more information about the state of your sessions.

Clicking any session id in the panel will print that session's details to the console, and clicking the "Clear All Sessions" button will clear all saved spec and global sessions and re-run the spec file (see Session caching for more details).

The command log ​

Whenever cy.session() is called, the command log will show one of the following lines, which includes the status of the session call along with the session id value:

No saved session was found, so a new session was created and saved:

New session (collapsed)

A saved session was found, and used:

Saved session (collapsed)

A saved session was found, but the validate function failed, so the session was recreated and saved:

Recreated session (collapsed)

Note that in cases where the validate function fails immediately after setup creates the session, the test will fail with an error.

Expanding the session group in the command log will show all of the commands that were run when creating and/or validating the session.

In this image, a saved session is restored, but when /personal is visited in the validate function, the app redirects to /signin , which invalidates the session. A new session is created by visiting /signin where the user is logged in, after which, validation succeeds, and the session is available for the remainder of the test.

Recreated session (expanded)

Printing to the console ​

Clicking a session id in the Instrument Panel or clicking the first line under an expanded session group in the command log will print that session's details to the console. This information contains the id along with any cached session data, including cookies, localStorage and sessionStorage .

Session console output

  • Authenticate faster in tests with the cy.session command
  • Custom Commands
  • Cypress.session
  • Updating an existing login custom command
  • Updating an existing login helper function
  • Switching sessions inside tests
  • Validating the session
  • Modifying session data before caching
  • Caching session data across specs
  • Multiple login commands
  • Where to call cy.visit()
  • Updating a login function that returns a value
  • Cross-domain sessions
  • When the page and session data are cleared
  • Test Isolation Enabled
  • Test Isolation Disabled
  • Session caching
  • Explicitly clearing sessions
  • Where to call cy.session()
  • Choosing the correct id to cache a session
  • Common Questions
  • The Instrument Panel
  • The command log
  • Printing to the console

Better world by better software

Gleb bahmutov phd , our planet 🌏 is in danger, act today: what you can do, cypress cy.intercept problems, a few common cy.intercept gotchas and how to avoid them.

Note: I am using code from testing-workshop-cypress to demonstrate these cy.intercept gotchas.

📚 Since this post has been published in 2020, Cypress team has resolved many of these issues. To learn how to effectively spy and stub network requests in your Cypress tests, enroll in my online course Cypress Network Testing Exercises . The course covers a lot of topis in its main 30 lessons plus multiple bonus lessons.

The intercept was registered too late

Cy.wait uses the intercept, cached response, multiple matchers, no overwriting interceptors, avoid cypress commands inside the interceptor, sending different responses, no overwriting interceptors (again), single use intercept.

  • Get the number of times an intercept was matched

Count intercepts (again)

Set an alias dynamically, simulate network error, network idle.

  • Stub SSE resource
  • new 🌟 Disable network caching

The problem

Let's say the application is making GET /todos call to load its data. We might write a test like this to spy on this call:

It looks reasonable, it even shows the call in the Command Log - but does NOT pass.

You can see the XHR call in the command log - and it looks like it should work, right? But if you open the "Routes" section, notice that our intercept was never counted.

The root cause

The application is making the call to load the data right on startup :

Thus, it makes the call right at the end of cy.visit command. By the time cy.intercept runs, the call is already in progress , and thus not intercepted. Cypress shows XHR calls by default in its Command Log, thus it has nothing to do with our intercept. I always thought NOT showing when cy.intercept happens in the Command Log was a user experience failure.

The solution

Make sure the network intercept is registered before the application makes the call.

In our case, we need to register the intercept before visiting the page. Once the page is loaded, the application fetches the todo items, and everything is working as expected.

The intercept works correctly

The bonus solution

You can overwrite Cypress commands and log a message to the Command Log. Unfortunately overwriting cy.intercept has a bug with aliases #9580 , and thus we cannot always show when the intercept is registered. We can still do it case by case.

The above test clearly shows that the intercept is registered too late.

The log message shows the intercept is registered AFTER the application makes the call

Update: the alias bug #9580 has been fixed and released in Cypress v6.2.0

If you first wait on the intercept and then separately try to cy.get it to validate - well, the cy.get always resolves with null .

cy.get always yields null after cy.wait

This is different behavior from cy.route where we could wait on the interception, and the get it separately.

cy.wait plus cy.get works for cy.route

The workaround

Honestly, I feel this is a bug #9306 that we should fix shortly. But for now you can validate the interception immediately using the value yielded by cy.wait

You can validate the interception yielded by cy.wait

If you want to use multiple assertions over the interception, use the .should(cb) or .then(cb) assertions. The .then(cb) makes more sense here, since the interception value would never change after completing.

Update: the bug #9306 has been fixed and released in Cypress v6.2.0

Let's inspect the interception object yielded by the cy.wait command.

We cannot validate the data sent by the server, because there is no data in the response. Instead the server tells the browser that the data loaded previously is still valid and has not been modified. Hmm, but we are not the browser - the cy.intercept runs in the proxy outside the browser. Thus we have nothing to test.

We can check the caching by using the following test:

The response is cached

This is where it gets a little tricky - since this caching depends on the DevTools setting. If for example, you set the browser DevTools Network tab to disable caching you get the test that passes when the DevTools is closed, and fails when the DevTools is open.

The server will always return the actual data if the server cannot determine what the client has already. The server determines the data "cache key" in this case by looking at the if-none-match request header sent by the web application.

The request headers sent by the client

We need to delete this header on the outgoing request. Let's do it using our cy.intercept . Now we can extend the test to validate the response.

The client always receives fresh copy of the server data

The command cy.intercept can match requests using a substring, a minimatch, or a regular expression. By default, it intercepts requests matching any HTTP method. Thus when you define several intercepts, it is easy to get into the situation when multiple intercepts apply. In that case the first cy.wait(alias) "uses up" the intercept's response.

Consider the following test that adds a new todo.

We probably want to make sure the new todo sent to the server has the title "Write a test". Let's set up an intercept and validate the sent data.

If we inspect the value yielded by cy.wait('@post') it shows the object sent in the request

The new item sent to the server

Great, let's validate the new item. Since we do not control the random ID generation (of course we can control it, see the Cypress testing workshop how), we can just validate the title and completed properties.

Validating the item sent to the server

Great, everything works, what's the problem?

Imagine someone else comes along and changes the cy.visit and adds a wait for todo items to load - just like we did before. They do this to guarantee the application has loaded before adding new items.

So far so good. The test passes.

Notice a curious thing in the Command Log though - the XHR request to post the new item to the server has todos(2) badge.

The network request matches two intercepts

The POST /todos network call the application has made matches two intercepts, but the Command Log only prints the first intercept's alias.

In our test both intercepts only spied on the request. Now someone comes along and asks why do we need to reset the database before each test using resetDatabase utility method. It would be so simple to stub the initial GET /todos call and return an empty list of items.

The changed test is below - it simply uses cy.intercept('/todos', []).as('todos') .

The test fails.

The test now fails

If there are multiple matching interceptors, the first intercept that stubs the request stops any further processing. Thus our POST /todos network request gets intercepted by overly broad first * /todos intercept.

Use specific intercepts and make sure the stubs are not "breaking" any listeners defined afterwards. Change the first intercept to only work with GET /todos call.

The test using specific intercepts works

Update: I have opened issue #9588 to provide better labels to the intercepted requests.

Let's imagine the most common scenario - every test starts with zero items. We stab the GET /todos request and visit the site in a beforeEach hook.

Several tests that start with zero items using network stub

Now you want to confirm the application displays the initial list of todos correctly. Hmm, you would like to stub the initial GET /todos call in the new test:

Attempting to overwrite the intercept fails

Unfortunately the test fails. The first intercept cy.intercept('GET', '/todos', []) still executes, our the second intercept never has a chance.

We have a tracker issue #9302 to solve this problem somehow. It is complex - changing an intercept from stub to spy, or from spy to stub is tricky.

Separate the suites of tests to avoid using the beforeEach hook that sets up the unwanted intercept.

We have completely separated the suite of tests that should all start with zero items from the suite of tests that should start with two items. Now the intercepts never "compete". After all - this is just JavaScript and you can compose the test commands and the hooks in any way you want.

Separate suites of tests to avoid competing intercepts

You cannot use Cypress commands inside the interceptor callback, since it breaks the deterministic command chaining. The following test fails

Calling cy.writeFile inside the interceptor

The interceptor is triggered by the application's code, while other Cypress commands are already running. Cypress has no idea how to chain the cy.writeFile command - should it be after the currently running command? Or later? This leads to non-deterministic and unpredictable tests. Thus this is disallowed.

Instead save the body of the request in a variable, wait for the network call to happen, and then write the data to a file.

Watch the video below for details

Imagine we stub the loading items from the server. Initially the server returns two items. Then the user adds another item (we stub the POST request too), and when the page reloads, we should receive three items. How would we return different responses for the same GET /todos call? At first we could try to overwrite the intercept

But of course this does not work - because as I have shown in the previous section, you cannot overwrite an intercept (yet).

The first intercept still returns the two items

The first interceptor responds to both GET /todos calls. The cy.intercept('GET', '/todos', threeItems) intercept was never called, as I highlighted in the screenshot.

Use JavaScript code to return different responses from a single GET /todos intercept. For example, you can place all prepared responses into an array, and then use Array.prototype.shift to return and remove the first item.

The same intercept returning different responses

Let's get back to overwriting the interceptors again. We want to overwrite the GET /todos response from a particular test.

The last test "shows the initial todos" fails, because its intercept is never executed. See the previous section No overwriting interceptors for the details and a solution.

We cannot replace the intercept again, but we can extend the logic in setting the intercept to use JavaScript code to implement the overwrite. Let's create a new Cypress command cy.http that will stub the network call with a response, but that response will come from an object of intercepts. Any test that wants to return something else should just replace the value in that object.

Tip: I will store the object with intercepts in Cypress.config() object and will reset it before every test.

The main logic is inside the cy.intercept call

Notice the value is not hard-coded. Here is how we use cy.http from our tests

The tests work

Changing the response in the same intercept

Notice we still have to call the cy.http before the cy.visit , thus cy.visit cannot be placed in the beforeEach hook. Still, overwriting is very convenient for tests that expect different responses, like adding an item.

Tip: add a log message to our cy.http command for better experience.

Changing the response in the same intercept in the same test

This is similar to overwriting interceptors. Imagine you want to stub a network call once, but then allow other calls to go through to the server. Just intercepting with a static response would not work, as that intercept would work forever.

Here is the test that does not work.

Notice how the new item appears in the UI, we also see it being sent to the server using POST /todos call. Yet, the intercept "todos" again returns the empty list of todos on page reload.

We want to intercept only once. We do not need to even write a custom command , a simple function would do:

Let's see the test

Nice! And since the intercept continues spying on the requests, even if it does not stub them, we can get the last call and confirm other details.

Get number of times an intercept was matched

Sometimes you want to know / assert the number of times an intercept was matched. You can see this information in the "Routes" table in the Command Log, how can you confirm it from the test?

Note: for now, using cy.state('routes') is an implementation detail, and might change in the future, but you could do the following:

Asserting the number of times an intercept was used

We can count the number of times the intercept was called

If you are stubbing the network calls, use req.reply

There is an alternative approach to getting the number of times a network intercept was invoked - by using cy.spy . If we pass a created spy as route handler, it allows the network call to continue unchanged, yet we can get the count from that spy later

Here is an application that fetches a list of fruits every 30 seconds. We can use a synthetic clock to speed up the test, as described in Testing periodic network requests with cy.intercept and cy.clock combination blog post. We can count the number of times the spy was called.

The Command Log shows the result - there were 4 times the intercept was matched, and 4 times the spy was called.

Counting intercepts using spies

For stubbing, you can use the Sinon's callsFake method and invoke the req.reply from there

In case of GraphQL, all requests go through a single endpoint. Thus it is important for the intercept to inspect the request first, before deciding what to do. A convenient way to deal with such requests is to set the alias dynamically. For example, let's inspect all GET /users requests, and set an alias for the request that limits the number of users to 5:

The test runs, and an alias is created. The test can wait on that alias:

Waiting for dynamically created alias

Imagine you are trying to check how your application handles a network communication error. Internet is unreliable, servers go down and come back up all the time. You want to make sure your web application does not blow up. You might try stubbing network request with forceNetworkError: true response.

Hmm, a curious thing happens - you see multiple intercept messages in the Command Log!

Double intercept

Sometimes you see the intercept matched twice, some times even three times - but it was supposed to be a single Ajax call!

This is the browser trying to be robust and retrying a failed network request. The browser sees a network error coming back from the Cypress proxy and retries the same request 1-2 times before giving up.

I prefer replying with a specific HTTP network status code rather than forceNetworkError: true in most situations. Thus I test how the application handles 404 or 500 errors rather than a generic "Server is not responding" network error.

The browser will not retry such call, since technically the server has responded. It is up to the application to retry on 404 status code.

The deprecated cy.server had an option to block all non-stubbed routes, returning 404 status code instead. How do we recreate the same behavior using cy.intercept ? If we do cy.intercept('*', { statusCode: 404 }) we will break all network requests.

The original cy.server and cy.route only dealt with XMLHttpRequest objects, thus we could limit ourselves to recreating the same behavior of JSON Ajax requests. Assuming your application's code is well-behaved and sets the correct accept header, we can define the last stub to catch all Ajax calls.

If you really need some calls to go through, write the route matching logic yourself

With the full access to the request inside the route matcher function you can decide how to proceed.

To wait for multiple network requests to finish and for the network to be idle, try using the cypress-network-idle plugin. Watch the videos introduction to Cypress-network-idle plugin and Prepare Intercept And Wait Using cypress-network-idle Plugin .

Stub SSE Resource

If you want to stub a server-side events resource, you can respond to the request with a text body that simply lists the events. Unfortunately, the events are not going to be spaced in time, but it still works. See the Cypress Network Testing Exercises bonus lesson 22 for details.

Disable network caching

Cypress network interception happens outside the browser. But the browsers love to save bandwidth, so they cache the data internally. Often you see response headers like ETag: W/"960-cdSYN2pW398HtVmxLUpnD9XjLME" and request headers like If-None-Match: W/"960-cdSYN2pW398HtVmxLUpnD9XjLME" - these control the data caching. The server will look at the If-None-Match header value and respond with 304 Not Modified if the data hash is still the same as what the browser already has.

This creates problems during Cypress testing if you want to get the actual data, but the server sends an empty body with 304 response.

To stop the browser from sending request header If-None-Match you can:

  • in the interactive mode open DevTools and check "Disable cache" checkbox.

Disable network cache using browser DevTools

While the DevTools stay open, the browser will NOT use the cached data and will receive the full data from the server.

  • you can delete the request header If-None-Match inside the intcept

The request automatically continues to the server and without it, the server has no idea what data the browser has, thus it is forced to send the full response.

  • disable network cache using Chrome Debugger Protocol and built-in Cypress Automation

Tip: I wrote cypress-cdp plugin that makes the above commands much simpler

Cypress Network Testing Exercises Course

I show solutions to many problems shown in this blog post in my hands-on course Cypress Network Testing Exercises .

  • blog post Migrating .route() to .intercept() in Cypress
  • blog post Difference between cy.route and cy.route2
  • spying on requests
  • stubbing any request
  • changing the response from the server
  • intercepting static resources like HTML and CSS
  • redirecting requests
  • replying with different responses
  • blog post Smart GraphQL Stubbing in Cypress
  • cy.intercept documentation page
  • The blog post Testing loading spinner states with Cypress shows another way to control the network to assert the loading element.
  • see how to implement "wait for network idle", "how to test if the network call has not been made" in Cypress Tips and Tricks

A common mistake when using cy.session() (and how to fix it)

February 8, 2023

cy.visit doesn't work

This is a guest post from Ambassador Filip Hric! Hello, I’m Filip. I teach testers about web development and developers about testing. I have spoken at conferences around the world, created multiple online courses, and host live workshops on e2e testing in Cypress.io. Find everything I do at https://filiphric.com.

In Cypress v12, the cy.session() command was released as generally available. Many teams have already added it to their projects to save minutes from their test runs.

I recently wrote a blogpost on how cy.session() can be used instead of abstracting login logic into a page object. As community members on my Discord implement cy.session() into their projects, I often see one problem pop up repeatedly. Let me give you an example.

Consider this login flow:

By applying the cy.session() API, we can cache the cookies, localStorage and sessionStorage state of our browser for this login flow like this:

There is one small problem with this type of login. As soon as Cypress completes the cy.type() function, it caches our browser state. However, our frontend might still be working on the login flow and some of the authentication data we need has not been set.

Let’s say our application login will send an http request to the server to authenticate the user, and then redirect to a home page, before saving cookies into the browser.

Given the example above, our session will not get properly cached because we didn’t not explicitly tell cy.session() authentication flow is still in progress. The easiest way we can fix that is to add a guarding assertion to our session.

This way we will ensure that Cypress will cache our browser at the right moment. Depending on our application, this might be right after we navigate to a new page or some time later. The exact point will be determined by the application we are testing.

Usually, when making a login action, a server responds with an authorization in the form of a token that gets saved as cookies or some other browser storage. Instead of checking for the location, we can check that storage item. The session might then look something like this:

There is a slight problem with this approach though. The cy.getCookie() command will execute immediately and will not retry. Instead of using cy.getCookie() command we will choose a slightly different approach.

This way we can ensure that we wait the proper time for the application to store our cookies in the browser. After our cookies are saved, we can safely cache our session and use it in our tests.

The validation of a successful login is important for the cy.session() command to work properly. In fact, when using cy.session() you can add the validation as a separate step. This is what the validate() function is for. Let’s see it in action:

In this simple example, cy.session() will work pretty much the same way as before. But there is one upside to this approach. Our validate() function can do more than check the mere presence of the token. Instead, we could check for the validity of the token and make sure it does not expire during, e.g., a longer test run. The validate function can look something like this:

If the cy.request() returns an error code, it will mean that our authorization is no longer valid and we need to log in again. The validate() function will take care of this, and re-run our login flow.

This way we still keep login attempts to minimum, while making sure that the authorization does not expire during the test run.

Remember to always ensure that your cy.session() flow contains a “confirming assertion” that will guard the creation of the session to proper time.

About the Ambassador Program

The Cypress Ambassador program supports the top Cypress advocates around the world. Through this program, Ambassadors are offered speaking opportunities, a personalized hub, and visibility within our extensive network.To learn more about these wonderful ambassadors visit our Official Ambassador webpage.

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications

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

Cy.visit does not work on this certain websites and I dunno why #26454

@justme6666

justme6666 commented Apr 7, 2023

@nagash77

nagash77 commented Apr 10, 2023

Sorry, something went wrong.

@nagash77

No branches or pull requests

@nagash77

IMAGES

  1. cy.visit() page with baseUrl and two dots doesn't work · Issue #5090

    cy.visit doesn't work

  2. cy.visit a page with a dash doesn't work · Issue #3554 · cypress-io

    cy.visit doesn't work

  3. 单步调试找到 cy.visit 的实现源代码(一)

    cy.visit doesn't work

  4. cy.visit('url', {headers: {}}) doesnt work per documentation · Issue

    cy.visit doesn't work

  5. Visit The Blank Page Between Cypress Tests

    cy.visit doesn't work

  6. 单步调试找到 cy.visit 的实现源代码(一)

    cy.visit doesn't work

VIDEO

  1. it doesn’t work 😂

  2. It didn't work out too well, did it

  3. How to check which CYPRESS version installed in your project

  4. How to Practice Positive Mindset / and Survive a Bad Day When It Doesn’t Work / Over 60

  5. Cypress End to End Testing

  6. Using cy.viewport to Test Responsive Designs in Cypress

COMMENTS

  1. visit

    But if your app makes a request upon being initialized, the above code will not work.cy.visit() will resolve once its load event fires. The cy.intercept() command is not processed until after cy.visit() resolves. Many applications will have already begun routing, initialization, and requests by the time the cy.visit() in the above code resolves. Therefore creating a cy.intercept() route will ...

  2. Cypress

    My webserver was available, I have not had any weird configurations and I was simply trying to visit a page in my cypress tests. When I looked into the details of the error, I saw the following: From Node.js Internals: Error: connect ECONNREFUSED 127.0.0.1:4200 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16)

  3. Cy.visit() fails to load data from any web address, local or otherwise

    I did find a solution. As it turns out, cy.visit() does not work in my app's current test suite configuration. Our command runs yarn run test:unit:cy which opens cypress in unit testing mode?. To sidestep this, I set up a new make command to run yarn run cypress open, where none of the unit test will run apparently, but cy.visit() runs quite happily. ...

  4. Cy.visit() does not load page · Issue #3941 · cypress-io/cypress

    No milestone. Development. No branches or pull requests. 7 participants. Current behavior: Upon running cy.visity () and inputing a URL, the request times out. Desired behavior: Trying to run a simple cy.visit () command but unable to Page does not load and hangs until it times out.

  5. Cypress stuck at cy.visit() · Issue #27501

    @MikeMcC399 I tried above work-around https: ... .6.3 to 13.0.0 (the last one I tried) everything worked fine, with no more problems on the second test, and during the cy.visit() of the second test it looked like fewer assets were being fetched. I don't know what the actual problem is but for now, I'm going to stick with version 13.6.3.

  6. Cy.visit() Failed Trying to Upload: Causes and Remedies

    Simulate different network conditions using Cypress commands like cy.route() if necessary. Page Load Timeout: If the page takes a while to load, consider increasing the timeout for cy.visit(). You can do this in your Cypress configuration or the test using cy.visit(url, { timeout: 10000 }), where 10000 is the timeout in milliseconds.

  7. Cypress Error: "cy.visit () failed because you are attempting to visit

    Use cy.visit() to Reset: If you need to switch back to the original domain after visiting a different one, make sure to use cy.visit() ... This is partly why Cypress doesn't often top the charts as a contemporary automation tool among newer web frameworks. On the other hand, modern tools, such as testRigor, leverage AI-driven techniques to ...

  8. Your One-Stop Guide to cy.visit () in Cypress: Usage, Examples, and

    Cypress: A JavaScript-based end-to-end (E2E) testing framework for modern web applications. It facilitates creating and running automated tests that interact with the browser UI, ensuring the application behaves as expected. cy.visit () Command: This crucial Cypress command serves as the entry point for your tests.

  9. cy.visit('url', {headers: {}}) doesnt work per documentation #4216

    We also send cookies that the browser would normally send. Headers like Accept, Connection, Host, and User-Agent are normally sent with the browser request, so we also send them with the cy.visit(), because cy.visit() is intended to be used to test visiting a web page. I just tried your original example with the headers you shared:

  10. cypress

    All Tests are working fine. I just found that this URL actually getting failed to load by calling cy.visit('xxx') in gitlab ci/cd job. But the same URL is working fine with my local machine cypress run.

  11. Visit

    cy.visit() requires the load load event to eventually fire. Assertions cy.visit() will automatically wait for assertions you've chained to pass. Timeouts cy.visit() can time out waiting for the page to fire its load event. cy.visit() can time out waiting for assertions you've added to pass. Command Log Visit example application in a beforeEach

  12. session

    Because cy.session() clears the page and all session data before running setup, you can use it to easily switch between sessions without first needing to log the previous user out. This allows tests to more accurately represent real-world scenarios and helps keep test run times short. const login = (name) => {.

  13. cy.visit is not working while navigating from

    @chrisbreiding apologies for insisting too much on this. I really don't have any choice here. The latest issue which I am facing connected to this, I have chromeWebSecurity: false, on my cypress.config file and it is working fine in the OPEN mode. However, when I execute the test in RUN mode on chrome browser, I am unable to bi-pass the security. Is this expected?

  14. Page occasionally does not load from cy.visit ()

    Ask questions, find answers and collaborate at work with Stack Overflow for Teams. Explore Teams. Collectives™ on Stack Overflow. Find centralized, trusted content and collaborate around the technologies you use most. ... After a few it block, cy.visit() stop attempting to load the url and the test fails due to assertions regarding page ...

  15. Cypress cy.intercept Problems

    Multiple matchers The problem. The command cy.intercept can match requests using a substring, a minimatch, or a regular expression. By default, it intercepts requests matching any HTTP method. Thus when you define several intercepts, it is easy to get into the situation when multiple intercepts apply. In that case the first cy.wait(alias) "uses up" the intercept's response.

  16. cy visit fails to load · Issue #21504 · cypress-io/cypress · GitHub

    Current behavior. cy visit fails to load . the same is working some times without changing anything. We attempted to make an http request to this URL but the request failed without a response. > Error: socket hang up. - you don't have internet access. - you forgot to run / boot your web server.

  17. A common mistake when using cy.session() (and how to fix it)

    In Cypress v12, the cy.session() command was released as generally available. Many teams have already added it to their projects to save minutes from their test runs. I recently wrote a blogpost on how cy.session() can be used instead of abstracting login logic into a page object. As community members on my Discord implement cy.session() into their projects, I often see one problem pop up ...

  18. cy.visit () doesn't work for pages of my baseUrl domain

    Teams. Q&A for work. Connect and share knowledge within a single location that is structured and easy to search. Learn more about Teams

  19. Cy.visit does not work on this certain websites and I dunno why

    Your help would be greatly appreciated, if you ever manage to use cy.visit to work on this website, please tell me how... I tried the standard cy.visit command and unline other websites this one doesn't load... Thank you. Desired behavior. In this situation cy.visit should load the specified page.... Test code to reproduce

  20. in cypress, intercept in test doesn't work

    The intercept must always be set up before the trigger (page visit or button click). But the intercept varies between tests, so instead of before() I would try setting up a helper function that is called at the top of each test. const loadAndIntercept = (apiResult) => {.