javascript - before 和 beforeEach 在 Cypress 中究竟是如何工作的?

标签 javascript cypress

我想我遗漏了一些关于 before 和 beforeEach 函数在 Cypress 中的工作方式。我有一个 spec 文件,它在 before 方法中从夹具加载数据。其中一些数据在 before 函数中使用,然后在 beforeEach 函数中再次使用,并在实际测试中使用。规范文件包含 2 个测试。第一个测试按预期执行。第二个失败,因为 beforeEach 表示来自夹具的值之一未定义。

我的期望是,如果我在 before 方法中从固定装置加载数据,它应该可用于规范文件中的所有测试。

执行“检查按钮栏的状态”时,测试 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. 我必须对 session cookie 使用白名单,因为 preserveOnce 根本不起作用。

这是我现在拥有的文件。它访问登录页面一次并获取 session cookie 设置。两项测试按预期进行。

支持/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

})

支持/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'
})

集成/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)
    })

})

最佳答案

我遇到了一个几乎和你之前遇到的问题一样的问题。

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() {
    })
})

希望能帮到您解决问题。

关于javascript - before 和 beforeEach 在 Cypress 中究竟是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55501838/

相关文章:

javascript - 使用 Javascript HTML 和 jQuery 的下拉列表

javascript - KnockoutJS,与 2D 数组的样式绑定(bind)?

typescript - 为什么我在 Cypress 中收到错误 `TypeError: fs.readdir is not a function`

javascript - 如何在 cy.visit() 中向 URL 插入动态值?

testing - 拖动点不起作用并且不会引发错误

html - Cypress :如何测试 HTML5 内置的验证弹出窗口?

javascript - Object.assign 与赋值 (=)

javascript - 使用 CSSTransitionGroup 和 React-Router v6 动画路由过渡

javascript - ajax - 刷新 div 的 javascript 函数

angular - Cypress - 以编程方式操作 Angular/NGRX 应用程序