End-to-end testing with Cypress series: 04 Happy path tests
- Publish Date
- Authors
- Jeremy Fairbank
- Location
- Maui, HI, USA
Transcript
In this video, add your first real-world, happy path end-to-end test with Cypress to the demo application. After watching this video, you will be able to identify happy paths in your own applications and write Cypress end-to-end tests that mimic the flow of a real user.
You will also:
- use Cypress commands such as
click
andtype
for interacting with forms - use other kinds of selectors with Cypress’
get
command - learn the best kinds of selectors to use with
get
and why CSS classes are not good selector candidates
- 00:00
- (upbeat music)
- 00:03
- Welcome back to Test Double's intro course
- 00:06
- on end-to-end testing with Cypress.
- 00:08
- In the last video you learned
- 00:10
- about real-world, happy path tests.
- 00:13
- In this video, you will dive deeper
- 00:15
- into happy path testing with Cypress.
- 00:18
- You will write your first real-world, happy path test,
- 00:22
- learn new Cypress commands to interact with forms,
- 00:26
- and learn how to use other kinds of selectors
- 00:28
- to find elements with the get command.
- 00:31
- Let's get started.
- 00:33
- First make sure you have the backend server,
- 00:35
- Cypress environment, front-end Dev server,
- 00:38
- and Cypress itself running.
- 00:41
- Refer back to the repo readme and previous videos
- 00:44
- if you need a refresher on starting those up.
- 00:47
- Also ensure you've started running the tasks.spec.js file
- 00:51
- in the Cypress browser runner
- 00:52
- by clicking on the file from the list of spec files
- 00:55
- in the Cypress app.
- 00:57
- We currently have an empty project board
- 00:59
- like many first-time users of the application.
- 01:03
- So the first action a real user might do
- 01:05
- would be to create a new task.
- 01:07
- That sounds like a great candidate
- 01:09
- for a real-world, happy path test.
- 01:12
- Open up your task.spec.js file
- 01:14
- from the yams/cypress/integration folder in your editor.
- 01:19
- Below your first test, add a new test with it,
- 01:22
- using test description creates a task.
- 01:25
- You need to click on the add task button like a real user.
- 01:30
- Inside the anonymous function, add this code.
- 01:34
- You again call the visit command to go to the project page.
- 01:39
- You also call the contains command again,
- 01:41
- passing in the text "Add Task".
- 01:44
- Notice that you can call a contains by itself
- 01:47
- without chaining off a previous command.
- 01:50
- Cypress will find the first element
- 01:52
- that contains the text "Add Task".
- 01:55
- You may notice that "Add Task"
- 01:56
- is entirely capitalized in the app,
- 01:58
- but the text we're selecting has only the first letter
- 02:01
- of each word capitalized.
- 02:03
- This is because the actual text in the DOM
- 02:06
- only has each first letter capitalized.
- 02:09
- It's the CSS that is transforming the appearance
- 02:12
- of the text to be all capitalized.
- 02:15
- By default Cypress honors case sensitivity
- 02:18
- when selecting elements with contains.
- 02:20
- So you have to make sure your selector matches
- 02:23
- what's actually in the DOM.
- 02:25
- To perform a case insensitive search,
- 02:28
- you can pass in the optional matchCase option
- 02:30
- set to false or pass in
- 02:32
- a case insensitive regular expression.
- 02:35
- Next you can chain off contains
- 02:37
- and call a new command, click.
- 02:40
- As its name suggests, the click command will click
- 02:42
- whatever the selected element from the command chain is.
- 02:46
- Unlike the contains or get command,
- 02:48
- the click command is a child command
- 02:51
- that must be called off a parent command like contains.
- 02:55
- Save the file.
- 02:57
- You should see the Cypress browser window refresh
- 02:59
- and the new test description appear on the left.
- 03:02
- Since the new test is below the previous test in the file,
- 03:06
- it should be the last test to run
- 03:08
- in the Cypress browser window too.
- 03:10
- So once the test finishes running,
- 03:12
- you should see the new task form on the right.
- 03:15
- Next you need to provide a title for the new task,
- 03:18
- but you need a way to select the title input element.
- 03:21
- Remember that Cypress is driving a browser.
- 03:24
- I have Cypress running Chrome in my case.
- 03:27
- That means you can use your browser's dev tools
- 03:30
- to inspect the DOM.
- 03:32
- Open your dev tools and inspect the input.
- 03:34
- This input has a name attribute with the value title.
- 03:38
- That could work for selecting the element.
- 03:41
- We won't cover it in this video course,
- 03:43
- but Cypress also offers a selector playground
- 03:46
- that lets you select an element,
- 03:47
- and Cypress will then suggest a selector.
- 03:50
- It's a nice feature, but some of the selectors
- 03:52
- it may suggest are highly specific and could easily break
- 03:56
- if you make changes to your front-end app,
- 03:58
- leading to false failures.
- 04:00
- So we'll stick with using dev tools.
- 04:03
- Add this line underneath the click command.
- 04:06
- You use the get command to find the element
- 04:08
- by passing in a selector for an input element
- 04:11
- with the name attribute equal to title.
- 04:14
- You chain off that with the type command,
- 04:16
- passing in the title, "New Task".
- 04:19
- As you might guess, the type command types its argument
- 04:22
- into the selected element.
- 04:24
- The type command is also a child command
- 04:26
- like the click command.
- 04:28
- Save the file.
- 04:30
- You should see the test run again,
- 04:31
- and this time type the title into the input element.
- 04:35
- Great job so far.
- 04:37
- Before you fill out more of this form though,
- 04:39
- let's adjust what is typed in the input.
- 04:42
- Recall that end-to-end tests
- 04:43
- run against the real API and database.
- 04:47
- So if you were to run a test that creates a task
- 04:49
- multiple times, you would end up with multiple tasks
- 04:52
- in the database with the same title.
- 04:55
- Tasks from previous test runs will show up
- 04:57
- on the project board.
- 04:59
- That might make it challenging to select
- 05:01
- and make assertions against the current task in a test run.
- 05:04
- You will likely want something more elegant for your test,
- 05:07
- but an easy way to generate unique titles
- 05:10
- is to add a timestamp.
- 05:11
- Update your test like so.
- 05:15
- You add a title variable
- 05:16
- that contaminates the new task string with a timestamp
- 05:20
- thanks to JavaScript's Date.now method,
- 05:22
- and ES2015 template literal string syntax.
- 05:27
- Then you pass the title into the type command.
- 05:30
- Now for every test run,
- 05:32
- you should have a unique title to ensure
- 05:34
- you can find the correct task in later assertions.
- 05:38
- Save the file,
- 05:38
- and you should see Cypress type the unique title.
- 05:42
- Next let's say the user wants to change the status
- 05:45
- from the pre-filled value.
- 05:47
- In this case, you need a way to click
- 05:48
- on the status dropdown to show the available options
- 05:52
- and click to select one of the options.
- 05:54
- Again, use dev tools to inspect the dropdown.
- 05:58
- You have a div tag
- 05:59
- with lots of classes and other attributes.
- 06:02
- In general you wanna select on contained text,
- 06:05
- or the most specific attribute that isn't a CSS class.
- 06:10
- CSS classes are more prone to be changed
- 06:12
- or moved around since they are used for styling.
- 06:15
- If that happened, then your test could start failing
- 06:17
- for irrelevant reasons, eating up your time
- 06:20
- debugging why the test started failing.
- 06:23
- You could select on the text backlog
- 06:25
- since it's the pre-filled value,
- 06:27
- but that would couple this test to the assumption
- 06:29
- that backlog is always the pre-filled value.
- 06:32
- Looking at the other attributes, the ID would work great.
- 06:36
- IDs are supposed to be unique,
- 06:38
- and are already typically used for selecting elements.
- 06:41
- We'll revisit this topic in a later video,
- 06:44
- as there are even better ways of selecting from the DOM
- 06:47
- in a more consistent manner.
- 06:49
- For now, we'll use the text and attributes
- 06:51
- we currently have at hand in the app's HTML.
- 06:55
- Add these lines to the bottom of the test.
- 06:58
- You use the get command with jQuery-like id selector syntax
- 07:02
- to select the dropdown and click on it.
- 07:05
- Then you use contains to find the in progress option
- 07:08
- and click on it.
- 07:13
- Save the file.
- 07:14
- You should see Cypress expand the dropdown
- 07:17
- and click on "In Progress".
- 07:20
- Next, you need to provide a description.
- 07:22
- Similar to the title input,
- 07:24
- we can inspect the description input
- 07:26
- to figure out a selector.
- 07:29
- We see that it's a text area and has a name attribute too.
- 07:34
- Add this line to the bottom of the test.
- 07:36
- You use the get command to select the textarea
- 07:39
- with the name attribute of description
- 07:41
- and type in the value "Do the thing".
- 07:44
- Save, and Cypress should type out the description.
- 07:47
- Next you need to give the task an estimate
- 07:50
- of level of effort.
- 07:51
- In this case, Yams uses a Fibonacci scale
- 07:54
- for estimating level of effort.
- 07:56
- Inspect the element to see what you can select on.
- 08:00
- This dropdown also has unique id attribute,
- 08:03
- so let's use that.
- 08:04
- Add these lines to the bottom of the test.
- 08:07
- You select on the id and click.
- 08:10
- Then you use contains to find the estimate option
- 08:13
- of 3 and click on it.
- 08:16
- Save the file,
- 08:18
- and you should see Cypress set the estimate to 3.
- 08:22
- Great, you're now filling out the form,
- 08:24
- but you still need to save the task and verify it's created.
- 08:28
- Add a line at the bottom of the test
- 08:30
- to select and click the "Save" button.
- 08:33
- Notice you again, pass in a string
- 08:35
- that matches how it is capitalized in the DOM
- 08:37
- versus the transformed text coming from CSS.
- 08:41
- Save the file.
- 08:43
- You should see Cypress
- 08:44
- fill out the whole form and click "Save".
- 08:47
- Then the app should go back to the project page
- 08:49
- with the new task on the board,
- 08:51
- and a success message displayed at the top of the screen.
- 08:55
- You can see with your own eyes
- 08:57
- that the app does indeed create a task,
- 08:59
- but you need your test to verify that.
- 09:02
- Let's do that by checking
- 09:03
- for the success message and verifying the task exists
- 09:06
- on the board in the correct status column.
- 09:10
- Add this line to the bottom of the test,
- 09:12
- but don't save the file yet.
- 09:14
- You use the contains command to verify the text
- 09:17
- "Created Task" eventually exists after saving.
- 09:20
- Now you need to determine
- 09:22
- if the card exists in the right column.
- 09:24
- Inspect with dev tools to see that the column
- 09:27
- also has a unique ID.
- 09:29
- Add this last line to the bottom of the test.
- 09:32
- You select the in progress column by its id,
- 09:35
- and verify somewhere down its DOM tree
- 09:38
- it contains the title of the task.
- 09:41
- This is why it was important
- 09:43
- that you generate a unique title for each task,
- 09:45
- so you don't get a false positive
- 09:47
- by matching on a task from a previous test run.
- 09:51
- Save the file and you should see it create a task
- 09:53
- and verify it was created in the correct column.
- 09:58
- And that's it, you've written your first
- 10:00
- real-world, happy path test.
- 10:03
- Let's recap what you learned in this video.
- 10:06
- You wrote your first real-world, happy path test.
- 10:09
- You learned interactive child commands like click and type.
- 10:13
- You used other kinds of selectors
- 10:15
- like name and id attributes to find elements.
- 10:18
- And you also learned about the downsides
- 10:21
- of using class attributes for selecting elements.
- 10:24
- You're now ready to write your own
- 10:26
- real-world, happy path tests.
- 10:28
- In the next video,
- 10:29
- you will add another real-world, happy path test,
- 10:32
- learning about other useful commands in Cypress,
- 10:35
- and why not to share persisted state between tests.
- 10:39
- (upbeat music)
‹ End-to-end testing with Cypress series: 03 Real-world tests
End-to-end testing with Cypress series: 05 Isolate test state ›
Jeremy Fairbank
- Code Name
- Agent 0029
- Location
- Maui, HI