From 03c2f321c42e61bc66608d72fb2602c93ec44cd0 Mon Sep 17 00:00:00 2001 From: Tamir Abutbul <1tamir198@gmail.com> Date: Tue, 9 Jan 2024 10:05:43 +0200 Subject: [PATCH] Adding cypress + example test (#476) --- frontend/cypress.config.ts | 10 +++++ frontend/cypress/support/commands.ts | 37 +++++++++++++++++++ frontend/cypress/support/component-index.html | 12 ++++++ frontend/cypress/support/component.ts | 12 ++++++ frontend/package.json | 5 ++- frontend/src/components/Button.cy.tsx | 31 ++++++++++++++++ frontend/src/components/TextInput.cy.tsx | 26 +++++++++++++ frontend/tsconfig.json | 11 +++++- 8 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 frontend/cypress.config.ts create mode 100644 frontend/cypress/support/commands.ts create mode 100644 frontend/cypress/support/component-index.html create mode 100644 frontend/cypress/support/component.ts create mode 100644 frontend/src/components/Button.cy.tsx create mode 100644 frontend/src/components/TextInput.cy.tsx diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts new file mode 100644 index 0000000..5b8a83b --- /dev/null +++ b/frontend/cypress.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + component: { + devServer: { + framework: "react", + bundler: "vite", + }, + }, +}); \ No newline at end of file diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts new file mode 100644 index 0000000..698b01a --- /dev/null +++ b/frontend/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/frontend/cypress/support/component-index.html b/frontend/cypress/support/component-index.html new file mode 100644 index 0000000..ac6e79f --- /dev/null +++ b/frontend/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/frontend/cypress/support/component.ts b/frontend/cypress/support/component.ts new file mode 100644 index 0000000..f1ad5ea --- /dev/null +++ b/frontend/cypress/support/component.ts @@ -0,0 +1,12 @@ +import "./commands"; +import { mount } from "cypress/react18"; + +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount; + } + } +} + +Cypress.Commands.add("mount", mount); \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 322a282..7ba589d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,6 +48,7 @@ "@typescript-eslint/parser": "^6.2.1", "@vitejs/plugin-react": "^3.1.0", "autoprefixer": "^10.4.14", + "cypress": "^13.3.0", "eslint": "^8.46.0", "eslint-config-prettier": "^8.7.0", "eslint-plugin-react": "^7.33.1", @@ -75,7 +76,9 @@ "lint": "npx eslint src/", "lint:fix": "npm run lint -- --fix", "prettier": "npx prettier src/ --check", - "prettier:fix": "npm run prettier -- --write" + "prettier:fix": "npm run prettier -- --write", + "cypress:open": "cypress open", + "cypress:run": "cypress run" }, "keywords": [], "author": "", diff --git a/frontend/src/components/Button.cy.tsx b/frontend/src/components/Button.cy.tsx new file mode 100644 index 0000000..875412c --- /dev/null +++ b/frontend/src/components/Button.cy.tsx @@ -0,0 +1,31 @@ +import { mount } from "cypress/react18"; +import { Button } from "./common/Button/Button"; + +describe("Button component tests", () => { + const buttonText = "buttonText"; + + it("renders", () => { + mount(); + cy.get("button").should("exist"); + }); + + it("Should have correct text", () => { + mount(); + cy.get("button").contains(buttonText); + }); + + it("calls onClick when clicked", () => { + const onClickStub = cy.stub().as("onClick"); + + mount(); + + cy.get("button").click(); + cy.get("@onClick").should("have.been.calledOnce"); + }); + + it("should be disabled", () => { + mount(); + + cy.get("button").should("be.disabled"); + }); +}); diff --git a/frontend/src/components/TextInput.cy.tsx b/frontend/src/components/TextInput.cy.tsx new file mode 100644 index 0000000..6bc9ca4 --- /dev/null +++ b/frontend/src/components/TextInput.cy.tsx @@ -0,0 +1,26 @@ +import TextInput from "../components/TextInput"; + +describe("TextInput", () => { + const label = "label"; + const placeholder = "some placeholder"; + + beforeEach(() => { + cy.mount( + { + return; + }} + /> + ); + }); + + it("contains correct label", () => { + cy.get("label").should("contain", label); + }); + + it("contains correct placeholder", () => { + cy.get("input").should("have.attr", "placeholder", placeholder); + }); +}); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ef3632d..1deabe3 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -14,8 +14,15 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "types": ["cypress"] }, - "include": ["src", "public/static", ".storybook/**/*.ts", "public/analytics.js"], + "include": [ + "src", + "public/static", + ".storybook/**/*.ts", + "public/analytics.js", + "cypress" + ], "references": [{ "path": "./tsconfig.node.json" }] }