skip to Main Content

Test Case:

it("Test Email text by test id" , () => {
const testIDName='email-title';
const {getByTestId} = render(
 <Provider store={store}>
<NavigationContainer><Login /></NavigationContainer>
</Provider>);
const foundID=getByTestId(testIDName);
expect(foundID).toBeDefined();
})

Element Structure:

<Text testID= {'email-title'} style={styles.emailText}>Email</Text>

Error Being Thrown:

Unable to find an element with testID: email-title
  63 |     <NavigationContainer><Login /></NavigationContainer>
  64 |     </Provider>);
> 65 |     const foundID=getByTestId(testIDName);
     |                   ^
  66 |     expect(foundID).toBeDefined();
  67 | })
  68 |

Libraries utilised :
– testing-library/react-native

I’m new to unit testing react native component, and not sure why element is not recognising the test ID.
Any Help would be appreciated at this point

2

Answers


  1. you need to mock the provider and that navigation:

    before the describe do this:

    const mockedNavigation = jest.fn();
    
    jest.mock('@react-navigation/native', () => {
      return {
        useNavigation: () => ({
          navigate: mockedNavigation,
        }),
      };
    });
    
    const store = jest.fn()
    
    describe('Login', () => {
     it('should render the email title', () => {
        const {getByTestId}= render(
          <Provider value={{ store }}>
            <Login />
          </Provider>
        ));
        expect(getByTestId('email-title')).toBeTruthy();
      });
    
    })
    

    On the TSX file :

     const Login () =>{
     return ( 
      <View> 
        <Text testID= {'email-title'} style={styles.emailText}>Email</Text> 
     </View>
     )
    }
    
    Login or Signup to reply.
  2. I think @Rodrigo Dias has the right approach. I think some additional improvements can be made:

    1. don’t use jest.fn() to mock your store (not sure if it would work, but I think it’s better to test with an actual store than a mock function), instead export the function that creates your actual store from store.ts and call that in every test. This way you have a clean store that’s identical to your store in production for every test.

    in store.ts:

    export const createStore = () => {
      return configureStore({
        //reducers
        //middleware
      })
    }
    
    1. I’d prefer using toBeVisible over toBeTruthy, because that is more strict. It requires elements to be visible, rather then just exist, which I assume is what you want.

    2. Also, don’t use desctructering for the getByTestId. Instead you can use screen, which automticaly has all the query functions on it for the latest render:

    import {render, screen} from '@testing-library/react-native';
    import {createStore} from '../../redux/store';
    
     it('should render the email title', () => {
        render(
          <Provider store={createStore()}>
            <Login />
          </Provider>
        ));
        expect(screen.getByTestId('email-title')).toBeTruthy();
    });
    
    1. there is a plugin "eslint-plugin-testing-library": "^5.11.0", that enforces some of these best practices, which I recomend installing.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search