Loading legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt 0 → 100644 +142 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.messageview import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageInfo import android.content.pm.ProviderInfo import androidx.core.net.toUri import androidx.test.core.app.ApplicationProvider import app.k9mail.core.android.testing.RobolectricTest import assertk.all import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.prop import com.fsck.k9.provider.AttachmentTempFileProvider import kotlin.test.Test import org.junit.Before import org.robolectric.Robolectric import org.robolectric.Shadows.shadowOf class ViewIntentFinderTest : RobolectricTest() { private val context = ApplicationProvider.getApplicationContext<Context>() private val attachmentTempFileProviderAuthority = "${context.packageName}.tempfileprovider" private val viewIntentFinder = ViewIntentFinder(context) @Before fun setUp() { // The AttachmentTempFileProvider methods called by ViewIntentFinder require the AUTHORITY property to be // set. The most robust way to accomplish this is to properly initialize the content provider. initializeAttachmentTempFileProvider() } @Test fun `provided non-default content type should be preferred`() { addViewerAppFor(mimeType = "application/pdf") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/pdf" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Fpdf".toUri(), ) prop(Intent::getType).isEqualTo("application/pdf") } } @Test fun `inferred content type should be preferred over provided default content type`() { addViewerAppFor(mimeType = "application/pdf") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/octet-stream" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Fpdf".toUri(), ) prop(Intent::getType).isEqualTo("application/pdf") } } @Test fun `inferred content type should be used when no app is installed for provided content type`() { addViewerAppFor(mimeType = "text/plain") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.txt" val mimeType = "text/fancy-format" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=text%2Fplain".toUri(), ) prop(Intent::getType).isEqualTo("text/plain") } } @Test fun `fall back to default content type when no app is installed for provided content type`() { addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/pdf" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Foctet-stream".toUri(), ) prop(Intent::getType).isEqualTo("application/octet-stream") } } private fun initializeAttachmentTempFileProvider() { val info = ProviderInfo().apply { authority = attachmentTempFileProviderAuthority grantUriPermissions = true } Robolectric.buildContentProvider(AttachmentTempFileProvider::class.java).create(info) } private var packageCounter = 1 private fun addViewerAppFor(mimeType: String) { val viewerPackageName = "test.viewerapp.$packageCounter" val viewerActivityName = "$viewerPackageName.activity" packageCounter++ val packageManager = shadowOf(context.packageManager) packageManager.installPackage( PackageInfo().apply { packageName = viewerPackageName }, ) val viewerActivityComponentName = ComponentName(viewerPackageName, viewerActivityName) packageManager.addActivityIfNotPresent(viewerActivityComponentName) val intentFilter = IntentFilter(Intent.ACTION_VIEW).apply { addDataType(mimeType) addDataScheme("content") addCategory(Intent.CATEGORY_DEFAULT) } packageManager.addIntentFilterForActivity(viewerActivityComponentName, intentFilter) } } Loading
legacy/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/ViewIntentFinderTest.kt 0 → 100644 +142 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.messageview import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageInfo import android.content.pm.ProviderInfo import androidx.core.net.toUri import androidx.test.core.app.ApplicationProvider import app.k9mail.core.android.testing.RobolectricTest import assertk.all import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.prop import com.fsck.k9.provider.AttachmentTempFileProvider import kotlin.test.Test import org.junit.Before import org.robolectric.Robolectric import org.robolectric.Shadows.shadowOf class ViewIntentFinderTest : RobolectricTest() { private val context = ApplicationProvider.getApplicationContext<Context>() private val attachmentTempFileProviderAuthority = "${context.packageName}.tempfileprovider" private val viewIntentFinder = ViewIntentFinder(context) @Before fun setUp() { // The AttachmentTempFileProvider methods called by ViewIntentFinder require the AUTHORITY property to be // set. The most robust way to accomplish this is to properly initialize the content provider. initializeAttachmentTempFileProvider() } @Test fun `provided non-default content type should be preferred`() { addViewerAppFor(mimeType = "application/pdf") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/pdf" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Fpdf".toUri(), ) prop(Intent::getType).isEqualTo("application/pdf") } } @Test fun `inferred content type should be preferred over provided default content type`() { addViewerAppFor(mimeType = "application/pdf") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/octet-stream" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Fpdf".toUri(), ) prop(Intent::getType).isEqualTo("application/pdf") } } @Test fun `inferred content type should be used when no app is installed for provided content type`() { addViewerAppFor(mimeType = "text/plain") addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.txt" val mimeType = "text/fancy-format" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=text%2Fplain".toUri(), ) prop(Intent::getType).isEqualTo("text/plain") } } @Test fun `fall back to default content type when no app is installed for provided content type`() { addViewerAppFor(mimeType = "application/octet-stream") val contentUri = "content://$attachmentTempFileProviderAuthority/id".toUri() val displayName = "document.pdf" val mimeType = "application/pdf" val result = viewIntentFinder.getBestViewIntent(contentUri, displayName, mimeType) assertThat(result).all { prop(Intent::getAction).isEqualTo(Intent.ACTION_VIEW) prop(Intent::getData).isEqualTo( "content://$attachmentTempFileProviderAuthority/id?mime_type=application%2Foctet-stream".toUri(), ) prop(Intent::getType).isEqualTo("application/octet-stream") } } private fun initializeAttachmentTempFileProvider() { val info = ProviderInfo().apply { authority = attachmentTempFileProviderAuthority grantUriPermissions = true } Robolectric.buildContentProvider(AttachmentTempFileProvider::class.java).create(info) } private var packageCounter = 1 private fun addViewerAppFor(mimeType: String) { val viewerPackageName = "test.viewerapp.$packageCounter" val viewerActivityName = "$viewerPackageName.activity" packageCounter++ val packageManager = shadowOf(context.packageManager) packageManager.installPackage( PackageInfo().apply { packageName = viewerPackageName }, ) val viewerActivityComponentName = ComponentName(viewerPackageName, viewerActivityName) packageManager.addActivityIfNotPresent(viewerActivityComponentName) val intentFilter = IntentFilter(Intent.ACTION_VIEW).apply { addDataType(mimeType) addDataScheme("content") addCategory(Intent.CATEGORY_DEFAULT) } packageManager.addIntentFilterForActivity(viewerActivityComponentName, intentFilter) } }