cy.get возвращает неверный элемент jquery - PullRequest
5 голосов
/ 21 февраля 2020

Вот фрагмент моего тестового кода:

cy.get('div[data-component-data-id=301602] h2:first')
  .should(($el) => {
    expect($el).to.have.text('dress')
  })

и кипарис жалуется на утверждение:

CypressError: Timed out retrying: You attempted to make a chai-jQuery assertion on an object that is neither a DOM object or a jQuery object.

The chai-jQuery assertion you used was:

  > text

The invalid subject you asserted on was:

  > Object{3}

To use chai-jQuery assertions your subject must be valid.

This can sometimes happen if a previous assertion changed the subject.

Так что мне нужно изменить expect($el).to.have.text('dress') на expect($el[0]).to.have.text('dress'), затем жалоба отклонена и тест пройден.

Я немного отлаживаю утверждение, оказывается, $el[0] также является элементом jquery.

Вот снимок о $el и $el[0]:

enter image description here

Итак, мой вопрос: Разве cy.get не эквивалентно jquery $? Почему я должен получить первый элемент из $el? Почему $el[0] is also a jquery element?

Заранее спасибо.

РЕДАКТИРОВАТЬ:

Оказывается, эта ошибка связана с кодом приложения при его включает в себя библиотеку Zepto. Я поднял проблему в репозитории Cypress Github, в которой вы можете отслеживать прогресс.

Ответы [ 2 ]

5 голосов
/ 29 февраля 2020

Я не совсем уверен, что вы ищете на этом этапе, но нашел способ сбросить эффект библиотеки zepto.

Подводя итог,

  • zepto - это jquery -совместимая библиотека, которая принимает глобальный $ в окне вашего приложения. ref

    $ = функция (селектор, контекст) {
    return zepto.init (селектор, контекст)
    }

  • в результате такие команды cy, как .get() и .wrap(), дают форму в zepto-wrapped результата jquery, который не совместим с chai expect() без некоторой деструктуризации.

Экспериментируя с Cypress.$ Я обнаружил, что он все еще ссылается на jquery propper, например

const h2 = Cypress.$('h2')

возвращает объект jquery, а не объект zepto, поэтому мы можем сбросить глобальное приложение $ из Cypress. $.

it('title display', () => {

  cy.visit('index.html')  // zepto takes effect here

  // Reset $
  const win = cy.state('window');
  win.$ = Cypress.$;

  cy.get('h2')
    .should($el => {
      expect($el).to.have.text('dress')  // passes
    })
})

Код сброса может быть включен в переписать команду cy.visit(), чтобы сделать ее менее распространенной.

Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
  return originalFn(url, options).then(_ => {
    const win = cy.state('window')
    win.$ = Cypress.$
  })
})
...

it('title display', () => {

  cy.visit('index.html')

  cy.get('h2')
    .should($el => {
      expect($el).to.have.text('dress')  // passes
    })
})

NOTE Это влияет на способ z epto работает в приложении.


Обход, который оставляет функциональность Zepto

Эта версия перезаписи cy.visit() оставит библиотеку Zepto функциональной, но позволит Нажмите на .should(), чтобы получить правильный jQuery объект.

По сути, мы добавляем наш собственный прокси (поверх прокси zepto) и проверяем тип селектора при каждом вызове.

Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
  return originalFn(url, options).then(_ => {
    const win = cy.state('window')
    const zepto_$ = win.$;
    win.$ = function(selector, context) {
      return typeof selector === 'string' 
        ? zepto_$(selector, context) 
        : Cypress.$(selector, context);
    }
  })
})

Используйте этот html фрагмент, чтобы проверить его. Если два журнала идентичны, zepto не затрагивается.

<body>
  <h2>dress</h2>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>

  <script>
    console.log('from app, call #1', $('h2'))
    setTimeout(() => {
      console.log('from app, call #2', $('h2'))
    }, 1000)
  </script>

</body>
2 голосов
/ 21 февраля 2020

Мне кажется, что использование .and("contain", "dress") решит вашу проблему.

РЕДАКТИРОВАТЬ:

Я попытался запустить фрагмент, похожий на ваш, на моей машине. Использование should не дало ожидаемых результатов, и я столкнулся с тем же странным поведением jquery. Тем не менее, при использовании then это работает как шарм. $ el и $ el [0] оба возвращают элемент jquery обычно

cy.get("h1.h2:first").then(($el) => {
    cy.log($el)
    cy.log($el[0])
    expect($el).to.have.text('measure')
    expect($el[0]).to.have.text('measure')
})
...