[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
      }

 

posted @   Zhentiw  阅读(568)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-12-05 [Angular2 Router] Get activated router url
2014-12-05 [Express] Level 5: Route file
点击右上角即可分享
微信分享提示