akveo / react-native-ui-kitten

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/react-native-ui-kitten/
MIT License
10.19k stars 952 forks source link

While testing, if <IconRegistry /> is rendered, fireEvent() returns an error #1499

Open giovanniRodighiero opened 2 years ago

giovanniRodighiero commented 2 years ago

šŸ› Bug Report

While testing with @testing-library/react-native, if inside the rendered component there is <IconRegistry icons={EvaIconsPack} /> (so every time I need to render a component that has an icon), the function fireEvent returns TypeError: Cannot read property 'pointerEvents' of null.

    TypeError: Cannot read property 'pointerEvents' of null

      27 |     expect(getByA11yLabel('backFiveSeconds')).toBeTruthy();
      28 |     expect(getByText('-5s')).toBeTruthy();
    > 29 |     fireEvent(getByA11yLabel('backFiveSeconds'), 'press');
         |     ^
      30 |     expect(spy).toHaveBeenCalled();
      31 |   });
      32 | });

Without IconRegistry it does work as expected.

To Reproduce

Steps to reproduce the behavior:

Code sample:

import React from 'react';
import { render, fireEvent, act } from '@testing-library/react-native';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry, Button, Text } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';

import theme from '../../../uiTheme.json';

describe('<AudioPlayer/>  >  <MainControlsLeft />', () => {
  it('Renders correctly and call the callback fn', async () => {
    const spy = jest.fn();
    const { getByText, getByA11yLabel } = render(
      <>
        <IconRegistry icons={EvaIconsPack} />
        <ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
          <Button
            key="back"
            accessibilityLabel="backFiveSeconds"
            appearance="ghost"
            onPress={spy}
          >
            {(props) => <Text {...props} category="s1" status="basic">-5s</Text>}
          </Button>
        </ApplicationProvider>
      </>
    );
    expect(getByA11yLabel('backFiveSeconds')).toBeTruthy();
    expect(getByText('-5s')).toBeTruthy();
    fireEvent(getByA11yLabel('backFiveSeconds'), 'press'); // => TypeError: Cannot read property 'pointerEvents' of null
    expect(spy).toHaveBeenCalled();
  });
});

Run with jest <filename>.

Expected behavior

I do expect the press event to be fired correctly.

Link to runnable example or repository (highly encouraged)

UI Kitten and Eva version

Package Version
@eva-design/eva 2.1.0
@ui-kitten/eva-icons 5.1.0
@ui-kitten/components 5.1.10
react 17.0.1
@testing-library/react-native 7.2.0
jest 26.6.3

Environment information

  System:
    OS: macOS 11.5.1
    CPU: (8) arm64 Apple M1
  Binaries:
    Node: 15.14.0 - ~/.nvm/versions/node/v15.14.0/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v15.14.0/bin/yarn
    npm: 7.7.6 - ~/.nvm/versions/node/v15.14.0/bin/npm
    Watchman: 2021.06.07.00 - /opt/homebrew/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 14.5, DriverKit 20.4, macOS 11.3, tvOS 14.5, watchOS 7.4
    Android SDK:
      API Levels: 29, 30
      Build Tools: 29.0.2
  IDEs:
    Xcode: 12.5.1/12E507 - /usr/bin/xcodebuild
  npmPackages:
    react: 17.0.1 => 17.0.1
    react-native: 0.64.2 => 0.64.2
firasbou commented 1 year ago

IconRegistry component should be inside ApplicationProvider

import React from 'react';
import { render, fireEvent, act } from '@testing-library/react-native';
import * as eva from '@eva-design/eva';
import { ApplicationProvider, IconRegistry, Button, Text } from '@ui-kitten/components';
import { EvaIconsPack } from '@ui-kitten/eva-icons';

import theme from '../../../uiTheme.json';

describe('<AudioPlayer/>  >  <MainControlsLeft />', () => {
  it('Renders correctly and call the callback fn', async () => {
    const spy = jest.fn();
    const { getByText, getByA11yLabel } = render(
        <ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
          <IconRegistry icons={EvaIconsPack} />
          <Button
            key="back"
            accessibilityLabel="backFiveSeconds"
            appearance="ghost"
            onPress={spy}
          >
            {(props) => <Text {...props} category="s1" status="basic">-5s</Text>}
          </Button>
        </ApplicationProvider>
    );
    expect(getByA11yLabel('backFiveSeconds')).toBeTruthy();
    expect(getByText('-5s')).toBeTruthy();
    fireEvent(getByA11yLabel('backFiveSeconds'), 'press');
    expect(spy).toHaveBeenCalled();
  });
});
flexbox commented 10 months ago

@giovanniRodighiero

If your problem is solved can you please close the issue? It sparks joy for maintainers āœØ