diff --git a/.eslintrc b/.eslintrc
index 22c0f3b..680ad52 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -5,7 +5,13 @@
"es6": true
},
"plugins": ["import"],
- "extends": ["eslint:recommended", "prettier", "react-app", "react-app/jest"],
+ "extends": [
+ "eslint:recommended",
+ "prettier",
+ "react-app",
+ "react-app/jest",
+ "plugin:cypress/recommended"
+ ],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
diff --git a/.gitignore b/.gitignore
index c6564a5..913194c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,3 +66,5 @@ bundle.zip
#SonarCloud
.scannerwork
.angular/cache/
+
+cypress/videos
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8351215..7f7e683 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -8,6 +8,7 @@
"reduxjs",
"SVGR",
"tailwindcss",
+ "testid",
"typeahead",
"uncompiled"
],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19d692b..6c2d264 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.2.0] - 2022-06-27
+
+- Added [cypress.io](https://www.cypress.io/)
+
## [0.1.0] - 2022-06-27
- Updated to React 18
diff --git a/README.md b/README.md
index 5beeead..d9d5c95 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ Only the important files are shown
.
├── .vscode # vscode setup (debug, snippets, etc)
├── config # tool configuration
+├── cypress # e2e tests
├── dist # production version
├── public # directory with public files (config, icons, etc)
├── scripts # Modified default create-react-app scripts
diff --git a/cypress.config.ts b/cypress.config.ts
new file mode 100644
index 0000000..8492a04
--- /dev/null
+++ b/cypress.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from "cypress";
+
+export default defineConfig({
+ e2e: {
+ setupNodeEvents(on, config) {
+ // implement node event listeners here
+ },
+ },
+ video: false,
+});
diff --git a/cypress/e2e/navigation.cy.js b/cypress/e2e/navigation.cy.js
new file mode 100644
index 0000000..784a747
--- /dev/null
+++ b/cypress/e2e/navigation.cy.js
@@ -0,0 +1,14 @@
+describe("Application navigation", () => {
+ beforeEach(() => {
+ cy.visit("http://localhost:3000");
+ });
+
+ it("Should render the navigation links", () => {
+ cy.get("[data-testid='nav']");
+ });
+
+ it("Should navigate to about when clicking on About", () => {
+ cy.get('[data-testid="nav.about"]').click();
+ cy.contains("about");
+ });
+});
diff --git a/cypress/e2e/todo.example.cy.js b/cypress/e2e/todo.example.cy.js
new file mode 100644
index 0000000..4768ff9
--- /dev/null
+++ b/cypress/e2e/todo.example.cy.js
@@ -0,0 +1,143 @@
+///
+
+// Welcome to Cypress!
+//
+// This spec file contains a variety of sample tests
+// for a todo list app that are designed to demonstrate
+// the power of writing tests in Cypress.
+//
+// To learn more about how Cypress works and
+// what makes it such an awesome testing tool,
+// please read our getting started guide:
+// https://on.cypress.io/introduction-to-cypress
+
+describe('example to-do app', () => {
+ beforeEach(() => {
+ // Cypress starts out with a blank slate for each test
+ // so we must tell it to visit our website with the `cy.visit()` command.
+ // Since we want to visit the same URL at the start of all our tests,
+ // we include it in our beforeEach function so that it runs before each test
+ cy.visit('https://example.cypress.io/todo')
+ })
+
+ it('displays two todo items by default', () => {
+ // We use the `cy.get()` command to get all elements that match the selector.
+ // Then, we use `should` to assert that there are two matched items,
+ // which are the two default items.
+ cy.get('.todo-list li').should('have.length', 2)
+
+ // We can go even further and check that the default todos each contain
+ // the correct text. We use the `first` and `last` functions
+ // to get just the first and last matched elements individually,
+ // and then perform an assertion with `should`.
+ cy.get('.todo-list li').first().should('have.text', 'Pay electric bill')
+ cy.get('.todo-list li').last().should('have.text', 'Walk the dog')
+ })
+
+ it('can add new todo items', () => {
+ // We'll store our item text in a variable so we can reuse it
+ const newItem = 'Feed the cat'
+
+ // Let's get the input element and use the `type` command to
+ // input our new list item. After typing the content of our item,
+ // we need to type the enter key as well in order to submit the input.
+ // This input has a data-test attribute so we'll use that to select the
+ // element in accordance with best practices:
+ // https://on.cypress.io/selecting-elements
+ cy.get('[data-test=new-todo]').type(`${newItem}{enter}`)
+
+ // Now that we've typed our new item, let's check that it actually was added to the list.
+ // Since it's the newest item, it should exist as the last element in the list.
+ // In addition, with the two default items, we should have a total of 3 elements in the list.
+ // Since assertions yield the element that was asserted on,
+ // we can chain both of these assertions together into a single statement.
+ cy.get('.todo-list li')
+ .should('have.length', 3)
+ .last()
+ .should('have.text', newItem)
+ })
+
+ it('can check off an item as completed', () => {
+ // In addition to using the `get` command to get an element by selector,
+ // we can also use the `contains` command to get an element by its contents.
+ // However, this will yield the