[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 we’ll be running this against a live backend, we need to generate the user’s information to avoid re-runs from trying to create new users that already exist. There are trade-offs with this approach. You should probably also clean out the application database before all of your tests start (how you accomplish this is pretty application-specific). Also, if your application requires email confirmation, I recommend you mock that on the backend and automatically set the user as confirmed during tests.
Let's create a helper method first.
support/generate.js
import {build, fake} from 'test-data-bot'
const userBuilder = build('User').fields(
{
username: fake(f => f.internet.userName()),
password: fake(f => f.internet.password())
}
)
export {userBuilder}
Then, create tests:
e2e/register.js
import {userBuilder} from '../support/generate'
describe('should register a new user', () => {
it('should register a new user', () => {
const user = userBuilder();
cy.visit('/')
.getByText(/register/i)
.click()
.getByLabelText(/username/i)
.type(user.username)
.getByLabelText(/password/i)
.type(user.password)
.getByText(/submit/i)
.click()
.url()
.should('eq', `${Cypress.config().baseUrl}/`)
.window()
.its('localStorage.token')
.should('be.a', 'string')
});
});
Cypress Driven Development
Because Cypress allows you to use all the developer tools you’re used to from Google Chrome, you can actually use Cypress as your main application development workflow. If you’ve ever tried to develop a feature that required you to be in a certain state you’ve probably felt the pain of repeatedly refreshing the page and clicking around to get into that state. Instead, you can use cypress to do that and developer your application entirely in Cypress.
Simulate HTTP Errors in Cypress Tests
Normally I prefer to test error states using integration or unit tests, but there are some situations where it can be really useful to mock out a response to test a specific scenario in an E2E test. Let’s use the cypress server and route commands to mock a response from our registration request to test the error state.
it(`should show an error message if there's an error registering`, () => {
cy.server()
cy.route({
method: 'POST',
url: 'http://localhost:3000/register',
status: 500,
response: {},
})
cy.visit('/register')
.getByText(/submit/i)
.click()
.getByText(/error.*try again/i)
})
Test user login with Cypress
To test user login we need to have a user to login with. We could seed the database with a user and that may be the right choice for your application. In our case though we’ll just go through the registration process again and then login as the user and make the same assertions we made for registration.
import {userBuilder} from '../support/generate'
describe('should register a new user', () => {
it('should register a new user', () => {
const user = userBuilder();
cy.visit('/')
.getByText(/register/i)
.click()
.getByLabelText(/username/i)
.type(user.username)
.getByLabelText(/password/i)
.type(user.password)
.getByText(/submit/i)
.click()
// now we have new user
.getByText(/logout/i)
.click()
// login again
.getByText(/login/i)
.click()
.getByLabelText(/username/i)
.type(user.username)
.getByLabelText(/password/i)
.type(user.password)
.getByText(/submit/i)
.click()
// verify the user in localStorage
.url()
.should('eq', `${Cypress.config().baseUrl}/`)
.window()
.its('localStorage.token')
.should('be.a', 'string')
.getByTestId('username-display', {timeout: 500})
.should('have.text', user.username)
});
});
Create a user with cy.request from Cypress
We’re duplicating a lot of logic between our registration and login tests and not getting any additional confidence, so lets reduce the duplicate logic and time in our tests using cy.request to get a user registered rather than clicking through the application to register a new user.
import {userBuilder} from '../support/generate'
describe('should register a new user', () => {
it('should register a new user', () => {
const user = userBuilder();
// send a http request to server to create a new user
cy.request({
url: 'http://localhost:3000/register',
method: 'POST',
body: user
})
cy.visit('/')
.getByText(/login/i)
.click()
.getByLabelText(/username/i)
.type(user.username)
.getByLabelText(/password/i)
.type(user.password)
.getByText(/submit/i)
.click()
// verify the user in localStorage
.url()
.should('eq', `${Cypress.config().baseUrl}/`)
.window()
.its('localStorage.token')
.should('be.a', 'string')
.getByTestId('username-display', {timeout: 500})
.should('have.text', user.username)
});
});
Keep tests isolated and focused with custom Cypress commands
We’re going to need a newly created user for several tests so let’s move our cy.request command to register a new user into a custom Cypress command so we can use that wherever we need a new user.
Because we need to create user very often in the test, it is good to create a command to simply the code:
//support/commands.js
import {userBuilder} from '../support/generate'
Cypress.Commands.add('createUser', (overrides) => {
const user = userBuilder(overrides);
// send a http request to server to create a new user
cy.request({
url: 'http://localhost:3000/register',
method: 'POST',
body: user
}).then(response => response.body.user)
})
We chain .then() call is to get the created user and pass down to the test.
describe('should register a new user', () => {
it('should register a new user', () => {
cy.createUser().then(user => {
cy.visit('/')
.getByText(/login/i)
.click()
.getByLabelText(/username/i)
.type(user.username)
.getByLabelText(/password/i)
.type(user.password)
.getByText(/submit/i)
.click()
// verify the user in localStorage
.url()
.should('eq', `${Cypress.config().baseUrl}/`)
.window()
.its('localStorage.token')
.should('be.a', 'string')
.getByTestId('username-display', {timeout: 500})
.should('have.text', user.username)
})
});
});
[Cypress] install, configure, and script Cypress for JavaScript web applications -- part2的更多相关文章
- [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 ...
- [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 -- 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 中首先实现.后来 ...
随机推荐
- scrollTop如何实现click后页面过渡滚动到顶部
用JS操作,body元素的scrollTop var getTop = document.getElementById("get-top"); var head = documen ...
- python--基础数据类型的补充与深浅copy
一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...
- python中join()函数讲解
本文简述的是string.join(words[, sep]),它的功能是把字符串或者列表,元组等的元素给连接起来,返回一个字符串,和split()函数与正好相反,看下面的代码理解. a=[" ...
- django 常见过滤器
一.形式:小写 {{ name | lower }} 二.过滤器是可以嵌套的,字符串经过三个过滤器,第一个过滤器转换为小写,第二个过滤器输出首字母,第三个过滤器将首字母转换成大写 标签 {{ st ...
- Django之ORM操作(重要)
Django ORM操作 一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给 ...
- Codeforces Round #416 (Div. 2) 本来以为这个时间是晚上的,下午就没做
A. Vladik and Courtesy time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- 九度oj 题目1173:查找
题目描述: 输入数组长度 n 输入数组 a[1...n] 输入查找个数m 输入查找数字b[1...m] 输出 YES or NO 查找有则YES 否则NO . 输入: 输入有多组数据. ...
- iOS第三方地图-高德地图(导航sdk路径规划)
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- BZOJ4446 [Scoi2015]小凸玩密室 【树形Dp】
题目 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 ...
- 算法复习——带修改莫队(bzoj2453)
题目: Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A ...