Best Practices | Cypress Documentation (2024)

info

Real World Practices

The Cypress team maintains the

Real World App (RWA), a full stack exampleapplication that demonstrates best practices and scalable strategies withCypress in practical and realistic scenarios.

The RWA achieves full code-coverage withend-to-end testsacross multiple browsers anddevice sizes, but also includesvisual regression tests, API tests, unittests, and runs them all in anefficient CI pipeline.

The app is bundled with everything you need,just clone the repositoryand start testing.

Organizing Tests, Logging In, Controlling State

danger

Anti-Pattern: Sharing page objects,using your UI to log in, and not taking shortcuts.

tip

Best Practice: Test specs in isolation,programmatically log into your application, and take control of your application'sstate.

tip

We gave a "Best Practices" conference talk at AssertJS (February 2018). Thisvideo demonstrates how to approach breaking down your application and organizingyour tests.

AssertJS - Cypress Best Practices

We have severalLogging in recipesin our examples.

Selecting Elements

danger

Anti-Pattern: Using highly brittleselectors that are subject to change.

tip

Best Practice: Use data-* attributesto provide context to your selectors and isolate them from CSS or JS changes.

Every test you write will include selectors for elements. To save yourself a lotof headaches, you should write selectors that are resilient to changes.

Oftentimes we see users run into problems targeting their elements because:

  • Your application may use dynamic classes or ID's that change
  • Your selectors break from development changes to CSS styles or JS behavior

Luckily, it is possible to avoid both of these problems.

  1. Don't target elements based on CSS attributes such as: id, class, tag
  2. Don't target elements that may change their textContent
  3. Add data-* attributes to make it easier to target elements

How It Works

Given a button that we want to interact with:

<button
id="main"
class="btn btn-large"
name="submission"
role="button"
data-cy="submit"
>
Submit
</button>

Let's investigate how we could target it:

SelectorRecommendedNotes
cy.get('button').click() NeverWorst - too generic, no context.
cy.get('.btn.btn-large').click() NeverBad. Coupled to styling. Highly subject to change.
cy.get('#main').click() SparinglyBetter. But still coupled to styling or JS event listeners.
cy.get('[name="submission"]').click() SparinglyCoupled to the name attribute which has HTML semantics.
cy.contains('Submit').click() DependsMuch better. But still coupled to text content that may change.
cy.get('[data-cy="submit"]').click() AlwaysBest. Isolated from all changes.

Targeting the element above by tag, class or id is very volatile andhighly subject to change. You may swap out the element, you may refactor CSS andupdate ID's, or you may add or remove classes that affect the style of theelement.

Instead, adding the data-cy attribute to the element gives us a targetedselector that's only used for testing.

The data-cy attribute will not change from CSS style or JS behavioral changes,meaning it's not coupled to the behavior or styling of an element.

Additionally, it makes it clear to everyone that this element is used directlyby test code.

info

Did you know?

The Selector Playgroundautomatically follows these best practices.

When determining a unique selector, it will automatically prefer elements with:

  • data-cy
  • data-test
  • data-testid

Real World Example

The Real World App (RWA) uses two usefulcustom commands for selecting elements for testing:

  • getBySel yields elements with a data-test attribute that match aspecified selector.
  • getBySelLike yields elements with a data-test attribute that containsa specified selector.
// cypress/support/commands.ts

Cypress.Commands.add('getBySel', (selector, ...args) => {
return cy.get(`[data-test=${selector}]`, ...args)
})

Cypress.Commands.add('getBySelLike', (selector, ...args) => {
return cy.get(`[data-test*=${selector}]`, ...args)
})

Text Content

After reading the above rules you may be wondering:

If I should always use data attributes, then when should I usecy.contains()?

A rule of thumb is to ask yourself this:

If the content of the element changed would you want the test to fail?

  • If the answer is yes: then use cy.contains()
  • If the answer is no: then use a data attribute.

Example:

If we looked at the <html> of our button again...

<button id="main" class="btn btn-large" data-cy="submit">Submit</button>

The question is: how important is the Submit text content to your test? If thetext changed from Submit to Save - would you want the test to fail?

If the answer is yes because the word Submit is critical and should not bechanged - then use cy.contains() to target theelement. This way, if it is changed, the test will fail.

