1 /* 2 * Copyright (C) 2024 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.systemui.screenshot 18 19 import android.content.Intent 20 import android.net.Uri 21 import android.os.Process 22 import android.os.UserHandle 23 import android.testing.AndroidTestingRunner 24 import androidx.test.filters.SmallTest 25 import com.android.internal.logging.UiEventLogger 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.screenshot.ui.viewmodel.PreviewAction 28 import com.google.common.truth.Truth.assertThat 29 import java.util.UUID 30 import kotlin.test.Test 31 import kotlinx.coroutines.test.runTest 32 import org.junit.Before 33 import org.junit.runner.RunWith 34 import org.mockito.Mockito.verifyNoMoreInteractions 35 import org.mockito.kotlin.any 36 import org.mockito.kotlin.argumentCaptor 37 import org.mockito.kotlin.eq 38 import org.mockito.kotlin.mock 39 import org.mockito.kotlin.never 40 import org.mockito.kotlin.times 41 import org.mockito.kotlin.verify 42 43 @RunWith(AndroidTestingRunner::class) 44 @SmallTest 45 class DefaultScreenshotActionsProviderTest : SysuiTestCase() { 46 private val actionExecutor = mock<ActionExecutor>() 47 private val uiEventLogger = mock<UiEventLogger>() 48 private val actionsCallback = mock<ScreenshotActionsController.ActionsCallback>() 49 50 private val request = ScreenshotData.forTesting() 51 private val validResult = ScreenshotSavedResult(Uri.EMPTY, Process.myUserHandle(), 0) 52 53 private lateinit var actionsProvider: ScreenshotActionsProvider 54 55 @Before setUpnull56 fun setUp() { 57 request.userHandle = UserHandle.OWNER 58 } 59 60 @Test previewActionAccessed_beforeScreenshotCompleted_doesNothingnull61 fun previewActionAccessed_beforeScreenshotCompleted_doesNothing() { 62 actionsProvider = createActionsProvider() 63 64 val previewActionCaptor = argumentCaptor<PreviewAction>() 65 verify(actionsCallback).providePreviewAction(previewActionCaptor.capture()) 66 previewActionCaptor.firstValue.onClick.invoke() 67 verifyNoMoreInteractions(actionExecutor) 68 } 69 70 @Test actionButtonsAccessed_beforeScreenshotCompleted_doesNothingnull71 fun actionButtonsAccessed_beforeScreenshotCompleted_doesNothing() { 72 actionsProvider = createActionsProvider() 73 74 val actionButtonCaptor = argumentCaptor<() -> Unit>() 75 verify(actionsCallback, times(2)) 76 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 77 val firstAction = actionButtonCaptor.firstValue 78 val secondAction = actionButtonCaptor.secondValue 79 firstAction.invoke() 80 secondAction.invoke() 81 verifyNoMoreInteractions(actionExecutor) 82 } 83 84 @Test <lambda>null85 fun actionAccessed_withResult_launchesIntent() = runTest { 86 actionsProvider = createActionsProvider() 87 88 actionsProvider.setCompletedScreenshot(validResult) 89 90 val actionButtonCaptor = argumentCaptor<() -> Unit>() 91 verify(actionsCallback, times(2)) 92 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 93 actionButtonCaptor.firstValue.invoke() 94 95 verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED), eq(0), eq("")) 96 val intentCaptor = argumentCaptor<Intent>() 97 verify(actionExecutor) 98 .startSharedTransition(intentCaptor.capture(), eq(Process.myUserHandle()), eq(false)) 99 assertThat(intentCaptor.firstValue.action).isEqualTo(Intent.ACTION_CHOOSER) 100 } 101 102 @Test <lambda>null103 fun actionAccessed_whilePending_launchesMostRecentAction() = runTest { 104 actionsProvider = createActionsProvider() 105 106 val previewActionCaptor = argumentCaptor<PreviewAction>() 107 verify(actionsCallback).providePreviewAction(previewActionCaptor.capture()) 108 val actionButtonCaptor = argumentCaptor<() -> Unit>() 109 verify(actionsCallback, times(2)) 110 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 111 112 actionButtonCaptor.firstValue.invoke() 113 previewActionCaptor.firstValue.onClick.invoke() 114 actionButtonCaptor.secondValue.invoke() 115 actionsProvider.setCompletedScreenshot(validResult) 116 117 verify(uiEventLogger).log(eq(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED), eq(0), eq("")) 118 val intentCaptor = argumentCaptor<Intent>() 119 verify(actionExecutor) 120 .startSharedTransition(intentCaptor.capture(), eq(Process.myUserHandle()), eq(true)) 121 assertThat(intentCaptor.firstValue.action).isEqualTo(Intent.ACTION_EDIT) 122 } 123 124 @Test <lambda>null125 fun scrollChipClicked_callsOnClick() = runTest { 126 actionsProvider = createActionsProvider() 127 128 val onScrollClick = mock<Runnable>() 129 actionsProvider.onScrollChipReady(onScrollClick) 130 val actionButtonCaptor = argumentCaptor<() -> Unit>() 131 // share, edit, scroll 132 verify(actionsCallback, times(3)) 133 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 134 actionButtonCaptor.thirdValue.invoke() 135 136 verify(onScrollClick).run() 137 } 138 139 @Test <lambda>null140 fun scrollChipClicked_afterInvalidate_doesNothing() = runTest { 141 actionsProvider = createActionsProvider() 142 143 val onScrollClick = mock<Runnable>() 144 actionsProvider.onScrollChipReady(onScrollClick) 145 val actionButtonCaptor = argumentCaptor<() -> Unit>() 146 actionsProvider.onScrollChipInvalidated() 147 // share, edit, scroll 148 verify(actionsCallback, times(3)) 149 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 150 actionButtonCaptor.thirdValue.invoke() 151 152 verify(onScrollClick, never()).run() 153 } 154 155 @Test scrollChipClicked_afterUpdate_runsNewActionnull156 fun scrollChipClicked_afterUpdate_runsNewAction() = runTest { 157 actionsProvider = createActionsProvider() 158 159 val onScrollClick = mock<Runnable>() 160 val onScrollClick2 = mock<Runnable>() 161 162 actionsProvider.onScrollChipReady(onScrollClick) 163 actionsProvider.onScrollChipInvalidated() 164 actionsProvider.onScrollChipReady(onScrollClick2) 165 val actionButtonCaptor = argumentCaptor<() -> Unit>() 166 // share, edit, scroll 167 verify(actionsCallback, times(3)) 168 .provideActionButton(any(), any(), actionButtonCaptor.capture()) 169 actionButtonCaptor.thirdValue.invoke() 170 171 verify(onScrollClick2).run() 172 verify(onScrollClick, never()).run() 173 } 174 createActionsProvidernull175 private fun createActionsProvider(): ScreenshotActionsProvider { 176 return DefaultScreenshotActionsProvider( 177 context, 178 uiEventLogger, 179 UUID.randomUUID(), 180 request, 181 actionExecutor, 182 actionsCallback, 183 ) 184 } 185 } 186