Javascript 在Cypress中覆盖cy.click()命令的正确方法是什么?

Javascript 在Cypress中覆盖cy.click()命令的正确方法是什么?,javascript,cypress,Javascript,Cypress,我正在尝试为cy构建覆盖。单击()以添加一个附加断言,该断言在单击元素之前必须为true。我知道我可以用一个自定义命令来实现这一点,但我更愿意通过重写内置命令来实现,这样我们现有的测试都可以在不需要更新的情况下得到修复,因此我们不需要记住在将来使用不同的click方法。 我目前的代码是: Cypress.Commands.overwrite('click', (originalFn, subject, options) => { cy.wrap(subject).should('n

我正在尝试为
cy构建覆盖。单击()
以添加一个附加断言,该断言在单击元素之前必须为true。我知道我可以用一个自定义命令来实现这一点,但我更愿意通过重写内置命令来实现,这样我们现有的测试都可以在不需要更新的情况下得到修复,因此我们不需要记住在将来使用不同的click方法。 我目前的代码是:

Cypress.Commands.overwrite('click', (originalFn, subject, options) => {
    cy.wrap(subject).should('not.have.attr', 'disabled').then(() => {
        return originalFn(subject,options);
    })
});
基本上,它应该检查一个额外的断言(等待它变为真,因为使用
应该
),然后执行内置的单击。我的推理是,内置的click断言无法识别某些元素上的disabled属性(例如
)。这适用于只需单击的测试,但在调用
cy.type
cy.select
时失败并显示以下消息,可能是因为这些测试在内部使用了单击

cypress_runner.js:199855 CypressError: Timed out retrying: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.

The command that returned the promise was:

  > `cy.type()`

The cy command you invoked inside the promise was:

  > `cy.wrap()`

Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.

Cypress will resolve your command with whatever the final Cypress command yields.

The reason this is an error instead of a warning is because Cypress internally queues commands serially whereas Promises execute as soon as they are invoked. Attempting to reconcile this would prevent Cypress from ever resolving.

我发现了,但是它关闭了,实际上没有给出这个问题的解决方案。覆盖单击而不引起内部调用的其他方法问题的正确方法是什么?

基于所引用的问题,我认为没有“正确”的方法覆盖单击,但对于您的用例,解决方案是查看强制选项

cypress_runner.js:199855 CypressError: Timed out retrying: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.

The command that returned the promise was:

  > `cy.type()`

The cy command you invoked inside the promise was:

  > `cy.wrap()`

Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.

Cypress will resolve your command with whatever the final Cypress command yields.

The reason this is an error instead of a warning is because Cypress internally queues commands serially whereas Promises execute as soon as they are invoked. Attempting to reconcile this would prevent Cypress from ever resolving.
.type()
发出单击时,将设置强制选项,请参阅

force:true,//强制单击,避免等待

由于
force
忽略禁用的属性,因此在调用
时不需要选中disabled。单击({force:true})

下面的内容似乎还可以,但我不确定它是否涵盖了所有场景

Cypress.Commands.overwrite('click', (originalFn, subject, options) => {

  if (!options?.force) {
    cy.wrap(subject).should('not.have.attr', 'disabled').then(() => {
      return originalFn(subject,options);
    })
  } else {
    return originalFn(subject,options);
  }
})

对于检查除禁用的
以外的内容的情况,有一个未记录的状态属性
当前的
,该属性给出命令类型

Cypress.Commands.overwrite('click', (originalFn, subject, options) => {

  const currentCommand = cy.state('current').attributes.name;

  if (currentCommand === 'click') {
    cy.wrap(subject).should('not.have.attr', 'disabled').then(() => {
      return originalFn(subject,options);
    })
  } else {
    return originalFn(subject,options);
  }
})

如果使用expect():expect(subject).to.not.have.attr('disabled');返回原始版本n(主题、选项);没有得到错误,请发布完整测试。试着点击一个按钮,点击一个按钮或输入就可以了。问题是当您使用此覆盖调用
cy.type()
cy.select()
时,因为它们最初似乎调用
cy.click()
。将覆盖添加到厨房水槽示例()并运行
select
type
的测试会重现问题。@LeonardoMartinez我尝试过,但
expect
不会像
cy.should()
那样等待条件变为真。在我的例子中,元素一开始被禁用,后来被启用(通过异步加载的JS代码),因此expect会立即失败。Woops抱歉,视力不好。这是一个好主意,将被添加,因为force应该跳过此附加检查。它确实修复了
类型
,但不幸的是,它似乎没有修复
选择
,因为它发出了两次单击(可能一次打开下拉列表,另一次选择选项),并且只将力传递给第二次单击。然而,这确实为我指明了一个有用的方向。所有这些内部调用都通过了
verify:false
来单击,但我们从未通过。因此,在这种情况下跳过此检查似乎暂时解决了问题。我添加了以下检查,它似乎正在工作,来自测试的单击确实会检查新的断言,但从单击、选择等内部调用的断言则不会<代码>如果(!options | |(!options.force&&options.verify!==false))
IMO覆盖命令评级过高。我更喜欢一个新命令的更明确的方法,或者只是在
click
前面加上
.should('not.have.attr','disabled')