Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I test if a prop is passed to child?

My component looks something like this: (It has more functionality as well as columns, but I have not included that to make the example simpler)

const WeatherReport: FunctionComponent<Props> = ({ cityWeatherCollection, loading, rerender }) => {
  /* some use effects skipped */
  /* some event handlers skipped */

  const columns = React.useMemo(() => [
    {
      header: 'City',
      cell: ({ name, title }: EnhancedCityWeather) => <Link to={`/${name}`} className="city">{title}</Link>
    },
    {
      header: 'Temp',
      cell: ({ temperature }: EnhancedCityWeather) => (
        <div className="temperature">
          <span className="celcius">{`${temperature}°C`}</span>
          <span className="fahrenheit">{` (~${Math.round(temperature * (9 / 5)) + 32}°F)`}</span>
        </div>
      )
    },
    {
      header: '',
      cell: ({ isFavorite } : EnhancedCityWeather) => isFavorite && (
        <HeartIcon
          fill="#6d3fdf"
          height={20}
          width={20}
        />
      ),
    },
  ], []);

  return (
    <Table columns={columns} items={sortedItems} loading={loading} />
  );
};

Now, I wrote some tests like this:

jest.mock('../../../components/Table', () => ({
  __esModule: true,
  default: jest.fn(() => <div data-testid="Table" />),
}));

let cityWeatherCollection: EnhancedCityWeather[];
let loading: boolean;
let rerender: () => {};

beforeEach(() => {
  cityWeatherCollection = [/*...some objects...*/];

  loading = true;
  rerender = jest.fn();

  render(
    <BrowserRouter>
      <WeatherReport
        cityWeatherCollection={cityWeatherCollection}
        loading={loading}
        rerender={rerender}
      />
    </BrowserRouter>
  );
});

it('renders a Table', () => {
  expect(screen.queryByTestId('Table')).toBeInTheDocument();
});

it('passes loading prop to Table', () => {
  expect(Table).toHaveBeenCalledWith(
    expect.objectContaining({ loading }),
    expect.anything(),
  );
});

it('passes items prop to Table after sorting by isFavorite and then alphabetically', () => {
  expect(Table).toHaveBeenCalledWith(
    expect.objectContaining({
      items: cityWeatherCollection.sort((item1, item2) => (
        +item2.isFavorite - +item1.isFavorite
        || item1.name.localeCompare(item2.name)
      )),
    }),
    expect.anything(),
  );
});

If you check my component, it has a variable called columns. I am assigning that variable to Table component.

I think, I should test that columns are being passed as props to the Table component. Am I thinking right? If so, can you please tell me how can I write a test case for that?

Also, it will be helpful if you can suggest me how can i test each cell declared inside columns property.

like image 602
Vishal Avatar asked Mar 02 '23 21:03

Vishal


2 Answers

It is not recommended to test implementation details, such as component props, with React Testing Library. Instead you should be asserting on the screen content.


Recommended

expect(await screen.findByText('some city')).toBeInTheDocument();
expect(screen.queryByText('filtered out city')).not.toBeInTheDocument();

Not Recommended

If you want to test props anyways, you can try the sample code below. Source

import Table from './Table'
jest.mock('./Table', () => jest.fn(() => null))

// ... in your test
expect(Table).toHaveBeenCalledWith(props, context)

You might consider this approach mainly on the two following scenarios.

You already tried the recommended approach but you noticed the component is:

  1. using legacy code and because of that it makes testing very hard. Refactoring the component would also take too long or be too risky.
  2. is very slow and it drastically increases the testing time. The component is also already tested somewhere else.

have a look at a very similar question here

like image 167
Doug Avatar answered Mar 15 '23 18:03

Doug


You can use the props() method, doing something like this:

 expect(Table.props().propYouWantToCheck).toBeFalsy();

Just doing your component.props() then the prop you want, you can make any assert with it.

like image 34
Otacílio Maia Avatar answered Mar 15 '23 20:03

Otacílio Maia