Работа с элементами DOM в тестовой библиотеке React?

У меня есть общий вопрос о работе с элементами DOM в библиотеке React Testing.

По сути, у меня есть несколько вложенных компонентов, один из которых создает ссылку React, которая пересылается некоторым дочерним компонентам (код ниже).

Когда он это делает, он затем визуализирует дочерние компоненты и проверяет вложенную ссылку для вызова .getBoundingClientRect() волшебной собственной функции Javascript, которая дает мне позиционирование по x и y, ширину и высоту, а также верхнюю, нижнюю, левую и правую границы. Мне действительно нужна эта информация, потому что я хочу делать с ней другие вещи, не изменяя напрямую DOM (я делаю все свои модификации DOM с помощью setState и позволяю React повторно визуализировать DOM)

В разработке (Chrome), когда я делаю console.log(this.thing_one_ref.current.getBoundingClientRect()), я получаю следующий результат:  введите описание изображения здесь

(вы заметите, что thing_one_ref здесь правильно заполняется после рендеринга моего приложения - не раньше - и выглядит так :)

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

У меня есть простая спецификация для этого кода, который проходит успешно, но, несмотря на то, что он проходит, вывод журнала в тестовой среде выглядит следующим образом:

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

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

// src / App.test.js

import React from 'react';
import { render, wait } from '@testing-library/react';
import App from './App';
test('renders learn react link', async () => {
  const { getByText, getByTestId } = render(<App />);
  const linkElement = getByTestId("app")
  await wait(() => expect(getByText(/A Test of refs/i, linkElement)).toBeInTheDocument());
});

// src / App.js

import React from 'react';
import './App.css';

import styled from 'styled-components'

import ThingOne from './thing_one'
import Container from './container'

const StyledApp = styled.div`
   position: relative;
   height: 100vh;
   width: 100%;
`

function App() {
  return (
    <StyledApp data-testid="app" className="App" style={{position: 'relative'}}>
      <Container />
    </StyledApp>
  );
}

export default App;

// src / container.js

import React from 'react'
import styled from 'styled-components'

import ThingOne from "./thing_one";
const StyledContainer = styled.div`
  display: block;
`

class Container extends React.Component {
  constructor(props) {
    super(props)
    this.thing_one_ref = React.createRef()
    this.state = {
      message: ""
    }
  }

  componentDidMount() {
    setTimeout(() => {
      this.setState({message: "A test of refs"})

      // here's the console.log
      console.log(this.thing_one_ref.current.getBoundingClientRect())
    }, 1000)
  }

  render() {
    const {message} = this.state
    return (
      <StyledContainer>
        {message}
        <ThingOne ref={this.thing_one_ref}/>
      </StyledContainer>
    )
  }
}

export default Container

// src / thing_one.js

import React from 'react'
import styled from 'styled-components'

const StyledThingOne = styled.div`
  display: block;
  width: 100px;
  height: 100px;
  position: relative;
  top: 20%;
  left: 20%;
  border: solid 1px black;
  margin: 20px;
`
const ThingOne = React.forwardRef((props, ref) => (
      <StyledThingOne ref={ref}></StyledThingOne>
));

export default ThingOne

Как заставить тестовую среду вести себя так, как если бы она смонтирована в реальной модели DOM с декартовой плоскостью, которую я могу использовать для тригонометрии и анимации ? У меня есть рабочий код, который зависит от результата getBoundingClientRect(), который выглядит примерно так (как сказано выше, работает в браузере)

DOMRect {x: 225.1875, y: 38, width: 102, height: 102, top: 38, …}

Полный исходный код можно найти здесь:

https://github.com/jasonfb/jest-playground-3


person Jason FB    schedule 16.12.2019    source источник


Ответы (1)


Я не уверен, что это выходит за рамки ваших текущих требований, но вы можете рассмотреть возможность запуска своих тестовых наборов в реальном браузере (в реальной среде DOM), а не в jsdom, который используется Jest для моделирования среды, подобной браузеру, на Node.JS.

Вы можете рассмотреть возможность использования тестовых фреймворков, таких как Selenium и Cypress для проведения тестов в поддерживаемых браузерах, таких как Chrome. Это позволит вам проводить интеграционное тестирование (то, чего вы пытаетесь достичь), а в будущем - сквозное тестирование в браузере. Это избавит от необходимости имитировать / заглушать / моделировать элементы DOM на Node.JS.

person wentjun    schedule 16.12.2019
comment
да, это звучит как хорошее направление для меня. Я (относительно) новичок в экосистеме React, но уже много лет тестирую на других языках. Есть ли способ продолжать писать JS-код (например, Jest) и использовать безголовый или настоящий браузер? (Например, раньше я использовал phantomjs, Selenium с полтергейстом, Webkit и т. Д., Написанные на Ruby) ... Я думаю, что я ищу способ использовать JEST для написания сценария в реальном браузере или, по крайней мере, в браузере без головы. что имитирует DOM более точно? - person Jason FB; 16.12.2019
comment
Думаю, я действительно хочу знать, какие из этих вариантов являются лучшими для приложения React? - person Jason FB; 16.12.2019
comment
это выглядит интересно, но выглядит немного сложным в настройке: medium.com/@mathieux51 / jest-selenium-webdriver-e25604969c6… может быть многообещающим - person Jason FB; 16.12.2019
comment
похоже, что с драйвером селена jest у вас в основном есть доступ к самому объекту драйвера, а затем все ваши спецификации должны быть написаны в формате селена (getElementById, getElementByXPath и т. д.), который я не предпочитаю но это может быть вариант, может быть - person Jason FB; 16.12.2019
comment
@JasonFB: да, когда дело доходит до этого, действительно есть множество вариантов, но если вы ищете простоты, когда дело доходит до интеграции, почему бы не попробовать Cypress? Независимо от того, что вы выберете, и Selenium, и Cypress позволят вам запускать тесты без головы или с помощью самого браузера. - person wentjun; 16.12.2019
comment
большое спасибо. Я сейчас читаю это: blog.bitsrc.io/testing-react -apps-with-cypress-658bc482678 .... быстрый вопрос: есть ли способ показать отчет о покрытии кода с помощью Cypress? В идеале я бы хотел получить все покрытие кода в одном отчете, чтобы я мог написать несколько (базовых) тестов с Jest и использовать Cypress для вещей, требующих более продвинутого тестирования, но все же видеть единичный отчет о покрытии. это показывает, какие линии покрыты, а какие нет. Это возможно? Я предполагаю, что если у Cypress есть собственный отчет о покрытии, он сам покажет мне этот отчет. - person Jason FB; 16.12.2019
comment
@JasonFB Да, как и многие тестовые среды, Cypress поддерживает покрытие кода. Вы можете прочитать об этом здесь! docs.cypress.io/guides/tooling/code-coverage.html# Введение - person wentjun; 16.12.2019