首页 > 解决方案 > 如何在赛普拉斯测试中更新全局变量?

问题描述

我想在我的赛普拉斯测试文件中使用全局变量,但尽管添加了等待,但它的值并没有按预期改变。

const builder = {
  stepsArr: []
};
describe('my test', () => {
  beforeEach(() => {
    cy.intercept('/graphql', (req) => {
      req.continue((res) => {
        if (res.body.data?.steps) {
          builder.stepsArr = res.body.data.steps.steps;
          console.log({ stepsArr: builder.stepsArr }); // logs correctly!
        }
      });
    }).as('graphqlRequest');
  });
  it.only('should check global var', () => {
    cy.waitFor('steps');
    cy.wrap({ getStepByTitle: pathwayBuilder.getStepByTitle })
      .invoke('getStepByTitle',
        'some title',
        builder.stepsArr // always empty array!
      )
      .then((stepObj) => {
        cy.log(stepObj);
      });
  });
});

执行顺序正确,但全局变量的值没有更新。尽管重试了 100 次,但当我调用我的函数时它显示空数组。有什么问题?

cy.waitFor('steps');来自support/commands.js文件中的命令

Cypress.Commands.add('waitFor', operationName => {
  cy.wait('@graphqlRequest').then(({ request }) => {
    if (request.body.operationName !== operationName) {
      cy.log('Waiting for:', operationName)
      return cy.waitFor(operationName)
    }
    return null
  })
})

该函数只是在控制台上记录参数

exports.pathwayBuilder = {
    getStepByTitle: (title, steps) => {
        console.log("Search", title);
        console.log("Steps", steps); // empty!
   }
}

标签: javascripttestinggraphqlcypress

解决方案


我认为.invoke()args 是错误的,请参阅此示例invoke() - 带参数的函数

const fn = (a, b, c) => {
  return a + b + c
}

cy.wrap({ sum: fn })
  .invoke('sum', 2, 4, 6)
  .should('be.gt', 10) // true
  .and('be.lt', 20) // true

...该函数接受三个参数,它们以逗号分隔传递。

getStepByTitle接受两个参数,但传入一个 - 包含第二个参数的对象

所以

 .invoke('getStepByTitle', {
   steps: builder.stepsArr // always empty array!
 })

应该

 .invoke('getStepByTitle', 'aTitle', builder.stepsArr )

我在运行测试中发现的更多内容

  1. getStepByTitle()需要返回一些东西,否则stepObj(的结果.invoke())将是未定义的

  2. cy.wait()自定义命令中没有成功(对我来说),但是如果我在测试中内联自定义命令的代码(对于参考赛普拉斯 7.1.0)它确实有效

  3. 在完成cy.wrap({ getStepByTitle }).invoke(...之前进行评估cy.wait()。看起来像是某种优化,赛普拉斯在命令添加到队列时调用。

代替

.then(obj => obj.getStepByTitle('some title', builder.stepsArr))` 

为了

.invoke('getStepByTitle', 'some title',  builder.stepsArr )

推荐阅读