【问题标题】:Testing onLayout in React Native在 React Native 中测试 onLayout
【发布时间】:2020-01-17 13:29:12
【问题描述】:

我正在尝试使用@testing-library/react-native 测试使用 onLayout 事件的组件,该组件通过组件道具使用 setState 函数,但该函数从未被调用:

expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: 100

Number of calls: 0

我怎样才能做到这一点?怎么了?

组件:

type Props = {
  children: React.ReactNode
  setHeaderHeight: React.Dispatch<React.SetStateAction<number>>
}

const HeaderSetHeightWrapper = ({ children, setHeaderHeight }: Props) => {
  return (
    <Wrapper
      onLayout={({
        nativeEvent: {
          layout: { height }
        }
      }) => {
        setHeaderHeight(Math.floor(height))
      }}
      testID="header-h"
    >
      {children}
    </Wrapper>
  )
}

const Wrapper = styled.View`
  position: absolute;
  left: 0;
  top: 0;
`

测试:

it('should set the header height on layout', async () => {
  const mockHeight = 100

  const setHeaderHeight = jest.fn()

  const { getByTestId } = render(
    <HeaderSetHeightWrapper setHeaderHeight={setHeaderHeight}>
      <View style={{ width: 100, height: mockHeight }} />
    </HeaderSetHeightWrapper>
  )

  const wrapper = getByTestId('header-h')

  fireEvent(wrapper, new NativeTestEvent('onLayout', { nativeEvent: { layout: { height: mockHeight } } }))

  await wait(() => expect(setHeaderHeight).toHaveBeenCalledWith(mockHeight))
})

【问题讨论】:

    标签: react-native react-testing-library


    【解决方案1】:

    以后有需要的可以使用fireEvent(element, eventName, data),它的文档是here,它的类型是:

    type FireEventFunction = (
      element: ReactTestInstance,
      eventName: string,
      ...data: Array<any>
    ) => any;
    

    因此,要触发 onLayout,请使用 layout 事件名称:

    // You can use any getBy* or another selector that returns a ReactTestInstance
    fireEvent(getByText('Some label'), 'layout', {
      nativeEvent: { layout: { height: 100 } },  // The event data you need
    });
    

    【讨论】:

      【解决方案2】:

      @testing-library/react-native 现在有一个fireEvent.layout 触发器,至少从 v5.0.3 开始:

      import { render, act, fireEvent } from '@testing-library/react-native';
      
      test(() => {
        const { getByTestId } = render(<MyComponent />);
        const view = getByTestId('my-view');
        act(() => {
          fireEvent.layout(view, {
            nativeEvent: {
              layout: {
                width: 300,
                // etc
              },
            },
          });
        });
      });
      

      这应该会触发onLayout 事件处理程序。

      【讨论】:

      • 感谢您的回答!是否有进一步的文档列出了可以触发的 React Native 事件?
      • 你指的是nativeEvent参数吗?这就是真正的布局事件所包含的内容,所以我正在复制它。
      • 我遇到的一个问题是fireEvent.layout 似乎不会为TouchableOpacity 元素触发onLayout,但它确实适用于View。
      • hmm,我一定是做错了,我在8版本上找不到layout:_reactNative.fireEvent.layout is not a function
      【解决方案3】:
      wrapper.find('Wrapper').simulate('layout')
      

      【讨论】:

      • 这个问题是关于使用@testing-library/react-native,而不是Enzyme。
      猜你喜欢
      • 2019-11-06
      • 2019-01-18
      • 2020-07-08
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2023-04-11
      相关资源
      最近更新 更多