This is first time I am using espresso intents, I followed IntentsBasicSamle provided in the android-testing project but no solved.
In my app I have a activity where user selects multiple images and then returned images are shown in the gridview, Now by using the espresso intents I want to mock this without going to actual image picker and return some specified images everytime.
No error but still opens the image chooser window when I run the test. I feel I am doing it wrong but I am not getting how it works.
I am testing using apk.
This is how photo picker is called
App code
This is how I am calling select images Intent and result is handled in onActivityResult.
if (ApiUtils.checkApiLevel(18)) {
//API18+
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, getActivity().getString(R.string.fragment_image_selection_select_picture)), 1);
Testing Code
@RunWith(AndroidJUnit4.class)
@LargeTest
public class ImagesTests {
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.company.recorder.RecorderActivity";
private static Class<? extends Activity> activityClass;
private ServiceValidatorIdlingResource serviceValidatorIdlingResource;
static {
try {
activityClass = (Class<? extends Activity>) Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* Change espresso default view idling time
* so that test can wait for long time
*/
@Before
public void registerWaitService() {
EspressoSolo.setIdlingResourceTimeout(30);
Instrumentation.ActivityResult result = createImageCaptureActivityResultStub();
// Stub the Intent.
intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result);
//For API 18 and above
intending(hasAction(Intent.EXTRA_ALLOW_MULTIPLE)).respondWith(result);
//intending(not(isInternal())).respondWith(result);
}
private Instrumentation.ActivityResult createImageCaptureActivityResultStub() {
// Put the drawable in a bundle.
Bundle bundle = new Bundle();
Uri imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
InstrumentationRegistry.getTargetContext().getPackageName()+ '/' +
InstrumentationRegistry.getTargetContext().getResources().getResourceTypeName(R.drawable.abc_ic_menu_copy_mtrl_am_alpha) + '/' +
InstrumentationRegistry.getTargetContext().getResources().getResourceEntryName(R.drawable.abc_ic_menu_copy_mtrl_am_alpha) );
Parcelable parcelable = (Parcelable)imageUri;
ArrayList<Parcelable> parcels = new ArrayList<>();
parcels.add(parcelable);
bundle.putParcelableArrayList(Intent.EXTRA_STREAM, parcels);
// Create the Intent that will include the bundle.
Intent resultData = new Intent();
resultData.putExtras(bundle);
// Create the ActivityResult with the Intent.
return new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
}
@Rule
public IntentsTestRule<?> mIntentsRule = new IntentsTestRule<>(
activityClass);
/**
* In this test images are taken during the recording
* add the images taken during the recording through add photos card
* displayed after recording is stopped.
*
* @throws Exception
*/
@Test
public void testAddImagesFromPhotosCard() throws Exception {
onView(withId(Recorder.getId("recorderpage_record"))).perform(click());
Log.d("called", "other package");
IdlingResource idlingResource0 = new RecordingWaitIdlingResource(5000);
Espresso.registerIdlingResources(idlingResource0);
Log.d("called", "other package");
onView(withId(Recorder.getId("card_topText"))).perform(click());
Espresso.unregisterIdlingResources(idlingResource0);
onView(withId(Recorder.getId("recorderpage_stop"))).perform(click());
//Log.d("called", "other package");
IdlingResource idlingResource2 = new RecordingWaitIdlingResource(2000);
Espresso.registerIdlingResources(idlingResource2);
onView(withId(Recorder.getId("recorderpage_statustext")))
.perform(click());
Espresso.unregisterIdlingResources(idlingResource2);
onView(withId(Recorder.getId("pager"))).perform(swipeLeft());
onData(allOf()).onChildView(withId(Recorder.getId("recordsOverflow"))).
atPosition(0).perform(click());
IdlingResource idlingResource3 = new RecordingWaitIdlingResource(2000);
Espresso.registerIdlingResources(idlingResource3);
onData(allOf()).onChildView(withId(Recorder.getId("recordsOverflow"))).
atPosition(0).perform(click());
Espresso.unregisterIdlingResources(idlingResource3);
onView(withText("Add an image")).perform(click());
Instrumentation.ActivityResult result = createImageCaptureActivityResultStub();
intending(toPackage("com.android.documentsui")).respondWith(result);
/* I actually dont know which preinstalled app is opened by intent, I saw this com.android.documentsui, also tried with photos and gallery package names */
intending(toPackage("com.android.documentsui.DocumentsActivity")).respondWith(result);
intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result);
//Now click on add images
onView(withId(Recorder.getId("menu_fragment_imagewizard_selection_add"))).perform(click());
//Just waits for 2seconds
IdlingResource idlingResource4 = new RecordingWaitIdlingResource(2000);
Espresso.registerIdlingResources(idlingResource4);
onView(withText("Add images")).perform(click());
Espresso.unregisterIdlingResources(idlingResource4);
}
}
Finally, This is what worked for me, posting my answer
Bundle bundle = new Bundle();
ArrayList<Parcelable> parcels = new ArrayList<>();
Intent resultData = new Intent();
Uri uri1 = Uri.parse("file://mnt/sdcard/img01.jpg");
Parcelable parcelable1 = (Parcelable) uri1;
parcels.add(parcelable1);
bundle.putParcelableArrayList(Intent.EXTRA_STREAM, parcels);
// Create the Intent that will include the bundle.
resultData.putExtras(bundle);
intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData));
Permissions
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.YOUR_PERMISSION;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With