Cypress-wait-until - 等待元素属性改变

use*_*513 2 javascript wait cypress

我正在测试一个具有按钮的应用程序,该按钮会导致屏幕上另一个元素中的值发生更改,而无需重新加载页面。但是,该值的变化几乎是即时的,或者需要几秒钟。显然,我不想使用一些任意的等待,我不想使用(硬)断言 - 这可能会导致测试停止,但不是失败......所以我一直在看 cypress-wait-until ( https://www.npmjs.com/package/cypress-wait-until )。我已经按照以下方式编写了各种变体:

    waitForElemToChange(elem) {
        elem.invoke('attr', val').then((initialVal) => {
        cy.waitUntil(() => elem.invoke('attr', 'value').then((val) => val != initialVal))
    }
Run Code Online (Sandbox Code Playgroud)

但到目前为止没有任何效果 - 大多数尝试都导致“重试超时:cy.invoke() 出错,因为您的主题是:null。您不能对空值调用任何函数,例如 attr。”

然而它是在前一行中刚刚返回一个值的同一个主题??

小智 20

这看起来太复杂了。我会通过等待initialValue,然后等待不同的值来实现它。

cy.get('input').should('have.value', 'myInitialValue');     // wait for initial value
cy.get('input').should('not.have.value', 'myInitialValue'); // wait for it to change
Run Code Online (Sandbox Code Playgroud)

.should()将重试断言最多 4 秒。

如果“几秒”指的是超过 4 秒,则可以添加一个超时选项,这比任意等待更好,因为一旦断言通过,它就会继续。

我假设您的元素是输入,因为您正在访问valnot text

  • 很好的答案,适合我使用文本:`cy.get('element').should('contain', 'some text');` (4认同)

Mud*_*era 5

我浏览了你的函数,我认为使用存在几个问题。这可能是与柏树相关的问题或等待插件。

首先,在您的代码中,我认为使用elem您尝试传递类似cy.get("path") 的问题是当您第一次调用elem并尝试重新使用elem 时,它变为空值。因此,如果您希望cy.get('path')运行两次,则不会发生。

其次,出于某种原因,在你等到,

cy.waitUntil(() => elem.invoke('attr', 'value').then((val) => val != initialVal))

//This part becomes true all the time.
elem.invoke('attr', 'value').then((val) => val != initialVal))
Run Code Online (Sandbox Code Playgroud)

第三,

invoke('attr', 'value')
Run Code Online (Sandbox Code Playgroud)

不会捕获对象的变化属性。请注意,这些观察结果是通过尝试您尝试做的事情而收集到的。需要额外的研究来找出函数的确切行为。

考虑到上述事实,我对代码做了一些更改。

  • 更改的主要更新是传递 CSS 路径而不是 cypress 对象 ( elem )
  • 使用 js 查询选择器操作来获取变化的值(获取初始值,我们可以使用 invoke )

示例 1:在 waitUntil 中获取新值并检查变量更改

const CheckElementChange = (path) => {
    //get the initial value of your object
    cy.get(path).invoke('attr', 'value').then($initialVal => {
        //It's better if you can do your click operation here

        //Wait untill the element changes
        cy.waitUntil(() =>
        cy.get(path).then($newVal => 
            $newVal[0].value !== $initialVal),
            //optional timeouts and error messages
            {
                errorMsg: "was expeting some other Value but got : " + $initialVal,
                timeout: 10000, 
                interval: 500 
              }
        ).then(() => {
            cy.log("Foudn a difference in values")
        })
})
}
Run Code Online (Sandbox Code Playgroud)

示例 2:在新值提取后移动 waitUntill 并等待newVal !== initialVal为真

const CheckElementChangew = (path) => {
    //get the initial value of your object
    cy.get(path).invoke('attr', 'value').then($initialVal => {
        //It's better if you can do your click operation here

        //Wait untill the element changes
        cy.get(path).then($newVal => {
            cy.waitUntil(() => $newVal[0].value !== $initialVal, {
                //optional timeouts and error messages
                errorMsg: "was expeting some other Value but got : " + $initialVal,
                timeout: 10000, 
                interval: 500 
              }).then(() => {
                cy.log("Foudn a difference in values")
            })
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

用法 :

it('test',() => {
    CheckElementChange2("#fname");
})
Run Code Online (Sandbox Code Playgroud)

注意:如果您希望点击时值发生变化,除非值变化有几秒钟的时间间隔,否则最好在提取初始值后进行点击(如上面代码中所述)