Merged in feat/cypress (pull request #1)

Adding cypress integration into the webapp

* Merge branch 'master' into feat/cypress

* moving the config files to ts

* updating from master

* adding pipeline config

* updating the cypress base image to use the same node version

* moving node to 14.15.4

* unifying all the tasks into one step

* using cypress base image for the whole pipeline for now

* removing cypress examples

* adding readme for tests

Approved-by: Ezequiel Bergamaschi
This commit is contained in:
Juan Allo 2021-02-23 05:40:02 +00:00
parent b7c5ff3940
commit d4094c4b27
13 changed files with 889 additions and 35 deletions

View File

@ -4,16 +4,23 @@
# The workflow allows running tests and code linting on the default branch. # The workflow allows running tests and code linting on the default branch.
# Node LTS # Node LTS
image: node:14.15.5 image: cypress/base:14.15.4
pipelines: pipelines:
default: default:
- parallel: - parallel:
- step: - step:
name: Build and Test name: Build and test
caches: caches:
- node - node
- npm
- cypress
script: script:
- yarn install - yarn install
- yarn build - yarn build
- yarn lint - yarn lint
- yarn test
definitions:
caches:
npm: $HOME/.npm
cypress: $HOME/.cache/Cypress

View File

@ -5,7 +5,7 @@
"build": "lerna run build", "build": "lerna run build",
"clean": "lerna clean && rm -rf node_modules", "clean": "lerna clean && rm -rf node_modules",
"lint": "lerna run lint", "lint": "lerna run lint",
"test": "lerna run test" "test": "lerna run test --stream"
}, },
"private": true, "private": true,
"devDependencies": { "devDependencies": {
@ -22,7 +22,7 @@
"Ezequiel Bergamaschi" "Ezequiel Bergamaschi"
], ],
"engines": { "engines": {
"node": "=14.15.5" "node": "=14.15.4"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

3
packages/webapp/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
cypress/screenshots
cypress/videos
cypress/downloads

View File

@ -0,0 +1,4 @@
{
"video": false,
"videoUploadOnPasses": false
}

View File

@ -0,0 +1,26 @@
# Running tests with cypress.
For details on why we picked Cypress, check the following [PR](https://bitbucket.org/wisemapping/wisemapping-react/pull-requests/1)
Check the [Cypress docs](https://docs.cypress.io/guides/overview/why-cypress.html) for more information
## How to run it
- To run the test cases headless run: `yarn test`
- To debug the tests you can use cypress interactive UI by running `yarn cypress open` (You will need to have the UI running in a separate terminal `yarn start`)
## How to write a new test case
Any new test cases should be added under the `cypress/integration` folder. Aim to group similar test cases in one file.
If any stub/mock is needed, those should be added to `cypress/fixtures` folder. Cypress has a [built in way](https://docs.cypress.io/api/commands/fixture.html#Usage) of using those.
We use `data-testid` as a practice to define selectors in the code and we leverage the [Cypress Testing Library plugin](https://testing-library.com/docs/cypress-testing-library/intro/) to find the elements in the tests.
- We leverage a `data-testid` or selecting by text (`findAllByText`, `findByText`) to make sure the test cases are decoupled from the implementation.
We leverage the [Page Object Pattern](https://martinfowler.com/bliki/PageObject.html) to abstract away selectors and actions and simplify changes required to future refactors. Take a look to any example under the `cypress/pageObject` folder to see how that pattern is implemented.
Finally any common functionality such as for example `login` should be abstracted into a command. CY Commands can be added into the `cypress/support` folder. Feel free to group similar commands into files (You only need to make sure those get imported into the `cypress/support/index.ts` file)
Happy testing!!!

View File

@ -0,0 +1,16 @@
import MapsPage from "../pageObject/MapsPage";
context("Maps Page", () => {
beforeEach(() => {
cy.visit("http://localhost:3000/c/maps");
});
it("should load the maps page", () => {
MapsPage.isLoaded();
});
it("should open the create dialog", () => {
MapsPage.create();
MapsPage.isCreateDialogVisible();
});
});

View File

@ -0,0 +1,14 @@
export default class MapsPage {
static isLoaded() {
return cy.findByTestId("create");
}
static create() {
return cy.findByTestId("create").click();
}
static isCreateDialogVisible() {
//TODO move to findByText when the double create dialog issue is solved
return cy.findAllByText("Create a new mindmap");
}
}

View File

@ -0,0 +1,7 @@
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@ -0,0 +1 @@
import '@testing-library/cypress/add-commands'

View File

@ -0,0 +1 @@
import './commands'

View File

@ -7,6 +7,8 @@
"build": "webpack --config webpack.prod.js", "build": "webpack --config webpack.prod.js",
"build-dev": "webpack --config webpack.dev.js", "build-dev": "webpack --config webpack.dev.js",
"lint": "eslint src", "lint": "eslint src",
"cy:run": "cypress run",
"test": "start-server-and-test start http-get://localhost:3000 cy:run",
"extract": "formatjs extract", "extract": "formatjs extract",
"compile": "formatjs compile" "compile": "formatjs compile"
}, },
@ -16,6 +18,8 @@
"private": false, "private": false,
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^2.13.15", "@formatjs/cli": "^2.13.15",
"@testing-library/cypress": "^7.0.3",
"@types/testing-library__cypress": "^5.0.8",
"@typescript-eslint/eslint-plugin": "^4.8.1", "@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1", "@typescript-eslint/parser": "^4.8.1",
"brotli-webpack-plugin": "^1.1.0", "brotli-webpack-plugin": "^1.1.0",
@ -23,6 +27,7 @@
"compression-webpack-plugin": "^7.1.2", "compression-webpack-plugin": "^7.1.2",
"copy-webpack-plugin": "^7.0.0", "copy-webpack-plugin": "^7.0.0",
"css-loader": "^5.0.1", "css-loader": "^5.0.1",
"cypress": "^6.5.0",
"eslint": "^7.14.0", "eslint": "^7.14.0",
"eslint-plugin-react": "^7.21.5", "eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
@ -56,6 +61,7 @@
"react-redux": "^7.2.2", "react-redux": "^7.2.2",
"react-router": "^5.1.8", "react-router": "^5.1.8",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"start-server-and-test": "^1.12.0",
"styled-components": "^5.1.7" "styled-components": "^5.1.7"
} }
} }

View File

@ -145,6 +145,7 @@ const MapsPage = (): ReactElement => {
<Toolbar> <Toolbar>
<Tooltip arrow={true} title={intl.formatMessage({ id: 'maps.create-tooltip', defaultMessage: 'Create a New Map' })}> <Tooltip arrow={true} title={intl.formatMessage({ id: 'maps.create-tooltip', defaultMessage: 'Create a New Map' })}>
<Button color="primary" <Button color="primary"
data-testid="create"
size="medium" size="medium"
variant="contained" variant="contained"
type="button" type="button"

830
yarn.lock

File diff suppressed because it is too large Load Diff