If the answer is no because the text could be changed - then usecy.get() with data attributes. Changing the text toSave would then not cause a test failure.

Cypress and Testing Library

Cypress loves the Testing Library project. We use Testing Library internally,and our philosophy aligns closely with Testing Library's ethos and approach towriting tests. We strongly endorse their best practices.

You can use theCypress Testing Librarypackage to use the familiar testing library methods (like findByRole,findByLabelText, etc...) to select elements in Cypress specs.

In particular, if you're looking for more resources to understand how werecommend you approach testing your components, look to: Cypress Component Testing.

Assigning Return Values

danger

Anti-Pattern: Trying to assignthe return value of Commands with const, let, or var.

tip

Best Practice: Use aliases and closuresto access and store what Commands yieldyou.

Many first time users look at Cypress code and think it runs synchronously.

We see new users commonly write code that looks like this:

// DONT DO THIS. IT DOES NOT WORK
// THE WAY YOU THINK IT DOES.
const a = cy.get('a')

cy.visit('https://example.cypress.io')

// nope, fails
a.first().click()

// Instead, do this.
cy.get('a').as('links')
cy.get('@links').first().click()

info

Did you know?

You rarely have to ever use const, let, or var in Cypress. If you're usingthem, you will want to do some refactoring.

If you are new to Cypress and wanting to better understand how Commands work -please read our Introduction to Cypress guide.

If you're familiar with Cypress commands already, but find yourself usingconst, let, or var then you're typically trying to do one of two things:

  • You're trying to store and compare values such as text, classes,attributes.
  • You're trying to share values between tests and hooks like before andbeforeEach.

For working with either of these patterns, please read ourVariables and Aliases guide.

Visiting External Sites

danger

Anti-Pattern: Trying to visitor interact with sites or servers you do not control.

tip

Best Practice: Only test websitesthat you control. Try to avoid visiting or requiring a 3rd party server. If you choose,you may use cy.request() to talk to 3rd party serversvia their APIs. If possible, cache results via cy.session()to avoid repeat visits.

One of the first things many of our users attempt to do is involve 3rd partyservers or services in their tests.

You may want to access 3rd party services in several situations:

  1. Testing log in when your app uses another provider via OAuth.
  2. Verifying your server updates a 3rd party server.
  3. Checking your email to see if your server sent a "forgot password" email.

If you choose, these situations can be tested withcy.visit() and cy.origin().However, you will only want to utilize these commands for resources in yourcontrol, either by controlling the domain or hosted instance. These use casesare common for:

  • Authentication as a service platforms, such as Auth0, Okta, Microsoft, AWSCognito, and others via username/password authentication. These domains andservice instances are usually owned and controlled by you or yourorganization.
  • CMS instances, such as a Contentful or Wordpress instance.
  • Other types of services under a domain in which you control.

Potential Challenges Authenticating with Social Platforms

Other services, such as social logins through popular media providers, are notrecommended. Testing social logins may work, especially if run locally. However,we consider this a bad practice and do not recommend it because:

  • It's incredibly time consuming and slows down your tests (unless usingcy.session()).
  • The 3rd party site may have changed or updated its content.
  • The 3rd party site may be having issues outside of your control.
  • The 3rd party site may detect you are testing via a script and block you.
  • The 3rd party site might have policies against automated login, leading tobanning of accounts.
  • The 3rd party site might detect you are a bot, and provide mechanisms such astwo-factor authentication, captchas, and other means to prevent automation.This is common with continuous integration platforms and general automation.
  • The 3rd party site may be running A/B campaigns.

Let's look at a few strategies for dealing with these situations.

When logging in

Many OAuth providers, especially social logins, run A/B experiments, which meansthat their login screen is dynamically changing. This makes automated testingdifficult.

Many OAuth providers also throttle the number of web requests you can make tothem. For instance, if you try to test Google, Google will automaticallydetect that you are not a human and instead of giving you an OAuth login screen,they will make you fill out a captcha.

Additionally, testing through an OAuth provider is mutable - you will first needa real user on their service and then modifying anything on that user mightaffect other tests downstream.

