我想我缺少赛普拉斯中before和beforeEach函数的工作方式。我有一个规范文件,该文件从before方法中的灯具中加载数据。其中一些数据在before函数中使用,然后在beforeEach函数中以及实际测试中再次使用。规格文件包含2个测试。第一个测试按预期执行。第二个失败,因为beforeEach表示夹具中的值之一未定义。
我的期望是,如果我以之前的方法从固定装置中加载数据,则该数据应可用于规格文件中的所有测试。
在执行“检查按钮栏的状态”时,测试beforeEach函数中的window.console.log(this.user_data)将按预期输出user_data。
执行“提交表单”时,测试beforeEach函数中的window.console.log(this.user_data)输出未定义,测试停止。
我在这里想念什么?
describe('Customer Profile', () => {
before(function () {
window.console.log('Enter the before function')
// Load the fixture data. Its asynchronous so if we want to use it right here and now
// we have to put the things that use inside a callback to be executed after the data
// loaded.
cy.fixture('user').as('user_data').then(function (){
window.console.log('Fixture has loaded the user data')
cy.visit('/LaunchPad/login')
// Fill out the login form
cy.get('input[name="username"]').type(this.user_data.username)
cy.get('input[name="password"]').type(this.user_data.password)
cy.get('button[type="submit"]').click()
})
})
beforeEach(function(){
window.console.log('Enter the beforeEach function')
window.console.log(this.user_data)
// Preserve the cookies for all tests in this suite
Cypress.Cookies.preserveOnce('SESSION')
// Open the profile view
cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
})
it('Check the state of the button bar', function(){
window.console.log('Running test of button bar')
cy.get('section.content-header > h1').contains('Company Profile Details')
// Check the state of the action bar and its buttons
cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save')
.should('have.attr', 'for', 'submit-form')
.should('have.attr', 'tabindex', '0')
cy.get('section.action-bar').get('#resetButton').contains('Reset')
.should('have.attr', 'type', 'reset')
.should('have.attr', 'value', 'Reset')
.should('have.class', 'btn btn-sm btn-default')
cy.get('section.action-bar').get('a.btn.btn-sm.btn-default').contains('Cancel')
.should('have.attr', 'href', '/Manager/'+this.user_data.org+'/')
cy.get('section.action-bar').get('a').contains('Delete').should('not.exist')
})
// This form has no required fields and no validation. So just pick a value or two
// submit the form and verify the banner is correct
it('Submit form', function(){
window.console.log('Running the submit form test')
cy.fixture('company_profile').as('company_profile')
cy.get('#companyProfileDto.name').type(this.company_profile.name)
})
})
更新 在根据卡洛斯·阿尔弗雷多(Carlos Alfredo)的回答做了更多阅读之后,我想到了这个。 1.我仍然必须访问登录页面。我们使用csrf和OATH来获取工作示例只是花费了太多时间。 2.我必须对会话cookie使用白名单,因为preserveOnce根本不起作用。
这是我现在拥有的文件。它一次访问登录页面并获得会话cookie设置。两项测试均按预期进行。
support / index.js
before(function(){
cy.login('bob', 'password')
cy.fixture('user').as('user_data')
cy.fixture('company_profile').as('company_profile')
})
beforeEach(function(){
window.console.log('Enter the global beforeEach function')
// Load the fixture data
})
support / commands.js
/*
We visit the login form despite what the best practise recommendation is because
we have OAUTH redirects and a CSRF token to deal with. Since the majority of the
examples and working use cases provided dont deal with those scenarios this is
the best I can do at the moment.
*/
Cypress.Commands.add('login', (username, password, options = {}) => {
cy.visit('/LaunchPad/login')
// Fill out the login form
cy.get('input[name="username"]').type(username)
cy.get('input[name="password"]').type(password)
cy.get('button[type="submit"]').click()
})
/*
We are white listing the cookie because Cypress.Cookies.preserveOnce('SESSION')
does not work. https://github.com/cypress-io/cypress/issues/2952
Because we are forcing Cypress to not clear the cookies, you will have to close
the test window after the suite is completed other wise the Vision360 apps will
think your session is alive.
*/
Cypress.Cookies.defaults({
whitelist: 'SESSION'
})
integration / customer_profile / customer_profile_spec.js
describe('Customer Profile', () => {
it('Check the state of the button bar', function(){
window.console.log('Running test of button bar')
cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
cy.get('section.content-header > h1').contains('Company Profile Details')
// Check the state of the action bar and its buttons
cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save')
.should('have.attr', 'for', 'submit-form')
.should('have.attr', 'tabindex', '0')
cy.get('section.action-bar').get('#resetButton').contains('Reset')
.should('have.attr', 'type', 'reset')
.should('have.attr', 'value', 'Reset')
.should('have.class', 'btn btn-sm btn-default')
cy.get('section.action-bar').get('a.btn.btn-sm.btn-default').contains('Cancel')
.should('have.attr', 'href', '/Manager/'+this.user_data.org+'/')
cy.get('section.action-bar').get('a').contains('Delete').should('not.exist')
})
// This form has no required fields and no validation. So just pick a value or two
// submit the form and verify the banner is correct
it('Submit form', function(){
window.console.log('Running the submit form test')
cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
// Fill and submit the form
cy.get('input#companyProfileDto\\.name').clear().type(this.company_profile.name)
cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save').click()
// Check the response
cy.get('.callout-success').contains('Your changes are saved.')
cy.get('input#companyProfileDto\\.name').should('have.value', this.company_profile.name)
})
})
答案 0 :(得分:5)
我遇到了几乎和您以前一样的问题。
before()
在下一个代码块之前运行。
describe("Some test", function() {
before(function() {
//something ...
cy.request('POST', loginUrl, loginInformation).its('body').as('currentUser')
})
// this.currentUser exists here
it("Should foo", function() {
})
// this.currentUser doesn't exist here
it("Should bar", function() {
})
})
我解决了将before()
语句从描述范围中移出的问题。
before(function() {
//something ...
cy.request('POST', loginUrl, loginInformation).its('body').as('currentUser')
})
describe("Some test", function() {
// this.currentUser exists here
it("Should foo", function() {
})
// this.currentUser also exists here
it("Should bar", function() {
})
})
我希望这可以帮助您解决问题。
答案 1 :(得分:1)
看起来柏树正在为每次测试清洁fixtures
。
从赛普拉斯指南(https://docs.cypress.io/guides/references/best-practices.html#Dangling-state-is-your-friend)
“我们已经构建了赛普拉斯来支持该用例。实际上,赛普拉斯不会在测试结束时清理其内部状态。我们希望您在测试结束时保持悬空状态!诸如桩,间谍之类的东西。 ,甚至在测试结束时也不会删除路由。这意味着您的应用程序在运行Cypress命令时或在测试结束后手动使用它时,其行为将相同。“
该页面中没有关于fixtures
的任何明确信息,但看起来它正在发生,fixtures
也已清除。多数民众赞成beforeEach()
在第一个测试(检查按钮栏的状态)中起作用,因为它恰好在before()
之后运行。
对于第二项测试,在before
钩子中设置的所有内容都消失了,现在beforeEach()
正在尝试获取从未定义的灯具。
希望有帮助。
您现在可能的建议: -一种好的做法是仅使用请求作为跳过UI的自定义命令进行登录。(https://docs.cypress.io/api/cypress-api/custom-commands.html#Custom-login-command)
答案 2 :(得分:0)
如果您保存了一组会话cookie,则最快的方法可能是对其进行硬编码/暴力破解,例如:
beforeEach(() => {
Cypress.Cookies.preserveOnce('SESSION') // remember cookies for this session:
cy.setCookie('logged_in_cookie_name', '000000000000000000000') // hard coded session cookie
cy.setCookie('security_salt_etc', '000000000000000000000') // its like a revokable password but more secure
})
after(() => { // logout!
cy.clearCookies()
})