react-nativejestjsreact-native-testing-library

Unable to find an element with a testID


I'm building a React Native app. Within my GigsByDay component, there is a TouchableOpacity element which, when pressed, directs the user to a GigDetails screen. I'm trying to test this particular functionality using Jest and React Native Testing Library.

I've written the following test, but have received the error:

Unable to find an element with testID: gigs-today-card

The test is as follows:

describe("gigs by week component", () => {
  let navigation;

  beforeEach(() => {
    navigation = { navigate: jest.fn() };
  });

  test("that when gig listing is pressed on it redirects user to Gig Details page", () => {
    render(<GigsByDay navigation={navigation} />);
    const gigCard = screen.getByTestId("gigs-today-card");
    fireEvent.press(gigCard);
    expect(navigation.navigate).toHaveBeenCalledWith("GigDetails");
  });
});

The element it's testing is as follows:

      <TouchableOpacity
        testID="gigs-today-card"
        style={styles.gigCard}
        onPress={() =>
          navigation.navigate('GigDetails', {
            venue: item.venue,
            gigName: item.gigName,
            blurb: item.blurb,
            isFree: item.isFree,
            image: item.image,
            genre: item.genre,
            dateAndTime: {...item.dateAndTime},
            tickets: item.tickets,
            id:item.id
          })
        }>
        <View style={styles.gigCard_items}>
          <Image
            style={styles.gigCard_items_img}
            source={require('../assets/Icon_Gold_48x48.png')}
          />
          <View>
            <Text style={styles.gigCard_header}>{item.gigName}</Text>
            <Text style={styles.gigCard_details}>{item.venue}</Text>
          </View>
        </View>
      </TouchableOpacity>

I've tried fixing my test as follows, but to no success:

  test("that when gig listing is pressed on it redirects user to Gig Details page", async () => {
    render(<GigsByDay navigation={navigation} />);
    await waitFor(() => {
    expect(screen.getByTestId('gigs-today-card')).toBeTruthy()
})
    const gigCard = screen.getByTestId("gigs-today-card");
    fireEvent.press(gigCard);
    expect(navigation.navigate).toHaveBeenCalledWith("GigDetails");
  });
});

Any suggestions on how to fix this? I also tried assigning the testID to the view within the TouchableOpacity element.

For context, here's the whole GigsByDay component:

import { FC } from 'react';
import { FlatList,TouchableOpacity,StyleSheet,View,Image,Text } from 'react-native'
import { listProps } from '../routes/homeStack';
import { GigObject } from '../routes/homeStack';

type ListScreenNavigationProp = listProps['navigation']

interface Props {
  gigsFromSelectedDate: GigObject[],
  navigation: ListScreenNavigationProp
}

const GigsByDay:FC<Props> = ({ gigsFromSelectedDate, navigation }):JSX.Element => (
  <FlatList
    testID='gigs-today'
    data={gigsFromSelectedDate}
    keyExtractor={item => item.id}
    renderItem={({ item }) => (
      <TouchableOpacity
        testID="gigs-today-card"
        style={styles.gigCard}
        onPress={() =>
          navigation.navigate('GigDetails', {
            venue: item.venue,
            gigName: item.gigName,
            blurb: item.blurb,
            isFree: item.isFree,
            image: item.image,
            genre: item.genre,
            dateAndTime: {...item.dateAndTime},
            tickets: item.tickets,
            id:item.id
          })
        }>
        <View style={styles.gigCard_items}>
          <Image
            style={styles.gigCard_items_img}
            source={require('../assets/Icon_Gold_48x48.png')}
          />
          <View>
            <Text style={styles.gigCard_header}>{item.gigName}</Text>
            <Text style={styles.gigCard_details}>{item.venue}</Text>
          </View>
        </View>
      </TouchableOpacity>
    )}
  />
)

Solution

  • Please pass the gigsFromSelectedDate prop with some mock array data so that the flat list would render its elements based on the array length. Currently, you are not passing it. Please check the code below.

      test('that when gig listing is pressed on it redirects user to Gig Details page', () => {
        const mockData = [{venue: 'some venue', 
                          gigName: 'some gigName, 
                          blurb: 'some blurb',
                          isFree: 'some isFree', 
                          image: 'some image', 
                          genre: 'some genre', 
                          dateAndTime: {}, 
                          tickets: ['some ticket'],
                         id: 'some id'}]
        const screen = render(<GigsByDay navigation={navigation} gigsFromSelectedDate={mockData} />);
        const gigCard = screen.getByTestId('gigs-today-card');
        fireEvent.press(gigCard);
        expect(navigation.navigate).toHaveBeenCalledWith('GigDetails');
      });