Here are solutions you may choose to use to alleviate these problems:

  1. Use another platform that you control to log in with username and passwordvia cy.origin(). This likely guarantees that youwill not run into the problems listed above, while still being able toautomate your login flow. You can reduce the amount of authenticationrequests by utilizing cy.session().
  2. Stub out the OAuth provider and bypass it using theirUI altogether if cy.origin() is not an option. Youcould trick your application into believing the OAuth provider has passed itstoken to your application.
  3. If you must get a real token and cy.origin() isnot an option, you can use cy.request() and usethe programmatic API that your OAuth provider provides. These APIs likelychange more infrequently and you avoid problems like throttling and A/Bcampaigns.
  4. Instead of having your test code bypass OAuth, you could also ask your serverfor help. Perhaps all an OAuth token does is generate a user in yourdatabase. Oftentimes OAuth is only useful initially and your serverestablishes its own session with the client. If that is the case, usecy.request() to get the session directly from yourserver and bypass the provider altogether ifcy.origin() is not an option.

info

Recipes

We have several examples of doing this in our logging in recipes.

3rd party servers

Sometimes actions that you take in your application may affect another 3rdparty application. These situations are not that common, but it is possible.Imagine your application integrates with GitHub and by using your applicationyou can change data inside of GitHub.

After running your test, instead of trying tocy.visit() GitHub, you can usecy.request() to programmatically interact withGitHub's APIs directly.

This avoids ever needing to touch the UI of another application.

Verifying sent emails

Typically, when going through scenarios like user registration or forgottenpasswords, your server schedules an email to be delivered.

  1. If your application is running locally and is sending the emails directlythrough an SMTP server, you can use a temporary local test SMTP serverrunning inside Cypress. Read the blog post"Testing HTML Emails using Cypress"for details.
  2. If your application is using a 3rd party email service, or you cannot stubthe SMTP requests, you can use a test email inbox with an API access. Readthe blog post"Full Testing of HTML Emails using SendGrid and Ethereal Accounts"for details.

Cypress can even load the received HTML email in its browser to verify theemail's functionality and visual style:

Best Practices | Cypress Documentation (1)

  1. In other cases, you should try using cy.request()command to query the endpoint on your server that tells you what email hasbeen queued or delivered. That would give you a programmatic way to knowwithout involving the UI. Your server would have to expose this endpoint.
  2. You could also use cy.request() to a 3rd party email recipient server thatexposes an API to read off emails. You will then need the properauthentication credentials, which your server could provide, or you could useenvironment variables. Some email services already provideCypress plugins to access emails.

Having Tests Rely On The State Of Previous Tests

danger

Anti-Pattern: Coupling multipletests together.

tip

Best Practice: Tests should alwaysbe able to be run independently from one another and still pass.

You only need to do one thing to know whether you've coupled your testsincorrectly, or if one test is relying on the state of a previous one.

Change it to it.onlyon the test and refresh the browser.

If this test can run by itself and pass - congratulations you have written agood test.

If this is not the case, then you should refactor and change your approach.

How to solve this:

  • Move repeated code in previous tests to before or beforeEach hooks.
  • Combine multiple tests into one larger test.

Let's imagine the following test that is filling out the form.

  • End-to-End Test
  • Component Test
// an example of what NOT TO DO
describe('my form', () => {
it('visits the form', () => {
cy.visit('/users/new')
})

it('requires first name', () => {
cy.get('[data-testid="first-name"]').type('Johnny')
})

it('requires last name', () => {
cy.get('[data-testid="last-name"]').type('Appleseed')
})

it('can submit a valid form', () => {
cy.get('form').submit()
})
})

What's wrong with the above tests? They are all coupled together!

If you were to change it toit.only on any of thelast three tests, they would fail. Each test requires the previous to run in aspecific order in order to pass.

Here's 2 ways we can fix this:

1. Combine into one test

  • End-to-End Test
  • Component Test
// a bit better
describe('my form', () => {
it('can submit a valid form', () => {
cy.visit('/users/new')

cy.log('filling out first name') // if you really need this
cy.get('[data-testid="first-name"]').type('Johnny')

cy.log('filling out last name') // if you really need this
cy.get('[data-testid="last-name"]').type('Appleseed')

cy.log('submitting form') // if you really need this
cy.get('form').submit()
})
})

Now we can put an .only on this test and it will run successfully irrespectiveof any other test. The ideal Cypress workflow is writing and iterating on asingle test at a time.

  • End-to-End Test
  • Component Test
