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.widget.ActionRow 27 import com.android.intentresolver.widget.ImagePreviewView 28 import com.google.common.truth.Truth.assertThat 29 import java.util.function.Consumer 30 import kotlin.coroutines.EmptyCoroutineContext 31 import kotlinx.coroutines.flow.MutableSharedFlow 32 import kotlinx.coroutines.test.TestScope 33 import kotlinx.coroutines.test.UnconfinedTestDispatcher 34 import org.junit.Rule 35 import org.junit.Test 36 import org.mockito.Mockito.never 37 import org.mockito.Mockito.times 38 import org.mockito.Mockito.verify 39 import org.mockito.kotlin.mock 40 import org.mockito.kotlin.whenever 41 42 class ChooserContentPreviewUiTest { 43 private val testScope = TestScope(EmptyCoroutineContext + UnconfinedTestDispatcher()) 44 private val previewData = mock<PreviewDataProvider>() 45 private val headlineGenerator = mock<HeadlineGenerator>() 46 private val imageLoader = FakeImageLoader(emptyMap()) 47 private val testMetadataText: CharSequence = "Test metadata text" 48 private val actionFactory = 49 object : ActionFactory { getCopyButtonRunnablenull50 override fun getCopyButtonRunnable(): Runnable? = null 51 52 override fun getEditButtonRunnable(): Runnable? = null 53 54 override fun createCustomActions(): List<ActionRow.Action> = emptyList() 55 56 override fun getModifyShareAction(): ActionRow.Action? = null 57 58 override fun getExcludeSharedTextAction(): Consumer<Boolean> = Consumer<Boolean> {} 59 } 60 private val transitionCallback = mock<ImagePreviewView.TransitionElementStatusCallback>() 61 @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() 62 createContentPreviewUinull63 private fun createContentPreviewUi( 64 targetIntent: Intent, 65 isPayloadTogglingEnabled: Boolean = false 66 ) = 67 ChooserContentPreviewUi( 68 testScope, 69 previewData, 70 targetIntent, 71 imageLoader, 72 actionFactory, 73 { null }, 74 transitionCallback, 75 headlineGenerator, 76 ContentTypeHint.NONE, 77 testMetadataText, 78 isPayloadTogglingEnabled, 79 ) 80 81 @Test test_textPreviewType_useTextPreviewUinull82 fun test_textPreviewType_useTextPreviewUi() { 83 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_TEXT) 84 val testSubject = createContentPreviewUi(targetIntent = Intent(Intent.ACTION_VIEW)) 85 86 assertThat(testSubject.preferredContentPreview) 87 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_TEXT) 88 assertThat(testSubject.mContentPreviewUi).isInstanceOf(TextContentPreviewUi::class.java) 89 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 90 } 91 92 @Test test_filePreviewType_useFilePreviewUinull93 fun test_filePreviewType_useFilePreviewUi() { 94 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_FILE) 95 val testSubject = createContentPreviewUi(targetIntent = Intent(Intent.ACTION_SEND)) 96 assertThat(testSubject.preferredContentPreview) 97 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_FILE) 98 assertThat(testSubject.mContentPreviewUi).isInstanceOf(FileContentPreviewUi::class.java) 99 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 100 } 101 102 @Test test_imagePreviewTypeWithText_useFilePlusTextPreviewUinull103 fun test_imagePreviewTypeWithText_useFilePlusTextPreviewUi() { 104 val uri = Uri.parse("content://org.pkg.app/img.png") 105 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 106 whenever(previewData.uriCount).thenReturn(2) 107 whenever(previewData.firstFileInfo) 108 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 109 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 110 val testSubject = 111 createContentPreviewUi( 112 targetIntent = 113 Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_TEXT, "Shared text") } 114 ) 115 assertThat(testSubject.mContentPreviewUi) 116 .isInstanceOf(FilesPlusTextContentPreviewUi::class.java) 117 verify(previewData, times(1)).imagePreviewFileInfoFlow 118 verify(transitionCallback, times(1)).onAllTransitionElementsReady() 119 } 120 121 @Test test_imagePreviewTypeWithoutText_useImagePreviewUinull122 fun test_imagePreviewTypeWithoutText_useImagePreviewUi() { 123 val uri = Uri.parse("content://org.pkg.app/img.png") 124 whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 125 whenever(previewData.uriCount).thenReturn(2) 126 whenever(previewData.firstFileInfo) 127 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 128 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 129 val testSubject = createContentPreviewUi(targetIntent = Intent(Intent.ACTION_SEND)) 130 assertThat(testSubject.preferredContentPreview) 131 .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_IMAGE) 132 assertThat(testSubject.mContentPreviewUi).isInstanceOf(UnifiedContentPreviewUi::class.java) 133 verify(previewData, times(1)).imagePreviewFileInfoFlow 134 verify(transitionCallback, never()).onAllTransitionElementsReady() 135 } 136 137 @Test test_imagePayloadSelectionTypeWithEnabledFlag_usePayloadSelectionPreviewUinull138 fun test_imagePayloadSelectionTypeWithEnabledFlag_usePayloadSelectionPreviewUi() { 139 // Event if we returned wrong type due to a bug, we should not use payload selection UI 140 val uri = Uri.parse("content://org.pkg.app/img.png") 141 whenever(previewData.previewType) 142 .thenReturn(ContentPreviewType.CONTENT_PREVIEW_PAYLOAD_SELECTION) 143 whenever(previewData.uriCount).thenReturn(2) 144 whenever(previewData.firstFileInfo) 145 .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) 146 whenever(previewData.imagePreviewFileInfoFlow).thenReturn(MutableSharedFlow()) 147 val testSubject = 148 createContentPreviewUi( 149 targetIntent = Intent(Intent.ACTION_SEND), 150 isPayloadTogglingEnabled = true 151 ) 152 assertThat(testSubject.mContentPreviewUi) 153 .isInstanceOf(ShareouselContentPreviewUi::class.java) 154 } 155 } 156