testing-library / native-testing-library

🐳 Simple and complete React Native testing utilities that encourage good testing practices.
https://native-testing-library.com
MIT License
516 stars 44 forks source link

fireEvent.layout doesn't trigger onLayout for TouchableOpacity #142

Closed colinfwren closed 4 years ago

colinfwren commented 4 years ago

Relevant code or config:

    import { act, render, fireEvent, wait } from '@testing-library/react-native';

    it('Passes with View', async () => {
        const mockOnLayout = jest.fn();
        function MyComponent() {
            return (
                <View onLayout={(e) => mockOnLayout(e)} testID='my-view'>
                    <View style={{ height: 200, width: 200}} />
                </View>
            )
        }
        const { getByTestId } = render(<MyComponent />);
        const view = getByTestId('my-view');
        act(() => {
            fireEvent.layout(view, {
                nativeEvent: {
                    layout: {
                        width: 300,
                    },
                },
            });
        });
        await wait(() => expect(mockOnLayout).toHaveBeenCalled());
    });
    it('Fails with TouchableOpacity', async () => {
        const mockOnLayout = jest.fn();
        function MyComponent() {
            return (
                <TouchableOpacity onLayout={(e) => mockOnLayout(e)} testID='my-view'>
                    <View style={{ height: 200, width: 200}} />
                </TouchableOpacity>
            )
        }
        const { getByTestId } = render(<MyComponent />);
        const view = getByTestId('my-view');
        act(() => {
            fireEvent.layout(view, {
                nativeEvent: {
                    layout: {
                        width: 300,
                    },
                },
            });
        });
        await wait(() => expect(mockOnLayout).toHaveBeenCalled());
    });

What you did:

Tried to test the onLayout functionality of a component that uses TouchableOpacity.

What happened:

Mocked onLayout handler was never called.

I had followed https://stackoverflow.com/questions/57961440/testing-onlayout-in-react-native/61774123#61774123 which suggested that it should work and on testing a View based component like in the example it worked, however on changing the View to TouchableOpacity it no longer worked.

Reproduction:

See attached test cases.

Problem description:

onLayout is a prop supported by TouchableOpacity so it'd be good to be able to verify that my component called it's onLayout handler that I pass to it when a layout event is triggered.

colinfwren commented 4 years ago

I've also noticed that when inspecting the view objects in both examples that the View based object has it's type and elementType properties set to View whereas the TouchableOpacity has both properties set to ''.

Not sure if that will help figure out what's happening or not

daveols commented 4 years ago

Apparently this library is going to be deprecated, but in the meantime this should fix the firing of that handler in your tests:

https://github.com/testing-library/native-testing-library/pull/136#issuecomment-659134430