describe('my form', () => {
beforeEach(() => {
cy.visit('/users/new')
cy.get('[data-testid="first-name"]').type('Johnny')
cy.get('[data-testid="last-name"]').type('Appleseed')
})

it('displays form validation', () => {
// clear out first name
cy.get('[data-testid="first-name"]').clear()
cy.get('form').submit()
cy.get('[data-testid="errors"]').should('contain', 'First name is required')
})

it('can submit a valid form', () => {
cy.get('form').submit()
})
})

This above example is ideal because now we are resetting the state between eachtest and ensuring nothing in previous tests leaks into subsequent ones.

We're also paving the way to make it less complicated to write multiple testsagainst the "default" state of the form. That way each test stays lean but eachcan be run independently and pass.

Creating "Tiny" Tests With A Single Assertion End-to-End Only

danger

Anti-Pattern: Acting like you'rewriting unit tests.

tip

Best Practice: Add multiple assertionsand don't worry about it

We've seen many users writing this kind of code:

describe('my form', () => {
beforeEach(() => {
cy.visit('/users/new')
cy.get('[data-testid="first-name"]').type('johnny')
})

it('has validation attr', () => {
cy.get('[data-testid="first-name"]').should(
'have.attr',
'data-validation',
'required'
)
})

it('has active class', () => {
cy.get('[data-testid="first-name"]').should('have.class', 'active')
})

it('has formatted first name', () => {
cy.get('[data-testid="first-name"]')
// capitalized first letter
.should('have.value', 'Johnny')
})
})

While technically this runs fine - this is really excessive, and not performant.

Why you do this pattern in component and unit tests:

  • When assertions failed you relied on the test's title to know what failed
  • You were told that adding multiple assertions was bad and accepted this astruth
  • There was no performance penalty splitting up multiple tests because they runreally fast

Why you shouldn't do this in end-to-end tests:

  • Writing integration tests is not the same as unit tests
  • You will always know (and can visually see) which assertion failed in a largetest
  • Cypress runs a series of async lifecycle events that reset state between tests
  • Resetting tests is much slower than adding more assertions

It is common for tests in Cypress to issue 30+ commands. Because nearly everycommand has an implicit assertion (and can therefore fail), even by limitingyour assertions you're not saving yourself anything because any single commandcould implicitly fail.

How you should rewrite those tests:

describe('my form', () => {
beforeEach(() => {
cy.visit('/users/new')
})

it('validates and formats first name', () => {
cy.get('[data-testid="first-name"]')
.type('johnny')
.should('have.attr', 'data-validation', 'required')
.and('have.class', 'active')
.and('have.value', 'Johnny')
})
})

Using after Or afterEach Hooks

danger

Anti-Pattern: Using afteror afterEach hooks to clean up state.

tip

Best Practice: Clean up state beforetests run.

We see many of our users adding code to an after or afterEach hook in orderto clean up the state generated by the current test(s).

We most often see test code that looks like this:

describe('logged in user', () => {
beforeEach(() => {
cy.login()
})

afterEach(() => {
cy.logout()
})

it('tests', ...)
it('more', ...)
it('things', ...)
})

Let's look at why this is not really necessary.

Dangling state is your friend

One of the best parts of Cypress is its emphasis on debuggability. Unlikeother testing tools - when your tests end - you are left with your workingapplication at the exact point where your test finished.

This is an excellent opportunity for you to use your application in thestate the tests finished! This enables you to write partial tests that driveyour application step by step, writing your test and application code at thesame time.

We have built Cypress to support this use case. In fact, Cypress does notclean up its own internal state when the test ends. We want you to havedangling state at the end of the test! Things like stubs,spies, even intercepts arenot removed at the end of the test. This means your application will behaveidentically while it is running Cypress commands or when you manually work withit after a test ends.

If you remove your application's state after each test, then you instantly losethe ability to use your application in this mode. Logging out at the end wouldalways leave you with the same login page at the end of the test. In order todebug your application or write a partial test, you would always be leftcommenting out your custom cy.logout() command.

It's all downside with no upside

For the moment, let's assume that for some reason your application desperatelyneeds that last bit of after or afterEach code to run. Let's assume thatif that code is not run - all is lost.

That is fine - but even if this is the case, it should not go in an after orafterEach hook. Why? So far we have been talking about logging out, but let'suse a different example. Let's use the pattern of needing to reset yourdatabase.

