在React Native中测试onLayout

时间:2019-09-16 17:05:33

标签: react-native react-testing-library

我正在尝试使用@ testing-library / react-native测试使用onLayout事件的组件,并通过组件props使用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))
})

3 个答案:

答案 0 :(得分:4)

@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事件处理程序。

答案 1 :(得分:0)

wrapper.find('Wrapper').simulate('layout')

答案 2 :(得分:0)

对于以后需要此服务的人,您可以使用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
});