[Cypress] install, configure, and script Cypress for JavaScript web applications -- part1
Despite the fact that Cypress is an application that runs natively on your machine, you can install it and add it as a dependency just like all other dependencies in your package.json file. So let's install Cypress and get our project ready to start end-to-end testing with Cypress.
install:
npm i -D cypress
Run:
npx cypress open
It will create some default tests and run the tests.
Config with eslint:
npm i -D eslint-plugin-cypress
Open .eslintrc.js:
const path = require('path')
module.exports = {
extends: [
'kentcdodds',
'kentcdodds/import',
'kentcdodds/webpack',
'kentcdodds/jest',
'kentcdodds/react',
],
plugins: ['eslint-plugin-cypress'],
env: {'cypress/globals': true},
overrides: [
{
files: ['**/__tests__/**'],
settings: {
'import/resolver': {
jest: {
jestConfigFile: path.join(__dirname, './jest.config.js'),
}
}
}
}
]
}
Update .gitignore:
coverage
node_modules
dist
cypress/videos
cypress/screenshots
Write the first Cypress Test
Cypress starts out your project with a ton of tests, let’s remove those and add our first test that verifies our calculator can add two numbers together using the Cypress selector playground and Cypress commands.
describe('anonymous calculator', () => {
it('can make calculation', () => {
cy.visit('http://localhost:8080')
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(3)') // get 1
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(4)') // get +
.click()
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(5)') // get 3
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(5)') // get =
.click()
.get('.mNQM6vIr72uG0YPP56ow5')// get display
.should('have.text', '4');
})
})
Configure Cypress in cypress.json
Cypress is fairly simple to configure, but it’s important to optimize our experience in testing Cypress. We’ll configure the baseUrl to make it easier to visit our app and we’ll also move our test files to a folder called e2e to make it more clear what types of tests we want to write with Cypress. We’ll use the cypress.json file, but Cypress can also be configured via command line flags and environment variables.
// cypress.json
{
"baseUrl": "http://localhost:8080",
"integrationFolder": "cypress/e2e/",
"viewportHeight": 900,
"viewportWidth": 400,
"defaultCommandTimeout": 5000
}
We have config the 'baseUrl', so in the test, we can use:
describe('anonymous calculator', () => {
it('can make calculation', () => {
cy.visit('/')
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(3)')
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(4)')
.click()
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(5)')
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(5)')
.click()
.get('.mNQM6vIr72uG0YPP56ow5')
.should('have.text', '4');
})
})
Installing cypress-testing-library
Our selectors are pretty ridiculous, mostly because we’re using CSS-in-JS and css modules for our react application. But even if we weren’t, using class names as selectors for our application testing is pretty brittle and not really testing in the way a user would. So instead let’s use cypress-testing-library to improve our selectors and make it easier to read our tests.
The following part of code is really hard to read and maintain because those wired selector
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(3)')
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(4)')
.click()
.get('._2S_Gj6clvtEi-dZqCLelKb > :nth-child(5)')
.click()
.get('._1yUJ9HTWYf2v-MMhAEVCAn > :nth-child(5)')
.click()
.get('.mNQM6vIr72uG0YPP56ow5')
To solve the problem, let's install:
npm i -D cypress-testing-library
Inside cypress/support:
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
import 'cypress-testing-library/add-commands' // Import commands.js using ES2015 syntax:
import './commands' // Alternatively you can use CommonJS syntax:
// require('./commands')
Update the tests:
cy.visit('/')
.getByText(/^1$/)
.click()
.getByText(/^\+$/)
.click()
.getByText(/^3$/)
.click()
.getByText(/^\=$/)
.click()
For the display, we need to use 'data-testid':
Update the component:
return (
<div
className={styles.autoScalingText}
style={{transform: `scale(${scale},${scale})`}}
ref={this.node}
data-testid="total"
>
{this.props.children}
</div>
Now the test looks like:
describe('anonymous calculator', () => {
it('can make calculation', () => {
cy.visit('/')
.getByText(/^1$/)
.click()
.getByText(/^\+$/)
.click()
.getByText(/^3$/)
.click()
.getByText(/^\=$/)
.click()
.getByTestId('total')
.should('have.text', '4');
})
})
Scripting Cypress for local development and Continuous Integration
We want to make starting cypress as simple as possible for local development and we need to be able to run a single script that exits when the tests are complete for continuous integration. So let’s add a few scripts to get ourselves setup for this development experience.
Install:
npm install --save-dev start-server-and-test
When we run e2e test, check if it is CI, when we run:
cypress run // not open the broswer
Otherwise:
cypress open
Then we want to run our server first, after get response from server, then we want to run cypress automaticlly:
start-server-and-test start http://localhost:8080 cy:run // run 'start' first, it will start the server wait response from 'http://localhost:8080', if get the response, then run cy:run' command
Scripts:
"scripts": {
"test": "is-ci \"test:coverage\" \"test:watch\"",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch",
"test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --watch",
"cy:run": "cypress run",
"cy:open": "cypress open",
"pretest:e2e:run": "npm run build",
"test:e2e": "is-ci \"test:e2e:run\" \"test:e2e:dev",
"test:e2e:run": "start-server-and-test start http://localhost:8080 cy:run",
"test:e2e:dev": "start-server-and-test dev http://localhost:8080 cy:open",
"dev": "webpack-serve",
"build": "webpack --mode=production",
"precommit": "lint-staged",
"postbuild": "cp ./public/index.html ./dist/index.html",
"start": "serve --no-clipboard --listen 8080 dist",
"lint": "jest --config test/jest-lint.js",
"format": "prettier \"**/*.js\" --write",
"validate": "npm run test && && npm run test:e2e:run",
"setup": "npm run setup && npm run validate"
},
Debug a test with Cypress
One of the greatest features of Cypress is how awesome the experience of debugging tests is. You do have to get used to the asynchronous nature of E2E testing, but once you get the hang of that debugging is pretty straightforward, and the ability to debug your own source code is awesome. The fact that your test and source code are executed in the same context also gives you some powerful advantages as well. You can potentially even expose some internal state to your Cypress app.
The way to add a debugger in the Cypress:
describe('anonymous calculator', () => {
it('can make calculation', () => {
cy.visit('/')
.getByText(/^1$/)
.click()
.getByText(/^\+$/)
.click()
.getByText(/^3$/)
.click()
.getByText(/^\=$/)
.then(subject => {
debugger
return subject;
})
.click()
.getByTestId('total')
.should('have.text', '4');
})
})
or
.getByText(/^\=$/)
.debug()
.click()
And
we can add cy.log('xxx'):
cy.log('get by text')
cy.getByText(/^\=$/)
.debug()
.click()
In the component, you can also put a debugger:
ReactDOM.render(
<Component initialState={{}}>
{({state, setState}) => {
debugger
if(window.Cypress) {
window.appState = state
window.setAppState = setState
}
[Cypress] install, configure, and script Cypress for JavaScript web applications -- part1的更多相关文章
- [Cypress] install, configure, and script Cypress for JavaScript web applications -- part3
Use custom Cypress command for reusable assertions We’re duplicating quite a few commands between th ...
- [Cypress] install, configure, and script Cypress for JavaScript web applications -- part2
Use Cypress to test user registration Let’s write a test to fill out our registration form. Because ...
- [Cypress] install, configure, and script Cypress for JavaScript web applications -- part4
Load Data from Test Fixtures in Cypress When creating integration tests with Cypress, we’ll often wa ...
- [Cypress] install, configure, and script Cypress for JavaScript web applications -- part5
Use the Most Robust Selector for Cypress Tests Which selectors your choose for your tests matter, a ...
- Cypress系列(3)- Cypress 的初次体验
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前言 这里的栗子项目时 Cypress ...
- Cypress系列(41)- Cypress 的测试报告
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 注意 51 testting 有一篇文章 ...
- document.write('<script type=\"text/javascript\"><\/script>')
document.write('<script type=\"text/javascript\"><\/script>')
- <script language = "javascript">, <script type = "text/javascript">和<script language = "application/javascript">(转)
application/javascript是服务器端处理js文件的mime类型,text/javascript是浏览器处理js的mime类型,后者兼容性更好(虽然application/ ...
- 2.1 <script>元素【JavaScript高级程序设计第三版】
向 HTML 页面中插入 JavaScript 的主要方法,就是使用<script>元素.这个元素由 Netscape 创造并在 Netscape Navigator 2 中首先实现.后来 ...
随机推荐
- Python编程快速上手--实践项目11.11.1
from selenium import webdriver from selenium.webdriver.common.keys import Keys import time def messa ...
- module_param
该宏定义在include/linux/moduleparam.h中 #define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a ...
- 17,时间模块 time,random模块
表示时间的三种方式 在python中,通常有着三种方式来表示时间:时间戳,元祖,格式化的时间字符串: 1,时间戳(timestamp):通常来说时间戳表示的是从1970年1月1日00:00:00开始按 ...
- Clojure基础
最近看了一段clojure,下面是从书上摘下来的一下语言基础的精华部分 ;函数的基本形式 (defn average [numbers] (/ (apply + numbers) (count num ...
- Eclipse截取android报错log
Eclipse截取android报错log: 1.前提条件:已安装eclipse 2. LogCat界面设置: Logcat是Android 编程中一个命令行工具,可以用于得到程序的 log 信息,可 ...
- 【Luogu】P1231教辅的组成(拆点+Dinic+当前弧优化)
题目链接 妈耶 我的图建反了两次 准确的说是有两个地方建反了,然后反上加反改了一个小时…… 知道为什么要拆点吗? 假设这是你的图 左边到右边依次是超级源点 练习册 书 答案 ...
- 【Luogu】P1967货车运输(最大生成森林+倍增LCA)
题目链接 倍增LCA是个什么蛇皮原理啊,循环完了还得再往上跳一次才能到最近公共祖先 合着我昨天WA两次就是因为这个 建最大生成森林,因为图不一定是联通的,所以不一定是一棵树.这个地方用克鲁斯卡尔就好了 ...
- P1279 字串距离 (动态规划)
题目描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X ...
- 「SDOI2010」古代猪文(bzoj1951)
题目写了一大堆背景. 一句话题意就是求 $q^{\sum_{d|n}C_{n}^{d}} \mod 999911659$. 因为$n$是质数,只有当$q$是$n$的倍数时(此题数据范围原因,最多$q= ...
- Jackson工具类(各种转换)
首先要在项目中引入jackson的jar包(在此不做说明) 下面直接上代码 public class JacksonUtils { private final static ObjectMapper ...