The idea goes like this:

After each test I want to ensure the database is reset back to 0 records sowhen the next test runs, it is run with a clean state.

With that in mind you write something like this:

afterEach(() => {
cy.resetDb()
})

Here is the problem: there is no guarantee that this code will run.

If, hypothetically, you have written this command because it has to runbefore the next test does, then the absolute worst place to put it is in anafter or afterEach hook.

Why? Because if you refresh Cypress in the middle of the test - you will havebuilt up partial state in the database, and your custom cy.resetDb() functionwill never get called.

If this state cleanup is truly required, then the next test will instantlyfail. Why? Because resetting the state never happened when you refreshedCypress.

State reset should go before each test

The simplest solution here is to move your reset code to before the testruns.

Code put in a before or beforeEach hook will always run prior to thetest - even if you refreshed Cypress in the middle of an existing one!

This is also a great opportunity to useroot level hooks in mocha.

A great place to put this configuration is in thesupportFile,since it is loaded before any test files are evaluated.

Hooks you add to the root will always run on all suites!

// cypress/support/e2e.js or cypress/support/component.js

beforeEach(() => {
// now this runs prior to every test
// across all files no matter what
cy.resetDb()
})

Is resetting the state necessary?

One final question you should ask yourself is - is resetting the state evennecessary? Remember, Cypress already automatically enforcestest isolationby clearing state before each test. Make sure you are not trying to clean upstate that is already cleaned up by Cypress automatically.

If the state you are trying to clean lives on the server - by all means, cleanthat state. You will need to run these types of routines! But if the state isrelated to your application currently under test - you likely do not even needto clear it.

The only times you ever need to clean up state, is if the operations thatone test runs affects another test downstream. In only those cases do you needstate cleanup.

Real World Example

The Real World App (RWA) resets and re-seedsits database via a custom Cypress task called db:seed ina beforeEach hook. This allows each test to start from a clean slate and adeterministic state. For example:

// cypress/tests/ui/auth.cy.ts

beforeEach(function () {
cy.task('db:seed')
// ...
})

The db:seed task is defined within thesetupNodeEvents function of theproject, and in this case sends a request to a dedicated back end API of the appto appropriately re-seed the database.

  • cypress.config.js
  • cypress.config.ts
const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
on('task', {
async 'db:seed'() {
// Send request to backend API to re-seed database with test data
const { data } = await axios.post(`${testDataApiEndpoint}/seed`)
return data
},
//...
})
},
},
})

The same practice above can be used for any type of database (PostgreSQL,MongoDB, etc.). In this example, a request is sent to a back end API, but youcould also interact directly with your database with direct queries, customlibraries, etc. If you already have non-JavaScript methods of handling orinteracting with your database, you can use cy.exec,instead of cy.task, to execute any system command orscript.

Unnecessary Waiting

danger

Anti-Pattern: Waiting for arbitrarytime periods using cy.wait(Number).

tip

Best Practice: Use route aliases orassertions to guard Cypress from proceeding until an explicit condition is met.

In Cypress, you almost never need to use cy.wait() for an arbitrary amount oftime. If you are finding yourself doing this, there is likely a much simplerway.

Let's imagine the following examples:

Unnecessary wait for cy.request()

Waiting here is unnecessary since the cy.request()command will not resolve until it receives a response from your server. Addingthe wait here only adds 5 seconds after thecy.request() has already resolved.

cy.request('http://localhost:8080/db/seed')
cy.wait(5000) // <--- this is unnecessary

Unnecessary wait for cy.visit() End-to-End Only

Waiting for this is unnecessary because the cy.visit()resolves once the page fires its load event. By that time all of your assetshave been loaded including javascript, stylesheets, and html.

cy.visit('http://localhost/8080')
cy.wait(5000) // <--- this is unnecessary

Unnecessary wait for cy.get()

Waiting for the cy.get() below is unnecessary becausecy.get() automatically retries until the table's tr hasa length of 2.

Whenever commands have an assertion they will not resolve until their associatedassertions pass. This enables you to describe the state of your applicationwithout having to worry about when it gets there.

cy.intercept('GET', '/users', [{ name: 'Maggy' }, { name: 'Joan' }])
cy.get('#fetch').click()
cy.wait(4000) // <--- this is unnecessary
cy.get('table tr').should('have.length', 2)

