[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 中首先实现.后来 ...
随机推荐
- Verilog之delay的两种用法(inter/intra)
verilog语言中有两种延迟方式:inter-delay和intra-delay,关于inter和intra.这两个英文前缀都有“内部,之间”的意思,但又有所不同.inter表达不同事物之间,int ...
- 《零基础入门学习Python》【第一版】视频课后答案第006讲
python中被看作假:FALSE none 0 ‘ ’ " " ( ) [ ] { },其他一切都被解释为真 测试题答案: 0.Python 的 floor 除法现在使用 ...
- IOS 自动布局-UIStackPanel和UIGridPanel(三)
在这一篇了我将继续讲解UIGridPanel. 在iphone的app里面可以经常看到一些九宫格布局的应用,做过html开发的对这类布局应该是很熟悉的.在IOS中要实现这样的布局方法还是蛮多的,但是我 ...
- HDU 4280 Island Transport
Island Transport Time Limit: 10000ms Memory Limit: 65536KB This problem will be judged on HDU. Origi ...
- BNUOJ 5227 Max Sum
Max Sum Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: ...
- 【JavaScript 1—基础知识点】:宏观概述
导读:JavaScript是一门新的(也可以说是旧的或者半新语言),里面有很多的知识点都能和已有的知识产生共鸣.但是,虽然简单,相同点也有很多,也有不同点.我脑袋也不好使,所以对于我来说,还是有必要再 ...
- 【C#】重写和重载的区别
导读:学习C#的时候,其实没想那么多的.就想着把视频看完,把例子做一下就好了,其实真心不懂那些玩意儿是什么,就好像是又回到了学VB的时候.可是,边上师哥压榨我这本就不聪明的脑袋瓜,问了我好多问题,于是 ...
- Thread.getContextClassLoader() is null
Java threads created from JNI code in a non-java thread have null ContextClassloader unless the crea ...
- 刷题总结——赛车(bzoj3190)
题目: 题目背景 JLOI2013 T1 题目描述 这里有一辆赛车比赛正在进行,赛场上一共有 N 辆车,分别称为 g1,g2,……,gn.赛道是一条无限长的直线.最初,gi 位于距离起跑线前进 ki ...
- Spoj-TRNGL Make Triangle
Make Triangle Chayanika loves Mathematics. She is learning a new chapter geometry. While reading the ...