A couple of months ago I have announced a Cypress.io course Testing The Swag Store targeted at the beginners who want to learn web end-to-end and component testing using Cypress.io test runner. The short announcement video can be seen below
It is hard to believe, but I have been on a roll creating lots and lots of lessons for this course. It now covers end-to-end testing, React component testing, Test-Driven Development, continuous integration using GitHub Actions, and collecting 100% code coverage. Each lesson is a full exercise for you to perform. Here are the lessons as of middle of April. The 📺 emoji next to the title means the lesson already has a video, I am still in the process of recording the rest. The 🎁 emoji means the lesson is free to watch without buying the course. Tip: you can vote on the next lessons to make free from this course by signing up for my monthly Cypress Tips & Tricks newsletter.
- Introduction to this course 🎁 📺
- Introduction to the course and what you will learn.
- Lesson 1: Write your first Cypress test 🎁 📺
- Run the swag store application locally and write your first Cypress end-to-end test.
- Lesson 2: Confirm the lowest price in the store 🎁 📺
- Inspect the web store inventory and confirm the item with the lowest price.
- Lesson 3: Confirm the sorted prices 📺
- Test sorting items by their price.
- Lesson 4: Sort by price from highest to lowest 📺
- Test sorting items by their price.
- Lesson 5: Refactor sort by price tests 📺
- Remove the duplicate testing code by moving it into helper functions.
- Lesson 6: Add sorting by name tests 📺
- Add two tests to confirm sorting by name works.
- Lesson 7: Confirm item text details 📺
- Find multiple elements by text inside one common parent element.
- Lesson 8: Load item data from a fixture file 📺
- Load JSON fixture file and confirm the item is present.
- Lesson 9: Validate the inventory list 📺
- Load the inventory list from the fixture file and check the page.
- Lesson 10: Test the locked out user login error message 📺
- How to check the login error message plus page objects.
- Lesson 11: Testing anonymous visit error message 📺
- Confirm a user cannot directly visit the inventory page without logging in first.
- Lesson 12: Testing empty username and passwords 📺
- Confirm the application needs the username and the password to log in.
- Lesson 13: Instant login by setting a cookie 🎁 📺
- Store the session cookie in a variable to restore it for instant login.
- Lesson 14: Instant login using cypress-data-session 🎁 📺
- Let the
cypress-data-session
cache the cookie value.
- Let the
- Lesson 15: Instant login using cy.session command 📺
- Let Cypress cache the browser state using
cy.session
command.
- Let Cypress cache the browser state using
- Lesson 16: Skip visit by disabling test isolation 📺
- Visit the page just once at the start of the spec.
- Lesson 17: Reusable login page object method 📺
- Visit the page just once at the start of the spec.
- Lesson 18: Avoid hard-coded username and password 📺
- Move the login information into the
env
config object.
- Move the login information into the
- Lesson 19: Organize NPM scripts for Cypress testing 📺
- Add NPM script commands and use
start-server-and-test
utility.
- Add NPM script commands and use
- Lesson 20: Test the item product view 📺
- Load the product view showing an individual item.
- Lesson 21: Confirm the exact item id 📺
- Load the product view showing an individual item.
- Lesson 22: Confirm item ids are unique 📺
- Each product item id attribute should be unique.
- Lesson 23: Simplify getting attribute from a list of elements 📺
- Map elements to attributes using
cypress-map
plugin.
- Map elements to attributes using
- Lesson 24: Add items to the cart 📺
- Verify the Add button and the cart badges work.
- Lesson 25: Page object for the inventory page 📺
- Rewrite the
add-to-cart.cy.js
spec usingInventoryPage
object.
- Rewrite the
- Lesson 26: Switch to using TypeScript for your tests 📺
- Configure TypeScript with Cypress
- Lesson 27: Test the Cart page
- Configure TypeScript with Cypress
- Lesson 28: Validate the user cy.session
- Check the session by visiting the protected page
- Lesson 29: Validate the user cy.session by checking cookie existence
- Faster session validation without visiting the page
- Lesson 30: Remove items from the cart
- Write a test to remove items from the cart
- Lesson 31: Confirm the items stored in the local storage
- Check the cart item ids written to the
localStorage
.
- Check the cart item ids written to the
- Lesson 32: Load inventory data
- Avoid hard-coding or duplicating inventory data.
- Lesson 33: Use application inventory data
- Use the existing inventory data from the application source code.
- Lesson 34: Set product ids in the local storage
- Use the
localStorage
to instantly open the cart page with items.
- Use the
- Lesson 35: Test the checkout process
- Go through the checkout pages.
- Lesson 36: Confirm the order items total 📺
- Verify the item total amount shown during the checkout process.
- Lesson 37: Confirm the order tax
- Verify the order tax is between 5% and 10% of the item price total.
- Lesson 38: Control application by invoking its methods 📺
- Set the cart contents by calling the application's own methods
- Lesson 39: Refactor filling out the information form
- Move the duplicate code into a custom command.
- Lesson 40: Yield the form element from the custom command
- Allow chaining more commands and assertions to your custom command.
- Lesson 41: Convert fill form into a child command
- Yield the form to be filled to the custom commadn
cy.fillForm()
.
- Yield the form to be filled to the custom commadn
- Lesson 42: Pass selectors and values to the custom command
- Yield the form to be filled to the custom commadn
cy.fillForm()
.
- Yield the form to be filled to the custom commadn
- Lesson 43: Add TypeScript types for your custom command
- Make your type linter and editor happy.
- Lesson 44: Use your custom command from page object method
- Remove code duplication when filling out the user information form.
- Lesson 45: Refactor login to use the cy.fillForm custom command
- Update the
login.page.ts
to use the new commandcy.fillForm
.
- Update the
- Lesson 46: Organize your specs and support file
- Organize your specs, support, and page object source files.
- Lesson 47: Replace relative paths with TypeScript aliases
- Use TS path aliases for shorter imports.
- Lesson 48: Test with different users
- Run the same full feature flow for all configured users.
- Lesson 49: Refactor the locked-out user test
- Skip the locked-out user test when testing all users
- Lesson 50: Isolate the problem user test failure
- Add more assertions to understand where the test goes wrong.
- Lesson 51: Debug the green performance glitch test
- Catch performance problems with lower timeouts.
- Lesson 52: Exploratory testing
- Find a bug and write a test for it.
- Lesson 53: Test-driven development
- Change the application code until the test turns green.
- Lesson 54: Add a custom command to get elements by the test id
- Implement a custom command
cy.getByTest
.
- Implement a custom command
- Lesson 55: Configure React component testing
- Set up React component testing in your project and mount the Button component.
- Lesson 56: Confirm the button has been clicked
- Pass the
cy.stub
to the Button component and confirm it is called on click.
- Pass the
- Lesson 57: Confirm a disabled button cannot be clicked
- Mount a disabled
Button
component and confirm it does not call the click prop.
- Mount a disabled
- Lesson 58: Test SubmitButton and Select components
- Write two component tests for low-level React components.
- Lesson 59: Test the InventoryItem component
- Mounting components that use the Router.
- Lesson 60: Component test adding item to the cart
- Add and remove the item by clicking buttons.
- Lesson 61: Working with local storage
- Check the local storage object after adding an item to the cart.
- Lesson 62: Include styles in the component test
- Implement the
CartItem
component tests.
- Implement the
- Lesson 63: Test the inventory list component
- Check the saved state by calling the shopping cart code.
- Lesson 64: Run Cypress tests on CI
- Run end-to-end and component tests using GitHub Actions service.
- Lesson 65: Speed up CI by splitting the specs
- Run specs in parallel using
cypress-split
plugin.
- Run specs in parallel using
- Lesson 66: Write unit tests using Cypress
- Test the
ShoppingCart
class using Cypress.
- Test the
- Lesson 67: Buy more than 1 of the same item
- Implement a new feature using test-driven development at all test levels.
- Lesson 68: Update all failing specs
- Update the tests failing after the previous lesson.
- Lesson 69: Fix the experimentalRunAllSpecs mode
- Make all e2e specs pass in
experimentalRunAllSpecs=true
mode
- Make all e2e specs pass in
- Lesson 70: Confirm the quantity change on checkout
- Confirm the user can buy two bike lights.
- The end of the course 🥇
- The closing thoughts and what to study next
Bonus lessons
- Bonus 01: Instrument application to get code coverage from E2E tests 📺
- Prepare application for collecting code coverage using Cypress end-to-end tests.
- Bonus 02: Generate the code coverage report 📺
- Generate the code coverage human-readable HTML report.
- Bonus 03: Collect the full E2E code coverage report 📺
- Generate the combined code coverage report from all E2E tests.
- Bonus 04: Exclude files from the code coverage report
- Exclude the service worker source files from code coverage.
- Bonus 05: Get element attributes using Ramda
- Revisit the lesson 22 using Ramda library.
- Bonus 06: Run all tests nightly using Cypress GitHub Action
- Periodically confirm the tests are passing using GHA service.
- Bonus 07: Show the code coverage badge
- Update the code coverage badge in the README after nightly tests.
- Bonus 08: Increase the code coverage
- Write end-to-end tests to fill the code coverage gaps.
- Bonus 09: Almost fully test the DrawerMenu component
- Add E2E tests to cover the code in
src/components/DrawerMenu.jsx
source file.
- Add E2E tests to cover the code in
- Bonus 10: Stop accidentally committing exclusive tests
- Use the
stop-only
utility to prevent checking init.only
tests.
- Use the
- Bonus 11: List all tests
- Use the
find-cypress-specs
utility to report all tests in the project.
- Use the
- Bonus 12: Use path aliases in component tests
- Use
@cypress
path alias in the component spec
- Use
- Bonus 13: Instrument code for component tests
- Tell Webpack to instrument the components for our components tests.
- Bonus 14: Generate code coverage reports for component tests
- Configure the
@bahmutov/cypress-code-coverage
plugin to work with component tests.
- Configure the
- Bonus 15: Combine E2E and Component coverage
- Produce a unified code coverage report on CI.
- Bonus 16: Increase InventoryItem code coverage
- Decide how to reach the code lines through tests.
- Bonus 17: Do not ignore parts of the source code
- Remove
istanbul ignore
comments to collect the true code coverage.
- Remove
- Bonus 18: Push the shopping cart to 100% code coverage
- Test the data edge cases to achieve full coverage.
- Bonus 19: Modify DOM to test an edge condition
- Target the default case in a Select switch statement.
- Bonus 20: Cover the InventoryListItem component
- Cover almost the entire
InventoryListItem
component with tests.
- Cover almost the entire
- Bonus 21: Write tests for the problem user persona
- Write separate tests for the problem user.
- Bonus 22: Full coverage for InventoryListItem for the problem user
- Complete the code coverage for
components/InventoryListItem.jsx
file.
- Complete the code coverage for
- Bonus 23: Test the incorrect login information
- Confirm an unknown user cannot log in.
- Bonus 24: Push the code coverage to a 100
- Cover the last few lines with end-to-end and small component tests.
- Bonus 25: Confirm thumbnail images
- Regular users should see thumbnail images and the problem user should see the standard 404 thumbnail.
- Bonus 26: Simulate a broken image link
- Use
cy.intercept
command to simulate 404 error when loading a thumbnail image.
- Use
- Bonus 27: Confirm every image loads
- Check that every image on the inventory page loads successfully.
- Bonus 28: Log message only on error
- Do not overwhelm Command Log with passing assertions.
- Bonus 29: Combine the code coverage from split E2E test jobs
- Use
cypress-workflows
split workflow v1 to automatically merge code reports when running E2E specs in parallel.
- Use
- Bonus 30: Split the component specs
- Use
cypress-workflows
split workflow v1 to automatically merge code reports when running component specs in parallel.
- Use
- Bonus 31: A single workflow with combined code coverage
- Use
cypress-workflows
split workflow v2 to run E2E and component tests in parallel and then merge all code coverage reports.
- Use
- Bonus 32: How to debug Cypress plugins
- Use the
DEBUG
variable to control diagnostic output when running Cypress.
- Use the
- Bonus 33: Expire data session after N milliseconds
- Automatically recompute the cached
cypress-data-session
cookie after a certain time period.
- Automatically recompute the cached
- Bonus 34: Add a badge with number of tests
- Add a README badge with the number of end-to-end and component tests in the project.
- Bonus 35: Include all source files in the code coverage report
- Make sure no source files are accidentally skipped by the tests.
- Bonus 36: Manipulate data- attributes using cypress-map methods
- Grab all
data-*
attributes viadataset
object and adjust the types before checking them usingcypress-map
queries.
- Grab all
If you are looking for advanced courses, I have Cypress Plugins and Cypress Network Testing Exercises that for sure will teach you something new.
Update 1: made a lesson public
In my April newsletter Cypress Tips April 2023 I asked which lesson to make public, and the people picked Lesson 17: Reusable login page object method, so I made it public.