How to unit test function in ImagePicker Expo using React native testing library?

Viewed 605

I have this code below in react-native using expo, which is a button, click on the button will call ImagePicker.requestMediaLibraryPermissionsAsync(), if the permission is granted, then call to ImagePicker.launchImageLibraryAsync() to let user pick the image.

I using React-native-testing-libary.

This code is working fine, but my jest test is keep failing, where it failed I tell below.

Here is my test, first I mock expo-image-picker module with the 2 function mentioned above and their resolved value :

import * as ImagePicker from 'expo-image-picker';

jest.mock('expo-image-picker', () => {
    return {
        requestMediaLibraryPermissionsAsync: jest.fn().mockResolvedValueOnce({
            status: 'granted'
        }), 
        launchImageLibraryAsync: jest.fn().mockResolvedValue({
          cancelled: false, type: 'image', 
          uri: 'abc.jpeg',
          width: '200',
          height: '200'
        })
    }
})

Here is my code for your references:

import * as ImagePicker from 'expo-image-picker';


const requestPermission = async () => {
    
  const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
   if (status !== 'granted') {
       alert('Sorry, we need camera roll permissions to make this work!');
  }else{
       pickImage()
  }
          

}

 const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });

    console.log(result);

    if (!result.cancelled) {
      setImage(result.uri);
    }
  };


<Button title="Pick an image from camera roll" onPress={requestPermission} />

Then here is what I do in my test cases.

it('should pass test case ', () => {

   const {getByTestId, queryByTestId, getByText} = render(<MyComponent />)

   const pickImageButton = getByTestId('add_image')

   // trigger the button 
   fireEvent.press(pickImageButton)

   // request permission, here the resolved value is granted. 
   expect(ImagePicker.requestMediaLibraryPermissionsAsync).toBeCalledTimes(1)// here is pass 
   
      
   // choose from library this should be called 
   expect(ImagePicker.launchImageLibraryAsync).toBeCalledTimes(1) // test keep failing here 

   ... other stuff here     
})

As you can see, in my test cases, it will fires a button then it called to ImagePicker.requestMediaLibraryPermissionsAsync which will resolved status: 'granted' which is same with my code.

Since status:granted, then this function ImagePicker.launchImageLibraryAsync() should be called.

But right now, expect(ImagePicker.requestMediaLibraryPermissionsAsync).toBeCalledTimes(1) is pass, but this line expect(ImagePicker.launchImageLibraryAsync).toBeCalledTimes(1) is not pass.

What I have tried:

I have tried both expect I wrap it inside a waitFor() like this:

// request permission
await waitFor(() => expect(ImagePicker.requestMediaLibraryPermissionsAsync).toBeCalledTimes(1))
      
 // choose from library, this line never called. 
await waitFor(() =>  expect(ImagePicker.launchImageLibraryAsync).toBeCalledTimes(1))

But the error still the same which is launchImageLibraryAsync() never get called.

Question:

  1. What causing launchImageLibraryAsync() not get called? And how to solve this.

  2. I thought of I need to wait for requestMediaLibraryPermissionsAsync to finish resolved, then only launchImageLibraryAsync() will get called. But how can I do that? As you can see I already wrap it with waitFor(), but the error still persist.

0 Answers
Related