1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.intentresolver.contentpreview 18 19 import android.content.Intent 20 import android.net.Uri 21 import android.platform.test.flag.junit.CheckFlagsRule 22 import android.platform.test.flag.junit.DeviceFlagsValueProvider 23 import com.android.intentresolver.ContentTypeHint 24 import com.android.intentresolver.FakeImageLoader 25 import com.android.intentresolver.contentpreview.ChooserContentPreviewUi.ActionFactory 26 import com.android.intentresolver.data.model.ChooserRequest 27 import com.android.intentresolver.widget.ActionRow 28 import com.android.intentresolver.widget.ImagePreviewView 29 import com.google.common.truth.Truth.assertThat 30 import java.util.function.Consumer 31 import kotlin.coroutines.EmptyCoroutineContext 32 import kotlinx.coroutines.flow.MutableSharedFlow 33 import kotlinx.coroutines.test.TestScope 34 import kotlinx.coroutines.test.UnconfinedTestDispatcher 35 import org.junit.Rule 36 import org.junit.Test 37 import org.mockito.Mockito.never 38 import org.mockito.Mockito.times 39 import org.mockito.Mockito.verify 40 import org.mockito.kotlin.mock 41 import org.mockito.kotlin.whenever 42 43 class ChooserContentPreviewUiTest { 44 private val testScope = TestScope(EmptyCoroutineContext + UnconfinedTestDispatcher()) 45 private val previewData = mock<PreviewDataProvider>() 46 private val headlineGenerator = mock<HeadlineGenerator>() 47 private val imageLoader = FakeImageLoader(emptyMap()) 48 private val testMetadataText: CharSequence = "Test metadata text" 49 private val actionFactory = 50 object : ActionFactory { getCopyButtonRunnablenull51 override fun getCopyButtonRunnable(): Runnable? = null 52 53 override fun getEditButtonRunnable(): Runnable? = null 54 55 override fun createCustomActions(): List<ActionRow.Action> = emptyList() 56 57 override fun getModifyShareAction(): ActionRow.Action? = null 58 59 override fun getExcludeSharedTextAction(): Consumer<Boolean> = Consumer<Boolean> {} 60 } 61 private val transitionCallback = mock<ImagePreviewView.TransitionElementStatusCallback>() 62 @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() 63 createContentPreviewUinull64 private fun createContentPreviewUi(action: String, sharedText: CharSequence? = null) = 65 ChooserContentPreviewUi( 66 testScope, 67 previewData, 68 ChooserRequest( 69 targetIntent = Intent(action), 70 sharedText = sharedText, 71 launchedFromPackage = "org.pkg", 72 ), 73 imageLoader, 74 actionFactory, 75 { null }, 76 transitionCallback, 77 headlineGenerator, 78 ContentTypeHint.NONE, 79 testMetadataText, 80 ) 81 82 @Test test_textPreviewType_useTextPreviewUinull83 fun test_textPreviewType_useTextPreviewUi() { 84 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_TEXT) 85 val testSubject = createContentPreviewUi(action = Intent.ACTION_VIEW) 86 87 assertThat(testSubject.preferredContentPreview) 88 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_TEXT) 89 assertThat(testSubject.mContentPreviewUi).isInstanceOf(TextContentPreviewUi::class.java) 90 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 91 } 92 93 @Test test_filePreviewType_useFilePreviewUinull94 fun test_filePreviewType_useFilePreviewUi() { 95 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_FILE) 96 val testSubject = createContentPreviewUi(action = Intent.ACTION_SEND) 97 assertThat(testSubject.preferredContentPreview) 98 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_FILE) 99 assertThat(testSubject.mContentPreviewUi).isInstanceOf(FileContentPreviewUi::class.java) 100 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 101 } 102 103 @Test test_imagePreviewTypeWithText_useFilePlusTextPreviewUinull104 fun test_imagePreviewTypeWithText_useFilePlusTextPreviewUi() { 105 val uri = Uri.parse("content://org.pkg.app/img.png") 106 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 107 whenever(previewData.uriCount).thenReturn(2) 108 whenever(previewData.firstFileInfo) 109 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 110 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 111 val testSubject = 112 createContentPreviewUi(action = Intent.ACTION_SEND, sharedText = "Shared text") 113 assertThat(testSubject.mContentPreviewUi) 114 .isInstanceOf(FilesPlusTextContentPreviewUi::class.java) 115 verify(previewData, times(1)).imagePreviewFileInfoFlow 116 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 117 } 118 119 @Test test_imagePreviewTypeWithoutText_useImagePreviewUinull120 fun test_imagePreviewTypeWithoutText_useImagePreviewUi() { 121 val uri = Uri.parse("content://org.pkg.app/img.png") 122 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 123 whenever(previewData.uriCount).thenReturn(2) 124 whenever(previewData.firstFileInfo) 125 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 126 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 127 val testSubject = createContentPreviewUi(action = Intent.ACTION_SEND) 128 assertThat(testSubject.preferredContentPreview) 129 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 130 assertThat(testSubject.mContentPreviewUi).isInstanceOf(UnifiedContentPreviewUi::class.java) 131 verify(previewData, times(1)).imagePreviewFileInfoFlow 132 verify(transitionCallback, never()).onAllTransitionElementsReady() 133 } 134 135 @Test test_imagePayloadSelectionTypeWithEnabledFlag_usePayloadSelectionPreviewUinull136 fun test_imagePayloadSelectionTypeWithEnabledFlag_usePayloadSelectionPreviewUi() { 137 // Event if we returned wrong type due to a bug, we should not use payload selection UI 138 val uri = Uri.parse("content://org.pkg.app/img.png") 139 whenever(previewData.previewType) 140 .thenReturn(ContentPreviewType.CONTENT_PREVIEW_PAYLOAD_SELECTION) 141 whenever(previewData.uriCount).thenReturn(2) 142 whenever(previewData.firstFileInfo) 143 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 144 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 145 val testSubject = createContentPreviewUi(action = Intent.ACTION_SEND) 146 assertThat(testSubject.mContentPreviewUi) 147 .isInstanceOf(ShareouselContentPreviewUi::class.java) 148 assertThat(testSubject.preferredContentPreview) 149 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_PAYLOAD_SELECTION) 150 } 151 } 152