2

我有一个关于在 React 测试库中使用 DOM 元素的一般性问题。

本质上,我有几个嵌套组件,其中一个创建了一个 React ref,它被转发到一些子组件(下面的代码)。

当它这样做时,它会渲染子组件并检查嵌套的 Ref 以调用.getBoundingClientRect()一个神奇的原生 Javascript 函数,该函数为我提供 x 和 y 定位、宽度和高度以及顶部、底部、左侧和右侧边界。我真的需要这些信息,因为我想用它做一些其他事情,而不直接修改 DOM(我正在使用 setState 进行所有 DOM 修改并让 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

4

1 回答 1

1

我不确定这是否超出了您当前的要求,但您可以考虑在实际浏览器(真正的 DOM 环境)上运行您的测试套件,而不是jsdom,Jest 使用它在 Node.JS 上模拟类似浏览器的环境.

您可以考虑使用SeleniumCypress等测试框架在 Chrome 等受支持的浏览器上进行测试。这将允许您执行集成测试(您想要实现的目标),以及将来在浏览器上进行端到端测试。这将消除在 Node.JS 上模拟/存根/模拟 DOM 元素的需要。

于 2019-12-16T17:05:07.043 回答