1. Multiple Assertions
cy .get('[data-cy=task]') .then( item => { expect(item[0]).to.contain.text('bread') expect(item[1]).to.contain.text('milk') })
- 用 then()就不会retry, 即使页面发生变化, expect assertion也不会retry.
cy .get('[data-cy=task]') .should( item => { if (item.length !== 3) { throw new Error('Not enough elements!') } expect(item[0]).to.contain.text('bread') expect(item[1]).to.contain.text('milk') })
- 用should(), 如果页面上元素发生变化, assert前面的一个命令就会retry。
- 可以加一些logic决定要不要做assertion。
2. Invisible element - changing the DOM
当Dom里面有一些invisible的element, 我们需要用.click(force:true) 来click到。更好的办法是让这个element显示出来。
cy .get('[data-cy=star]') // invisible element, only display when mouse over the 'board-item'. .invoke('show') .should('be.visible') .click()
同时我们也可以通过trigger()的办法来测试元素什么时候display。当鼠标靠近时display, 鼠标离开时disappear.
cy .get('[data-cy="board-item"]') .trigger('mouseover') cy .get('[data-cy=star]') .should('be.visible') cy .get('[data-cy="board-item"]') .trigger('mouseout') cy .get('[data-cy=star]') .should('not.be.visible')
- Cypress checks actionability of elements
- .invoke() function can change attributes of DOM elements.
- Trigger different type of events. Event listeners can be triggererd by .trigger() command.
3. Cookies
保存token在cookies里面,这样执行测试时候不用每个case都需要login一次。
方法一: 保存cookies 里面的token在support file>index.js里面,所有的tests都会share这个token。
Cypress.Cookies.defaults({ preserve: 'trello_token' })
方法二: 只是单个文件share这个token, 则可以放在 berore each里面:
beforeEach(() => { Cypress.Cookies.preserveOnce('trello_token') cy .visit('/') }) it('test #1', () => { cy .setCookie('trello_token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImZpbGlwQGV4YW1wbGUuY29tIiwiaWF0IjoxNjE1OTg5MTkyLCJleHAiOjE2MTU5OTI3OTIsInN1YiI6IjIifQ.c3HqS_RRCJp4IPYvwbUkxWPwBx4VXJa_0ArzKq7qx_M') cy .reload() }); it('test #2', () => { });
- Cypress deletes cookies and other storage in between tests
- Cypress.Cookies API enables you to change cookies rules.
4. Intercepting Network Requests
- use .intercept() to match any http request our app makes.
- intercepted http requests can be waited for.
- Intercepted http requests can be tested.
it('Intercept requests', () => {
cy
.intercept({
method: 'POST',
url: '/api/boards'
}).as('createBoard')
cy
.visit('/')
cy
.get('[data-cy=create-board]')
.click()
cy
.get('[data-cy=new-board-input]')
.type('launching a rocket{enter}')
cy
.wait('@createBoard')
.then( (board) => {
expect(board.response.statusCode).to.eq(201)
expect(board.request.body.name).to.eq('launching a rocket')
})
});
5. Stubbing Responses
stubbing response, 举例 如果get response stubbing empty.
cy .intercept({ method: 'GET', url: '/api/boards' }, { body: [] }).as('boardList')
can use fixture to load a json file as request reponse body:
cy .intercept({ method: 'GET', url: '/api/boards' }, { fixture: 'threeBoards' }).as('boardList')
stubbing network error:
cy .intercept({ method: 'POST', url: '/api/boards' }, { forceNetworkError: true }).as('boardList') cy.visit('/') cy.get('[data-cy-create-board]') .click() cy.get('[data-cy=new-board-input]') .type('new board{enter}') cy.get('#errorMessge') .should('be.visible')
- Second argument modifies intercepted request
- We can dynamically change just a part of response data.
it('Stubbing response', () => {
cy
.intercept({
method: 'GET',
url: '/api/boards'
}, (req) => {
req.reply( (res) => {
res.body[0].starred = true
return res
})
}).as('boardList')
cy
.visit('/')
});
6. Creating a custom command
- Create .d.ts definmitions file to get autocomplete of custom command.
- JSDoc adds documentation to custom comands.
create a custom comman in the test file or under the support folder > commands.js.(notes: can add the command in a index to load type definitions that come tish cypress module.E.g. command.d.ts or index.d.ts check in cypress documents. )
Cypress.Commands.add('addBoard', (input) => {
cy
.get('[data-cy="create-board"]')
.click();
cy
.get('[data-cy=new-board-input]')
.type(input + '{enter}');
})
it('Custom commands', () => {
cy
.visit('/');
cy
.addBoard('groceries');
});
More powerful custom command using prevSubject: true or prevSubject: 'optional' command to call a child command only.
- custom commands can be parent, child or dual.
- https://testautomationu.applitools.com/advanced-cypress-tutorial/chapter9.html
Cypress.Commands.add('take', {prevSubject: 'optional'}, (subject, input) => {
if (subject) {
cy
.wrap(subject)
.find(`[data-cy=${input}]`)
} else {
cy
.get(`[data-cy=${input}]`)
}
})
it('Custom commands', () => {
cy
.visit('/board/77787127477');
cy
.take('list')
.eq(0)
.take('task')
});
7. Install Plugins
8. Running a Task
We can run a task in the background , wait for it to finish, and then continue on with our test.
