首页 > 解决方案 > 在赛普拉斯中,如何找到具有相同 ID 的选择并获取长度?

问题描述

我有一个这样的 HTML 代码。

<div id ='pages'>
    <div id='wrapper'>1 </div>
    <div id='wrapper'>2 </div>
</div>

我想用 id 包装器查找元素计数。我使用赛普拉斯。我开始学习赛普拉斯。如果我尝试:

cy.get('div#wrapper').should('have.length', 2)

我得到断言错误:

CypressError: Timed out retrying: expected 1 to equal 2

标签: testingcypress

解决方案


正如jonrsharpe指出的那样,拥有多个具有相同id属性的元素是无效的 HTML。

话虽如此,DOM 非常聪明,即使是无效的 HTML 也可以恢复和工作。重复id元素不应该造成太大的麻烦。

如果您尝试这样做document.querySelectorAll('#wrapper'),它应该返回 2 个元素的列表(在您的情况下)。

问题是,赛普拉斯使用 jQuery 来查询 DOM,而不是使用原生 DOM 方法,我猜 jQuery 没有那么聪明(或者更迂腐)。

话虽如此,我在运行时无法重现该错误:

// succeeds
cy.get('div#wrapper').should('have.length', 2)

仅在#wrapper直接查询时(没有前面的div):

// fails
cy.get('#wrapper').should('have.length', 2)

I reckon this is because jQuery uses a heuristic of exiting early when a selector string ( #wrapper) contains only a single id (and that's why div#wrapperreturns both elements).

此外,您在注释 ( cy.get('#pages') .find('div#wrapper') .should(($div) => { expect($div).to.have.length(2) })) 中的解决方案在工作时并不理想,因为它不会重试。让我演示一下:

在下面的代码中,第二个#wrapper只会在 1 秒后出现在 DOM 中。

describe( 'test', () => {
    beforeEach(() => {
        cy.document().then( doc => {
            doc.body.innerHTML = `
                <div id='pages'>
                    <div id='wrapper'>1</div>
                </div>
            `;
            setTimeout(() => {
                doc.body.innerHTML = `
                    <div id='pages'>
                        <div id='wrapper'>1</div>
                        <div id='wrapper'>2</div>
                    </div>
                `;
            }, 1000 );
        });
    });

    // will fail
    it('solution A', () => {
        cy.get('#pages') // <- won't be retried
            .find('div#wrapper') // <- only this command will be retried
            .should( $div => expect($div).to.have.length(2) );
    });

    // will pass
    it('solution B', () => {
        cy.get('#pages #wrapper') // <- will be retried and succeed in 1sec
            .should( $div => {
                expect($div).to.have.length(2);
            });
    });

    // will pass
    it('solution C', () => {
        cy.get('#pages')
            .should($pages => {
                // using native DOM querying
                expect($pages[0].querySelectorAll('#wrapper').length).to.eq(2);
            });
    });
});

因此,您应该使用类似于Bor的解决方案C


推荐阅读