End-to-End Testing: Your First Test with Cypress | Cypress Documentation (2024)

info

What you'll learn

  • How to start testing a new project in Cypress.
  • What passing and failing tests look like.
  • Testing web navigation, DOM querying, and writing assertions.

Add a test file

Assuming you've successfullyinstalled Cypress andopened Cypress, now it's time to addyour first test. We're going to do this with the Create new emptyspec button.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (1)

On clicking it, you should see a dialog where you can enter the name of your newspec. Just accept the default name for now.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (2)

The newly-generated spec is displayed in a confirmation dialog. Just go aheadand close it with the ✕ button.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (3)

Once we've created that file, you should see it immediately displayed in thelist of end-to-end specs. Cypress monitors your spec files for any changes andautomatically displays any changes.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (4)

Even though we haven't written any code yet - that's okay - let's click on yournew spec and watch Cypress launch it. Spoiler alert: it's probably going toFAIL. Don't worry, it's just because you haven't set up Cypress to visit apage in your app yet! Let's try something different.

Write your first test

Now it's time to write your first test. We're going to:

  1. Write your first passing test.
  2. Update it so it fails.
  3. Watch Cypress reload in real time.

Open up your favorite IDE and replace the contents of your spec with the codebelow.

describe('My First Test', () => {
it('Does not do much!', () => {
expect(true).to.equal(true)
})
})

Once you save this change you should see the browser reload.

Although it doesn't do anything useful, this is our first passing test! ✅

Over in the Command Log you'llsee Cypress display the suite, the test and your first assertion (which shouldbe passing in green).

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (5)

info

Notice Cypress displays a message about this being the default pageon the righthand side.Cypress assumes you'll want to go out and visit a URL onthe internet - but it can also work just fine without that.

Now let's write our first failing test.

describe('My First Test', () => {
it('Does not do much!', () => {
expect(true).to.equal(false)
})
})

Once you save again, you'll see Cypress display the failing test in red sincetrue does not equal false.

Cypress also displays the stack trace and the code frame where the assertionfailed (when available). You can click on the blue file link to open the filewhere the error occurred inyour preferred file opener.To read more about the error's display, read aboutDebugging Errors.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (6)

Cypress gives you a visual structure ofsuites, tests, and assertions. Soon you'll also see commands, page events,network requests, and more.

info

What are describe, it, and expect ?

All of these functions come fromBundled Libraries that Cypress bakes in.

  • describe and it come from Mocha
  • expect comes from Chai

Cypress builds on these popular tools and frameworks that you hopefullyalready have some familiarity and knowledge of. If not, that's okay too.

tip

Using ESlint?

Check out ourCypress ESLint plugin.

Write a real test

A solid test generally covers 3 phases:

  1. Set up the application state.
  2. Take an action.
  3. Make an assertion about the resulting application state.

You might also see this phrased as "Given, When, Then", or "Arrange, Act,Assert". But the idea is: First you put the application into a specific state,then you take some action in the application that causes it to change, andfinally you check the resulting application state.

Today, we'll take a narrow view of these steps and map them cleanly to Cypresscommands:

  1. Visit a web page.
  2. Query for an element.
  3. Interact with that element.
  4. Assert about the content on the page.

Step 1: Visit a page

First, let's visit a web page. We will visit ourKitchen Sink application in this exampleso that you can try Cypress out without needing to worry about finding a page totest.

We can pass the URL we want to visit to cy.visit().Let's replace our previous test with the one below that actually visits a page:

describe('My First Test', () => {
it('Visits the Kitchen Sink', () => {
cy.visit('https://example.cypress.io')
})
})

Save the file and switch back over to the Cypress Test Runner. You might noticea few things:

  1. The Command Log now showsthe new VISIT action.
  2. The Kitchen Sink application has been loaded into theApp Preview pane.
  3. The test is green, even though we made no assertions.
  4. The VISIT displays a blue pending state until the page finishesloading.

Had this request come back with a non 2xx status code such as 404 or 500,or if there was a JavaScript error in the application's code, the test wouldhave failed.

danger

Testing Apps You Don't Control

In this guide we are testing our example application:https://example.cypress.io. However you shouldthink carefully about testing applications you don't control. Why?

  • They have the potential to change at any moment which will break tests.
  • They may do A/B testing which makes it impossible to get consistent results.
  • They may detect you are a script and block your access.
  • They may have security features enabled which prevent Cypress from working.

Generally speaking, the point of Cypress is to be a tool you use every day tobuild and test your own applications, not a general purpose web automation tool.However, this is a guideline rather than a hard-and-fast rule and there are anumber of good reasons to make exceptions for certain kinds of application:

  • They are specifically designed to integrate with third parties, e.g. SSOproviders.
  • They provide you with a complementary service, e.g. SaaS control panels oranalytics.
  • They reuse your content or provide plugins for an app you control.

The key here is to carefully weigh the benefits of the tests in question againstthe possible disruption and flake these sorts of tests can introduce.

Step 2: Query for an element

Now that we've got a page loaded, we need to take some action on it. Why don'twe click a link on the page? Sounds easy enough, let's go look for one welike... how about type?

To find this element by its contents, we'll usecy.contains().

Let's add it to our test and see what happens:

describe('My First Test', () => {
it('finds the content "type"', () => {
cy.visit('https://example.cypress.io')

cy.contains('type')
})
})

Our test should now display CONTAINS in theCommand Log and still be green.

Even without adding an assertion, we know that everything is okay! This isbecause many of Cypress' commands are built to fail if they don't find whatthey're expecting to find. This is known as anImplicit Assertion.

To verify this, replace type with something not on the page, like hype.You'll notice the test goes red, but only after about 4 seconds!

