变量无法在赛普拉斯的循环内更新
Variable fails to update inside a loop in Cypress
在编写 Cypress 测试时,我遇到了这个问题,它不允许我更新所需的变量。
我想要实现的是 运行 一个循环,并为某些 API 查询更新循环内的 questionId
变量。
期望的变量随着每次迭代而变化,问题是它采用初始值 0
但无法在循环内更新。
我已经阅读了多篇关于赛普拉斯 async/sync 程序的文章,但似乎没有任何帮助。
这是测试片段:
it('Should pass', function () {
cy.visit(`${Cypress.env('appUrl')}/url`)
let questionId: number = 0
for (let index = 0; index < 9; index++) {
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers')
.then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
questionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + questionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
})
}
})
赛普拉斯在传统的 for 循环中表现得怪异。不要使用传统的 for 循环,而是尝试使用 Cypress lodash 的 times
函数。 (link 转到一篇关于 Lodash 的 times
函数的文章,因为 Cypress._
只是 Lodash 的包装器。)
...
let questionId = 0;
Cypress._.times(9, () => {
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers')
.then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
questionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + questionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
})
});
问题是像
这样的同步循环
for (let index = 0; index < 9; index++) {...}
运行 在任何赛普拉斯命令开始执行之前完成。
同样适用于Cypress._.times(9, () => {...})
。
处理它的一种方法是使用递归函数。
这将等待每一步的异步代码完成,然后再继续下一步(这很重要,因为下一步取决于上一步的结果)
const handleQuestion = (questionId, iteration=0) => {
if (iteration === 9) return // finished, exit
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
// what does the intercept above do?
// Do you need to wait on it, and what triggers the GET?
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers').then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
const nextQuestionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + nextQuestionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
.then(() => {
cy.contains('button', 'Submit answer') // check that the submit button
.should('be.visible') // is ready for the next question
.and('be.enabled')
handleQuestion(nextQuestionId, ++iteration) // move on to next question
})
})
}
handleQuestion(0) // start with question #0
下一次迭代前的检查可能需要一些调整
cy.contains('button', 'Submit answer')
.should('be.visible')
.and('be.enabled')
此块旨在等待页面进入下一个问题的就绪状态。
您还可以检查一些指示就绪状态的文本,例如
cy.contains('Please submit your answer')
在编写 Cypress 测试时,我遇到了这个问题,它不允许我更新所需的变量。
我想要实现的是 运行 一个循环,并为某些 API 查询更新循环内的 questionId
变量。
期望的变量随着每次迭代而变化,问题是它采用初始值 0
但无法在循环内更新。
我已经阅读了多篇关于赛普拉斯 async/sync 程序的文章,但似乎没有任何帮助。
这是测试片段:
it('Should pass', function () {
cy.visit(`${Cypress.env('appUrl')}/url`)
let questionId: number = 0
for (let index = 0; index < 9; index++) {
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers')
.then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
questionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + questionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
})
}
})
赛普拉斯在传统的 for 循环中表现得怪异。不要使用传统的 for 循环,而是尝试使用 Cypress lodash 的 times
函数。 (link 转到一篇关于 Lodash 的 times
函数的文章,因为 Cypress._
只是 Lodash 的包装器。)
...
let questionId = 0;
Cypress._.times(9, () => {
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers')
.then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
questionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + questionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
})
});
问题是像
这样的同步循环for (let index = 0; index < 9; index++) {...}
运行 在任何赛普拉斯命令开始执行之前完成。
同样适用于Cypress._.times(9, () => {...})
。
处理它的一种方法是使用递归函数。
这将等待每一步的异步代码完成,然后再继续下一步(这很重要,因为下一步取决于上一步的结果)
const handleQuestion = (questionId, iteration=0) => {
if (iteration === 9) return // finished, exit
cy.intercept({ method: 'GET', path: `${questionId}` }).as('questionData')
// what does the intercept above do?
// Do you need to wait on it, and what triggers the GET?
cy.log('next question id: ' + questionId)
cy.intercept({ method: 'POST', path: 'answers' }).as('answers')
cy.contains('button', 'Submit answer').click()
cy.wait('@answers').then((xhr: any) => {
expect(xhr.response.statusCode).to.eq(200)
const nextQuestionId = xhr.response.body.data.next_question_id
cy.log('new question id: ' + nextQuestionId)
cy.contains('span', 'You are correct!').should('be.visible')
cy.contains('button', 'view solution').click()
cy.contains('button', 'continue').click()
.then(() => {
cy.contains('button', 'Submit answer') // check that the submit button
.should('be.visible') // is ready for the next question
.and('be.enabled')
handleQuestion(nextQuestionId, ++iteration) // move on to next question
})
})
}
handleQuestion(0) // start with question #0
下一次迭代前的检查可能需要一些调整
cy.contains('button', 'Submit answer')
.should('be.visible')
.and('be.enabled')
此块旨在等待页面进入下一个问题的就绪状态。
您还可以检查一些指示就绪状态的文本,例如
cy.contains('Please submit your answer')