Ryan
Ryan

Reputation: 1050

How to stub Intent.createChooser Intent using Espresso

Problem

I have an image inside my app, and am sharing it to any other app that can handle image sharing, and the feature is working perectlty.

I am writing an Espresso UI test to intercept the intent and ensure it has the correct action and extras, but cannot seem to get it to work.

Code

Here is the code when creating the intent:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType(MediaType.PNG.toString());
startActivity(Intent.createChooser(intent, "send");

and here is my attempt to match the Intent in my test, but fails to find a match:

Intents.init();
launchActivity(MyFragment.newIntent(getTargetContext());

Matcher<Intent> expectedIntent = allOf(
    hasAction(Intent.ACTION_CHOOSER),
    hasExtra(
        Intent.ACTION_SEND,
        hasExtra(Intent.EXTRA_STREAM, EXPECTED_SHARE_URI) // Expected URI has been copied from the extras 'uriString' value when debugging
    )
);
intending(expectedIntent).respondWith(new Instrumentation.ActivityResult(0, null));
MyScreen.clickShareButton(); // performs click on the share button
intended(expectedIntent);
Intents.release();

Error

IntentMatcher: (has action: is "android.intent.action.CHOOSER" and has extras: has bundle with: key: is "android.intent.extra.STREAM" value: is "[my uri appears here]")

Additional info

When debugging, the intent that is created results in an intent with action "android.intent.action.CHOOSER", and has an extra of type Intent, with action "android.intent.action.SEND" and type "image/png", and in turn has an extra, a HierarchicalUri with a uriString.

Summary

Anyone know what I am doing wrong? I can't find a way to tie all this together and create a matcher for this intent. Any help would be greatly appreciated!

Upvotes: 3

Views: 1847

Answers (2)

SerjantArbuz
SerjantArbuz

Reputation: 1244

For me it was:

fun yourEspressoAction() {
    Intents.init()

    yourEspressoActionClick()

    intended(
        chooser(
            allOf(
                hasAction(Intent.ACTION_SEND),
                hasType(ShareType.Text.Plain.value),
                hasExtra(Intent.EXTRA_TEXT, text)
            )
        )
    )

    Intents.release()
}

/** Matcher for [Intent.createChooser]. */
private fun chooser(matcher: Matcher<Intent>): Matcher<Intent> {
    return Matchers.allOf(
        hasAction(Intent.ACTION_CHOOSER),
        hasExtra(Matchers.`is`(Intent.EXTRA_INTENT), matcher)
    )
}

Found answer here: link

Upvotes: 0

Aaron
Aaron

Reputation: 3894

If you're getting an error on this line intended(expectedIntent) because the intent didn't match, it's probably because Intent.createChooser put your intent as an extra data with the key Intent.EXTRA_INTENT. In your case, you only need an extra intent matcher for the chooser:

Matcher<Intent> intent = allOf(
    hasAction(Intent.ACTION_SEND),
    hasExtra(Intent.EXTRA_STREAM, EXPECTED_SHARE_URI)
);

Matcher<Intent> expectedIntent = allOf(
    hasAction(Intent.ACTION_CHOOSER),
    // Intent.createChooser put your intent with the key EXTRA_INTENT
    hasExtra(Intent.EXTRA_INTENT, intent)
);

intending(anyIntent()).respondWith(new Instrumentation.ActivityResult(0, null));

MyScreen.clickShareButton();

intended(expectedIntent);

Upvotes: 1

Related Questions