Can you see what Cypress is doing under the hood? It's automatically waiting andretrying because it expects the content to eventually be found in the DOM.It doesn't immediately fail!

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (7)

caution

Error Messages

We've taken care at Cypress to write hundreds of custom error messages thatattempt to clearly explain what went wrong. In this case, Cypress timed outretrying to find the content hype within the entire page. To read more aboutthe error's display, read aboutDebugging Errors.

Before we add another command - let's get this test back to passing. Replacehype with type.

Step 3: Click an element

Ok, now we want to click on the link we found. How do we do that? Add a.click() command to the end of the previous command, likeso:

describe('My First Test', () => {
it('clicks the link "type"', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()
})
})

You can almost read it like a little story! Cypress calls this "chaining" and wechain together commands to build tests that really express what the app does ina declarative way.

Also note that the App Previewpane has updated further after the click, following the link and showing thedestination page:

Now we can assert something about this new page!

info

✨ IntelliSense is available in your Cypress spec files by adding a specialtriple slash comment line. Read aboutIntelligent Code Completion.

Step 4: Make an assertion

Let's make an assertion about something on the new page we clicked into. Perhapswe'd like to make sure the new URL is the expected URL. We can do that bylooking up the URL and chaining an assertion to it with.should().

Here's what that looks like:

describe('My First Test', () => {
it('clicking "type" navigates to a new url', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()

// Should be on a new URL which
// includes '/commands/actions'
cy.url().should('include', '/commands/actions')
})
})

Adding more commands and assertions

We are not limited to a single interaction and assertion in a given test. Infact, many interactions in an application may require multiple steps and arelikely to change your application state in more than one way.

We can continue the interactions and assertions in this test by adding anotherchain to interact with and verify the behavior of elements on this new page.

We can use cy.get() to select an element based on itsclass. Then we can use the .type() command to enter textinto the selected input. Finally, we can verify that the value of the inputreflects the text that was typed with another .should().

In general, the structure of your test should flow query -> query -> command orassertion(s). It's best practice not to chain anything after an action command;for more details on why this is, see our guide onretry-ability.

describe('My First Test', () => {
it('Gets, types and asserts', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()

// Should be on a new URL which
// includes '/commands/actions'
cy.url().should('include', '/commands/actions')

// Get an input, type into it
cy.get('.action-email').type('[emailprotected]')

// Verify that the value has been updated
cy.get('.action-email').should('have.value', '[emailprotected]')
})
})

caution

We normally don't suggest selecting and finding elements by their class names,but we do so here since we are querying an external site, and sometimes that isall we have to work with.

For more information on our guidance on selector best practices, see our guideon it here.

And there you have it: a short test in Cypress that visits a page, finds andclicks a link, verifies the URL and then verifies the behavior of an element onthe new page. If we read it out loud, it might sound like:

note

  1. Visit: https://example.cypress.io
  2. Find the element with content: type
  3. Click on it
  4. Get the URL
  5. Assert it includes: /commands/actions
  6. Get the input with the action-email data-testid
  7. Type [emailprotected] into the input
  8. Assert the input reflects the new value

Or in the Given, When, Then syntax:

note

  1. Given a user visits https://example.cypress.io
  2. When they click the link labeled type
  3. And they type "[emailprotected]" into the [data-testid="action-email"]input
  4. Then the URL should include /commands/actions
  5. And the [data-testid="action-email"] input has "[emailprotected]" as itsvalue

And hey, this is a very clean test! We didn't have to say anything about howthings work, just that we'd like to verify a particular series of events andoutcomes.

info

Page Transitions

Worth noting is that this test transitioned across two different pages.

  1. The initial cy.visit()
  2. The .click() to a new page

Cypress automatically detects things like a page transition event and willautomatically halt running commands until the next page has finishedloading.

Had the next page not finished its loading phase, Cypress would have endedthe test and presented an error.

Under the hood - this means you don't have to worry about commands accidentallyrunning against a stale page, nor do you have to worry about running commandsagainst a partially loaded page.

We mentioned previously that Cypress waited 4 seconds before timing outfinding a DOM element - but in this case, when Cypress detects apage transition event it automatically increases the timeout to 60 secondsfor the single PAGE LOAD event.

In other words, based on the commands and the events happening, Cypressautomatically alters its expected timeouts to match web application behavior.

These various timeouts are defined in theConfiguration document.

Record Tests with Cypress Studio

If you want a minimal code approach to creating tests, you can useCypress Studio to record your browserinteractions and generate tests. Visit ourguide for more information.

Next steps

  • Take our freeTesting your first applicationcourse.
  • Learn more about the Cypress App UI.
  • Start testing your app.
  • Set upintelligent code completionfor Cypress commands and assertions.
  • Record your test results to Cypress Cloud foradvanced features like parallelization, flake detection, and more.
  • Check out the Real World App (RWA) forpractical demonstrations of Cypress testing practices, configuration, andstrategies in a real-world project.
  • Search Cypress's documentation to quickly find what you need.

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (8)

End-to-End Testing: Your First Test with Cypress | Cypress Documentation (2024)

References

Top Articles
Latest Posts
Article information

Author: Nathanael Baumbach

Last Updated:

Views: 5998

Rating: 4.4 / 5 (75 voted)

Reviews: 90% of readers found this page helpful

Author information

Name: Nathanael Baumbach

Birthday: 1998-12-02

Address: Apt. 829 751 Glover View, West Orlando, IN 22436

Phone: +901025288581

Job: Internal IT Coordinator

Hobby: Gunsmithing, Motor sports, Flying, Skiing, Hooping, Lego building, Ice skating

Introduction: My name is Nathanael Baumbach, I am a fantastic, nice, victorious, brave, healthy, cute, glorious person who loves writing and wants to share my knowledge and understanding with you.