I have an intent from an activity that I created like so:
private fun startShareIntent() {
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "Watch ${viewmodel.movie.value?.title} with me!\n\n${viewmodel.movie.value?.summary}")
type="text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)
}
That function is run when I click on an icon on the toolbar. I want to run an Espresso UI test on it to check if the activity started is indeed of the above intent. To do that, I'm just checking first if the intent is actually the above intent like so:
@Test
fun test_clicking_share_icon_shows_sharing_sheet() {
val scenario = activityScenarioRule.scenario
Intents.init()
val expectedIntent = allOf(
hasAction(Intent.ACTION_SEND),
hasExtra(Intent.EXTRA_TEXT, "Watch ${dummyMovieData.title} with me!\n\n${dummyMovieData.summary}"),
hasType("text/plain")
)
onView(withText(dummyMovieData.title)).perform(click())
onView(withId(R.id.share_detail)).perform(click())
intended(expectedIntent)
Intents.release()
}
However, this returns me an AssertionFailedError
:
junit.framework.AssertionFailedError: Wanted to match 1 intents. Actually matched 0 intents.
IntentMatcher: (has action: is "android.intent.action.SEND" and has extras: has bundle with: key: is "android.intent.extra.TEXT" value: is "Watch Enola Holmes with me!\n\nWhile searching for her missing mother, intrepid teen Enola Holmes uses her sleuthing skills to outsmart big brother Sherlock and help a runaway lord." and has type: is "text/plain")
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.SEND typ=text/plain flg=0x1 clip={text/plain T:Watch Enola Holmes with me!
While searching for her missing mother, intrepid teen Enola Holmes uses her sleuthing skills to outsmart big brother Sherlock and help a runaway lord.} (has extras) }}]])
How can I make it so that the test can match the intent? It seems from the error message the two are already the same.
An explicit intent is one that you use to launch a specific app component, such as a particular activity or service in your app. To create an explicit intent, define the component name for the Intent object—all other intent properties are optional.
An intent is to perform an action on the screen. It is mostly used to start activity, send broadcast receiver,start services and send message between two activities. There are two intents available in android as Implicit Intents and Explicit Intents. Here is a sample example to start new activity with old activity.
An intent filter declares the capabilities of its parent component — what an activity or service can do and what types of broadcasts a receiver can handle. It opens the component to receiving intents of the advertised type, while filtering out those that are not meaningful for the component.
Android Intent is used to open new activity, either internal (opening a product detail screen from product list screen) or external (like opening a dialer to make a call). Internal intent activity is handled transparently by the espresso testing framework and it does not need any specific work from the user side.
Both take a Hamcrest Matcher<Intent> object as an argument. The following code snippet shows intent validation that uses existing intent matchers that matches an outgoing intent that starts a browser: Espresso-Intents records all intents that attempt to launch activities from the application under test.
GrantPermissionRule allows the espresso test to read contacts. validatePickContactIntent finds the contact_select button and clicks it. Since intents were initialized before this test began, all outgoing intents will be recorded including our ACTION_PICK intent.
If your app delegates functionality to other apps or the platform, you can use Espresso-Intents to focus on your own app's logic while assuming that other apps or the platform will function correctly. With Espresso-Intents, you can match and validate your outgoing intents or even provide stub responses in place of actual intent responses.
The problem is that you need to add a CHOOSER
as :
fun chooser(matcher: Matcher<Intent>): Matcher<Intent> {
return allOf(
hasAction(Intent.ACTION_CHOOSER),
hasExtra(`is`(Intent.EXTRA_INTENT), matcher))
}
And then you can do :
intended(chooser(expectedIntent))
Create a variable like this one to match with your Intent
private val expectedIntent = Matchers.allOf(
IntentMatchers.hasAction(Intent.ACTION_SEND),
IntentMatchers.hasExtra("Your key", "Watch ${dummyMovieData.title} with me!\n\n${dummyMovieData.summary}"),
IntentMatchers.hasType("text/plain")
)
Then change your test to :
@Test
fun test_clicking_share_icon_shows_sharing_sheet() {
Intents.init()
onView(withText(dummyMovieData.title)).perform(click())
onView(withId(R.id.share_detail)).perform(click())
intended(expectedIntent)
Intents.release()
}
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