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的更多相关文章

  1. [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 ...

  2. [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 ...

  3. [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 ...

  4. [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 ...

  5. Cypress系列(3)- Cypress 的初次体验

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前言 这里的栗子项目时 Cypress ...

  6. Cypress系列(41)- Cypress 的测试报告

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 注意 51 testting 有一篇文章 ...

  7. document.write('<script type=\"text/javascript\"><\/script>')

    document.write('<script type=\"text/javascript\"><\/script>')

  8. <script language = "javascript">, <script type = "text/javascript">和<script language = "application/javascript">(转)

          application/javascript是服务器端处理js文件的mime类型,text/javascript是浏览器处理js的mime类型,后者兼容性更好(虽然application/ ...

  9. 2.1 <script>元素【JavaScript高级程序设计第三版】

    向 HTML 页面中插入 JavaScript 的主要方法,就是使用<script>元素.这个元素由 Netscape 创造并在 Netscape Navigator 2 中首先实现.后来 ...

随机推荐

  1. python--MySQl单表查询

    一.  关键字的执行优先级(重点) from where group by having # 使用是要放在group by 后面而且前面必须有group by select distinct # 去重 ...

  2. leepcode作业解析-5-15日

    1.删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外 ...

  3. django第六天(模板相关,过滤器和标记)

    django第6天 DTL简介 django template language django模板语言 语法: filter{{}} tag{% %} 简单变量的使用 视图函数可以通过两种方式将变量船 ...

  4. 数据结构( Pyhon 语言描述 ) — —第11章:集和字典

    使用集 集是没有特定顺序的项的一个集合,集中的项中唯一的 集上可以执行的操作 返回集中项的数目 测试集是否为空 向集中添加一项 从集中删除一项 测试给定的项是否在集中 获取两个集的并集 获取两个集的交 ...

  5. 交换机VLAN的定义、意义以及划分方式

    什么是VLAN 虚拟网技术(VLAN,Virtual Local Area Network)的诞生主要源于广播.广播在网络中起着非常重要的作用,如发现新设备.调整网络路径.IP地址租赁等等,许多网络协 ...

  6. JavaScript括号中什么什么不加引号什么时候加引号?

    *****我的QQ号:1539832180.欢迎一起讨论学习.***** 1.如果是你定义的变量,不能加引号. 因为在大多数语言里面,单引号(或双引号)里面的内容表示的都是字符串. 2.如果是你定义的 ...

  7. suse-12-linux gcc gcc-c++离线安装教程,不使用yum等

    最近这几天接手新的项目,要部署新的服务器,采用目前比较主流的框架开发的程序,前后端进行了分离.在这种情况下就需要使用nginx做代理,以便于很好的区分前后端,目前虽然已经有很多很好的发布体系,但是个人 ...

  8. 利用pytorch复现spatial pyramid pooling层

    sppnet不讲了,懒得写...直接上代码 from math import floor, ceil import torch import torch.nn as nn import torch.n ...

  9. Centos7 编译安装python3

    step1:preparation $ yum install yum-utils make wget gcc $yum-builddep python step2:download $ wget h ...

  10. hdu2087

    #include <stdio.h> #include <string.h> int main(){ int cnt,i,j,k; +],tmp[+]; int strl,tm ...