Alternatively a better solution to this problem is by waiting explicitly for analiased route.

cy.intercept('GET', '/users', [{ name: 'Maggy' }, { name: 'Joan' }]).as(
'getUsers'
)
cy.get('[data-testid="fetch-users"]').click()
cy.wait('@getUsers') // <--- wait explicitly for this route to finish
cy.get('table tr').should('have.length', 2)

Running Tests Intelligently

As your test suite grows and takes longer to run, you may find yourself hittingperformance bottlenecks on your CI system. We recommend integrating your sourcecontrol system with your test suite such that merges are blocked until all yourCypress tests have passed. The downside of this is that longer test executiontimes slow the velocity at which branches may be merged and features may beshipped. This issue is compounded further if you have dependent chains ofbranches waiting to be merged.

One solution to this problem is Smart Orchestration with Cypress Cloud.Using a combination ofparallelization,load balancing,Auto Cancellation, andSpec Prioritization,Smart Orchestration maximizes your available compute resources & minimizeswaste.

Web Servers

danger

Anti-Pattern: Trying to starta web server from within Cypress scripts with cy.exec() orcy.task().

tip

Best Practice: Start a web serverprior to running Cypress.

We do NOT recommend trying to start your back end web server from withinCypress.

Any command run by cy.exec() orcy.task() has to exit eventually. Otherwise, Cypress willnot continue running any other commands.

Trying to start a web server from cy.exec() orcy.task() causes all kinds of problems because:

  • You have to background the process
  • You lose access to it via terminal
  • You don't have access to its stdout or logs
  • Every time your tests run, you'd have to work out the complexity aroundstarting an already running web server.
  • You would likely encounter constant port conflicts

Why can't I shut down the process in an after hook?

Because there is no guarantee that code running in an after will always run.

While working in the Cypress Test Runner you can always restart / refresh whilein the middle of a test. When that happens, code in an after won't execute.

What should I do then?

Start your web server before running Cypress and kill it after it completes.

Are you trying to run in CI?

We haveexamples showing you how to start and stop your web server.

Setting a Global baseUrl

danger

Anti-Pattern: Using cy.visit()without setting a baseUrl.

tip

Best Practice: Set a baseUrl inyour Cypress configuration.

By adding a baseUrl in yourconfiguration Cypress will attempt to prefix the baseUrl any URL provided tocommands like cy.visit() andcy.request() that are not fully qualified domain name(FQDN) URLs.

This allows you to omit hard-coding fully qualified domain name (FQDN) URLs incommands. For example,

cy.visit('http://localhost:8080/index.html')

can be shortened to

cy.visit('index.html')

Not only does this create tests that can easily switch between domains, i.e.running a dev server on http://localhost:8080 vs a deployed production serverdomain, but adding a baseUrl can also save some time during the initialstartup of your Cypress tests.

When you start running your tests, Cypress does not know the url of the app youplan to test. So, Cypress initially opens on https://localhost + a randomport.

Without baseUrl set, Cypress loads main window in localhost + random port

Best Practices | Cypress Documentation (2)

As soon as it encounters a cy.visit(), Cypress thenswitches to the url of the main window to the url specified in your visit. Thiscan result in a 'flash' or 'reload' when your tests first start.

By setting the baseUrl, you can avoid this reload altogether. Cypress willload the main window in the baseUrl you specified as soon as your tests start.

Cypress configuration file

  • cypress.config.js
  • cypress.config.ts
const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:8484',
},
})

With baseUrl set, Cypress loads main window in baseUrl

Best Practices | Cypress Documentation (3)

Having a baseUrl set gives you the added bonus of seeing an error if yourserver is not running during cypress open at the specified baseUrl.

Best Practices | Cypress Documentation (4)

We also display an error if your server is not running at the specifiedbaseUrl during cypress run after several retries.

Best Practices | Cypress Documentation (5)

Usage of baseUrl in depth

This short video explains indepth how to use baseUrl correctly.

Best Practices | Cypress Documentation (2024)

FAQs

What is a cy task? ›

cy. task() provides an escape hatch for running arbitrary Node code, so you can take actions necessary for your tests outside of the scope of Cypress. This is great for: Seeding your test database. Storing state in Node that you want persisted between spec files.

