大家好,我是阿萨。8月开始了,夏日未央。学习的好时机。大家一起加油。好好学习,天天向上。Cypress的基本用法基本都讲解完了。这一期,总结下Cypress 比其他 Web UI 自动化更好的地方。
一,闭包(Closure)
Cypress 中, 保存一个值或者引用对的最好方式是使用闭包。其中then 就是Cypress的典型应用。
先介绍一个场景: 有个button, 在点击了提交按钮后,这个button的文本会 变化。 然后我们写一个用例来比较下 form 提交后,button 会变化的场景。
代码如下:
it('test then', function() { cy.get('btn').then(($btn)=>{const txt=$btn.text() cy.get('form').submit() cy.get('btn').should(($btn2)=>{ expect($btn2.text()).not.to.eq(txt) expect($btn2.text()).not.to.eq(txt) }) }
二, 变量和别名。
Cypress 可以使用wrap 或者as 变量去给元素赋值或者实现变量共享。
- wrap
我们先看wrap 的典型使用场景。
通过wrap 传递变量。
const getName =()=>{return 'Sarah' } cy.wrap({name:getName}).invoke('name').should('eq','Sarah')
来看看wrap的语法:
cy.wrap(subject)cy.wrap(subject, options)
常见用法,除了上面的例子,还有如下2种;
cy.get('form').within(($form) => {// ... more commands cy.wrap($form).should('have.class', 'form-container')})
cy.get('button').then(($button) => {// $button is a wrapped jQuery elementif ($button.someMethod() === 'something') {// wrap this element so we can// use cypress commands on it cy.wrap($button).click() } else {// do something else }})
// import application code for logging inimport { userService } from '../../src/_services/user.service' it('can assert against resolved object using .should', () => { cy.log('user service login')const username = Cypress.env('username')const password = Cypress.env('password') // wrap the promise returned by the application code cy.wrap(userService.login(username, password))// check the yielded object .should('be.an', 'object') .and('have.keys', ['firstName', 'lastName', 'username', 'id', 'token']) .and('contain', { username: 'test', firstName: 'Test', lastName: 'User', }) // cy.visit command will wait for the promise returned from// the "userService.login" to resolve. Then local storage item is set// and the visit will immediately be authenticated and logged in cy.visit('/')// we should be logged in cy.contains('Hi Test!').should('be.visible')})
2. as
as 是用来分配别名供以后使用。
语法:
.as(aliasName)
常见用法:
cy.get('.main-nav').find('li').first().as('firstNav') // Alias element as @firstNavcy.intercept('PUT', '/users').as('putUser') // Alias route as @putUsercy.stub(api, 'onUnauth').as('unauth') // Alias stub as @unauthcy.spy(win, 'fetch').as('winFetch') // Alias spy as @winFetch
给元素加个别名
it('disables on click', () => { cy.get('button[type=submit]').as('submitBtn') cy.get('@submitBtn').click().should('be.disabled')})
对用cy.intercept()定义的被拦截路由进行别名,然后使用cy.wait()等待别名路由。
cy.intercept('PUT', '/users', { fixture: 'user' }).as('editUser') // we'll assume submitting `form` triggers a matching requestcy.get('form').submit() // once a response comes back from the `editUser`// this `wait` will resolve with the subject containing `url`cy.wait('@editUser').its('url').should('contain', 'users')
说白了, 这2个传递变量的方式就是为了规避Cypress的异步执行的坑。
明天讲解Cypress的那些坑。
今天就到这了。