Cypress идентифицирует элемент документа внутри DOM

#cypress

Вопрос:

У меня есть приложение, в котором есть раздел документа с некоторыми примечаниями, и я пытаюсь идентифицировать и проверить текст (« Release Notes «) с помощью Cypress. Но все мои стратегии поиска терпят неудачу и нуждаются в некоторой помощи. Пожалуйста, посмотрите, можете ли вы порекомендовать какой-нибудь другой способ найти это.

дом:

введите описание изображения здесь

Ниже приведен мой код:

 cy.get('.release-notes')
            .should('be.visible')
            .then((text => {
                cy.log(text.text()) // blank
                cy.log(text) // <span.release-notes>
            }))
       
        cy.get('[data="release-notes.html"]').should('be.visible').then((text => {
            cy.log(text.text()) // blank
            cy.log(text) // <object.release-notes-object>
        }))
        //Below lines - Fails
        //cy.get('h1:contains("Release Notes")') -- Timed out retrying after 4000ms: Expected to find element: h1:contains("Release Notes"), but never found it.
        //cy.get('body').should('contains', "Release Notes"); --Timed out retrying after 4000ms: object tested must be an array, a map, an object, a set, a string, or a weakset, but object given
    
 

Примечание: У меня "includeShadowDom": true внутри моего cypress.json

Ответ №1:

Возможно, вы будете заблокированы #document . Он не похож на ан iframe , но может вести себя как таковой.

Попробуй

 cy.get('object.release-notes-object')
  .its('0.contentDocument').should('exist')
  .its('body').should('not.be.undefined').within(() => {

    cy.get('h1').should('contain', 'Release Notes')

  })
 

Также отключите безопасность chromewebs в случае возникновения междоменной проблемы

кипарис.json

 {
  "chromeWebSecurity": false
}
 

Отладка внутреннего документа

Поскольку вы можете войти во внутренний текст документа, теоретически теперь вы должны иметь возможность запросить его.

Взгляните на внутреннее тело DOM с точки зрения Cypress, поэкспериментируйте со временем — заметки о выпуске, скорее всего, будут получены с сервера

 cy.get('object.release-notes-object')
  .its('0.contentDocument').should('exist')
  .its('body').should('not.be.undefined')
  .then($body => {
    cy.wait(10000)        // just for debugging, explicit wait here 
    .then(() => console.log($body[0].innerHTML))  // inspect the elements inside after wait
  })
 

Другим способом добавьте a .should() , чтобы повторить попытку

 cy.wait(10000)           // for debugging only, waiting for fetch
cy.get('object.release-notes-object')
  .its('0.contentDocument').should('exist')
  .its('body', {timeout: 10000})   //vary timeout here
  .should('not.be.undefined') 
  .should('have.descendants', 'h1')  // retries the body fetch until true
 

Разница между последним и добавлением тайм-аута в cy.get('h1') том .should('have.descendants', 'h1') , что при каждой повторной попытке будет повторно запрашиваться тело.

Возможно, что перед извлечением примечаний к выпуску имеется пустой элемент тела, и он заменяется при добавлении примечаний к выпуску.

Комментарии:

1. Спасибо, Михи., я попробовал и получил эту ошибку Timed out retrying after 4000ms: cy.its() errored because the property: document does not exist on your subject. cy.its() waited for the specified property document to exist, but it never did. If you do not expect the property document to exist, then add an assertion such as:

2. Согласно вашему последнему редактированию, "chromeWebSecurity": false — уже есть.

3. Я изменил код на то, что работает с <iframe> (проверено тестом). Мое предчувствие, что это может сработать, так как у iframe #document тоже есть.

4. Хорошая попытка и, к сожалению, не работает. Ошибка: Timed out retrying after 4000ms: Expected to find element: h1, but never found it.

5. Черт, значит, строки contentDocument и <body> прошли успешно? Это может быть просто проблема с тайм-аутом…

Ответ №2:

Перед "includeShadowDom": true глобальным флагом мы должны сделать что-то вроде этого:

 cy.get('selector').shadow().find('selector')
 

Теперь, может быть, вы можете опустить эту .shadow() часть и попробовать

 cy.get('[app-name="Voyage Planning"]').find('h1:contains("Release Notes")')
 

Комментарии:

1. Спасибо @Alapan. Опущение глобального shadow флага заставит меня переработать более 100 существующих хороших тестов

2. Если вы используете "includeShadowDom": true что-то, что вам не нужно добавлять .shadow . Или я что-то не так понял? Можете ли вы попробовать это cy.get('[app-name="Voyage Planning"]').find('h1:contains("Release Notes")') и посмотреть, сработает ли это?

3. Ну, я не думаю, что у нас есть проблемы с теневыми элементами. Согласно моему предположению, у cypress может не быть поддержки/документации по dom внутри dom, как в этом примере.

Ответ №3:

У вас есть атрибуты data-gr-ext-installed и data-new-gr-c-s-check-loaded на теле. Они выглядят так, как будто отмечают окончание чего-то загружающегося.

Добавьте проверку на это в решение @Mihi (которое должно быть почти правильным).

 cy.get('object.release-notes-object')
  .its('0.contentDocument').should('exist')
  .its('body')
  .should('not.be.undefined')
  .should('have.attr', 'data-gr-ext-installed')  // or data-new-gr-c-s-check-loaded
  .within(() => {

    cy.get('h1').should('contain', 'Release Notes')

  })
 

Комментарии:

1. Спасибо @Paolo., в строке 3 происходит сбой с ошибкой Timed out retrying after 4000ms: expected '<body>' to have attribute 'data-gr-ext-installed' »