В Cypress, как найти подсчет выбора с тем же идентификатором и получить длину? - PullRequest
0 голосов
/ 20 марта 2019

У меня такой HTML-код.

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

Я хочу найти количество элементов с помощью id-оболочки.Я использовал Cypress.Я начинаю изучать кипарис.Если я попытаюсь:

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

Я получу ошибку AssertionError:

CypressError: Timed out retrying: expected 1 to equal 2

1 Ответ

0 голосов
/ 23 марта 2019

Как указывало jonrsharpe , в HTML нельзя использовать несколько элементов с одинаковым атрибутом id.

При этом DOM достаточно умен и может восстанавливаться и работать даже с некорректным HTML. Дублирующие элементы - id не должны вызывать особых проблем.

Если вы, например, попробуйте сделать document.querySelectorAll('#wrapper'), он должен вернуть список из 2 элементов (в вашем случае).

Проблема в том, что Cypress использует jQuery для запроса DOM вместо использования собственных методов DOM, и я предполагаю, что jQuery не такой умный (или более педантичный).

При этом я не могу воспроизвести эту ошибку при запуске:

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

Только при прямом запросе #wrapper (без предшествующего div):

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

Я считаю, что это связано с тем, что jQuery использует эвристику преждевременного выхода, когда строка селектора (#wrapper) содержит только один идентификатор (и именно поэтому div#wrapper возвращает оба элемента).

Кроме того, ваше решение в комментариях (cy.get('#pages') .find('div#wrapper') .should(($div) => { expect($div).to.have.length(2) })), хотя и работает, не идеально, потому что оно не будет повторяться. Позвольте мне продемонстрировать:

В следующем коде 2-й #wrapper появится в DOM только через 1 сек.

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);
            });
    });
});

Таким образом, вы должны пойти с решением, аналогичным B или C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...