I have a Send Feedback in my app's Preferences. It should open a Chooser and a new Intent, to send an email with provided email address, subject and text template. This part simply works both on emulator and physical device:
prefButtonSendFeedback?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val emailIntent = Intent(Intent.ACTION_SENDTO)
emailIntent.type = "text/plain"
emailIntent.data = Uri.parse("mailto:")
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.send_feedback_email_address)))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.send_feedback_email_subject))
emailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.send_feedback_email_content_template))
context?.startActivity(Intent.createChooser(emailIntent, getString(R.string.send_feedback_intent_name)))
true
}
I have also Espresso test for this case:
@Test fun clickOnFeedbackActionMenuItem_StartsFeedbackFragment() {
launchFragmentInContainer<SettingsFragment>()
Intents.init()
intending(
hasAction(Intent.ACTION_CHOOSER)
).respondWith(
ActivityResult(Activity.RESULT_OK, null)
)
// Press on Feedback navigation item
onView(withId(androidx.preference.R.id.recycler_view))
.perform(
actionOnItem<RecyclerView.ViewHolder>(
hasDescendant(withText(R.string.pref_send_feedback)), click()
)
)
val emailIntent = allOf(
hasAction(Intent.ACTION_SENDTO),
hasData(Uri.parse("mailto:")),
hasExtra(Intent.EXTRA_EMAIL, arrayOf(withText(R.string.send_feedback_email_address))),
hasExtra(Intent.EXTRA_SUBJECT, withText(R.string.send_feedback_email_subject)),
hasExtra(Intent.EXTRA_TEXT, withText(R.string.send_feedback_email_content_template))
)
val expectedIntent = allOf(
hasAction(Intent.ACTION_CHOOSER),
hasExtra(equalTo(Intent.EXTRA_INTENT), emailIntent),
hasExtra(equalTo(Intent.EXTRA_TITLE), withText(R.string.send_feedback_intent_name))
)
intended(expectedIntent)
Intents.release()
}
My issue is similar in general to one from How to stub Intent.createChooser Intent using Espresso
- With matchers like in the code I have an error:
androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 0 intents.
IntentMatcher: (has action: is "android.intent.action.CHOOSER" and has extras: has bundle with: key: "android.intent.extra.INTENT" value: (has action: is "android.intent.action.SENDTO" and has data: is <mailto:> and has extras: has bundle with: key: is "android.intent.extra.EMAIL" value: is [<with string from resource id: <3134850762>>] and has extras: has bundle with: key: is "android.intent.extra.SUBJECT" value: is <with string from resource id: <2131820702>> and has extras: has bundle with: key: is "android.intent.extra.TEXT" value: is <with string from resource id: <2131820701>>))
Matched intents:[]
Recorded intents:
-Intent { act=android.intent.action.CHOOSER (has extras) } handling packages:[[android]], extras:[Bundle[{android.intent.extra.INTENT=Intent { act=android.intent.action.SENDTO dat=mailto: (has extras) }, android.intent.extra.TITLE=Send Feedback:}]])
- Test is green, when I have only few Matchers - adding any other fail test:
val emailIntent = allOf(
hasAction(Intent.ACTION_SENDTO),
hasData(Uri.parse("mailto:")),
)
val expectedIntent = allOf(
hasAction(Intent.ACTION_CHOOSER),
hasExtra(equalTo(Intent.EXTRA_INTENT), emailIntent),
)
- I used also a truth assertions and debugger
val receivedIntent: Intent = Iterables.getOnlyElement(Intents.getIntents())
assertThat(receivedIntent).hasAction(Intent.ACTION_CHOOSER) ### here is a breakpoint
It shows me, that my Intent has all Extras I need (subject, address and text) - I removed unnecessary values:
receivedIntent =
(...)
mAction = "android.intent.action.CHOOSER"
(..)
mExtras =
mMap =
value[0] =
mAction = "android.intent.action.SENDTO"
mData = "mailto:"
mExtras =
mMap =
value[0] = "App Feedback"
value[1] = "Add here any bugs, issues or ideas about App"
value[2] =
0 = "info@example.com"
value[1] = "Send Feedback:"
My question is, what is wrong with my Matchers - for me they look ok:
- Chooser has extra Intent and title
- email Intent has email addres, subject and text
Moreover, I am not sure how intending() works - I assume that using it like in my code will not run real Intent during test. So it will not run an email client. I am wrong - it runs, but without it all next test hangs even, if I am using Intents.release().