Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Espresso intended is not matching my ACTION_SEND intent

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.

like image 443
Richard Avatar asked Oct 28 '20 15:10

Richard


People also ask

What is explicit intent?

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.

What is intent explain with example?

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.

What is intent filter in android?

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.

What is Android intent in espresso testing?

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.

What is the difference between espresso-intents and Hamcrest matcher?

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.

How do I use espresso test to read contacts?

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.

How do I use espresso-intents with other apps?

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.


1 Answers

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()
    }
like image 135
Skizo-ozᴉʞS Avatar answered Oct 09 '22 02:10

Skizo-ozᴉʞS