What does a cy wrap do? ›

Whenever you're using a child command you likely want to use cy. wrap() on the subject. Wrapping it enables you to immediately use more Cypress commands on that subject.

What is a cy session? ›

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.

What is cy origin? ›

cy. origin() yields the value yielded by the last Cypress command in the callback function. If the callback contains no Cypress commands, cy. origin() yields the return value of the function. In either of the two cases above, if the value is not serializable, attempting to access the yielded value will throw an error.

What is the difference between CY task and command? ›

The key takeaways are: If you need to run a promise or interact with your backend, go with a task. Remember: Commands are not promises. If you are interacting with the DOM and making assertions, go with a command.

What is CY exec? ›

cy. exec() provides an escape hatch for running arbitrary system commands, so you can take actions necessary for your test outside the scope of Cypress. This is great for: Running build scripts. Seeding your test database.

What is a promise in Cypress? ›

On the same note, Promise is a state of the command in the case of Cypress async tests, and it will have the following states: Resolved: If the test phase is successful. Pending: If the test phase run result is being awaited. Rejected: If the test phase is unsuccessful.

What is cy in Cypress? ›

A new Cypress chain always starts with cy. [command] , where what is yielded by the command establishes what other commands can be called next (chained).

How to give a wait in Cypress? ›

You can pass an array of aliases that will be waited on before resolving. ​ When passing an array of aliases to cy. wait() , Cypress will wait for all requests to complete within the given requestTimeout and responseTimeout .

What are the 3 types of sessions? ›

Sessions of Parliament
  • Budget session (February to May)
  • Monsoon session (July to September)
  • Winter session (November to December)

What are the two types of session? ›

Binary versus Multiparty Session Types

Interaction between two processes can be checked using binary session types, while interactions between more than two processes can be checked using multiparty session types.

How to test login using Cypress? ›

Step-by-Step Guide: Setting Up Cypress & Testing Login
  1. Step 1: Create a new project. Create a new project folder first, then go there in your terminal. ...
  2. Step 2: Install Cypress. ...
  3. Step 3: Open Cypress. ...
  4. Step 4: Write a test. ...
  5. Step 5: Run the test.
May 18, 2023

How to handle redirection in Cypress? ›

In order to set the extra option for loading the page in the browser, you can use the options parameter. If the response code is not “2XX” or “3XX,” the failOnStatusCode: false wouldn't fail the test. To check if the URL was changed following the redirect, you can use cy. url() to get the current URL of the website.

Does Cypress support iframes? ›

Conclusion: In Cypress, dealing with iframes is very easy; the important thing is how much time we invest in research. The main point is to install the dependency and then include the required statement in the support file.

How to access window object in Cypress? ›

cy. window() yields the window object.

What is a Cypress axe? ›

With cypress-axe you can inject axe-core from Deque Systems into your page under tests in a Cypress test and use it to check the DOM for accessibility violations.

When to use custom commands in Cypress? ›

Unlike the default Cypress commands, these custom commands can be used for specific testing needs, allowing testers to streamline and optimize their automation flows. With the ability to add or overwrite existing commands, custom commands provide a flexible and powerful way to interact with web applications.

How to see console log in Cypress? ›

# Check console logs
  1. Check at the end of the test. We can spy on the console. ...
  2. Check each console. log call as it happens. ...
  3. Throw on console.error. If we want to simply throw an error and fail the test as soon as the application calls console.error method, we can use cy.stub(console, 'error').throw('Console error')
Sep 8, 2022

What is recurse in Cypress? ›

cypress-recurse

A way to re-run Cypress commands until a predicate function returns true.

Top Articles
Latest Posts
Article information

Author: Melvina Ondricka

Last Updated:

Views: 6481

Rating: 4.8 / 5 (68 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Melvina Ondricka

Birthday: 2000-12-23

Address: Suite 382 139 Shaniqua Locks, Paulaborough, UT 90498

Phone: +636383657021

Job: Dynamic Government Specialist

Hobby: Kite flying, Watching movies, Knitting, Model building, Reading, Wood carving, Paintball

Introduction: My name is Melvina Ondricka, I am a helpful, fancy, friendly, innocent, outstanding, courageous, thoughtful person who loves writing and wants to share my knowledge and understanding with you.