diff options
| author | 2023-01-10 22:18:22 +0000 | |
|---|---|---|
| committer | 2023-01-10 22:18:22 +0000 | |
| commit | 9839aa762eb456254e55cf9f1852452a5c841112 (patch) | |
| tree | 345483302a9f06a278f91cd9d200ed1dba1abd2f /java/tests/src | |
| parent | 49b65f54be53ec48d53a550e783759100e8812dc (diff) | |
| parent | a9a6a1c4494529fe2a8e1672d7f6c56aca978743 (diff) | |
Merge "EnterTransitionAnimationDelegate to track animation hold timeout" into tm-qpr-dev
Diffstat (limited to 'java/tests/src')
4 files changed, 185 insertions, 7 deletions
diff --git a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java index 97de97f5..6bc5e12a 100644 --- a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java +++ b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java @@ -30,10 +30,8 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.database.Cursor; -import android.graphics.Bitmap; import android.net.Uri; import android.os.UserHandle; -import android.util.Size; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.MyUserIdProvider; @@ -208,11 +206,10 @@ public class ChooserWrapperActivity } @Override - protected Bitmap loadThumbnail(Uri uri, Size size) { - if (sOverrides.previewThumbnail != null) { - return sOverrides.previewThumbnail; - } - return super.loadThumbnail(uri, size); + protected ImageLoader createPreviewImageLoader() { + return new TestPreviewImageLoader( + super.createPreviewImageLoader(), + () -> sOverrides.previewThumbnail); } @Override diff --git a/java/tests/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt b/java/tests/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt new file mode 100644 index 00000000..ffe89400 --- /dev/null +++ b/java/tests/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver + +import android.content.res.Resources +import android.view.View +import android.view.Window +import androidx.activity.ComponentActivity +import androidx.lifecycle.Lifecycle +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestCoroutineScheduler +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +private const val TIMEOUT_MS = 200 + +@OptIn(ExperimentalCoroutinesApi::class) +class EnterTransitionAnimationDelegateTest { + private val scheduler = TestCoroutineScheduler() + private val dispatcher = StandardTestDispatcher(scheduler) + private val lifecycleOwner = TestLifecycleOwner() + + private val transitionTargetView = mock<View> { + // avoid the request-layout path in the delegate + whenever(isInLayout).thenReturn(true) + } + + private val windowMock = mock<Window>() + private val resourcesMock = mock<Resources> { + whenever(getInteger(anyInt())).thenReturn(TIMEOUT_MS) + } + private val activity = mock<ComponentActivity> { + whenever(lifecycle).thenReturn(lifecycleOwner.lifecycle) + whenever(resources).thenReturn(resourcesMock) + whenever(isActivityTransitionRunning).thenReturn(true) + whenever(window).thenReturn(windowMock) + } + + private val testSubject = EnterTransitionAnimationDelegate(activity) { + transitionTargetView + } + + @Before + fun setup() { + Dispatchers.setMain(dispatcher) + lifecycleOwner.state = Lifecycle.State.CREATED + } + + @After + fun cleanup() { + lifecycleOwner.state = Lifecycle.State.DESTROYED + Dispatchers.resetMain() + } + + @Test + fun test_postponeTransition_timeout() { + testSubject.postponeTransition() + testSubject.markOffsetCalculated() + + scheduler.advanceTimeBy(TIMEOUT_MS + 1L) + verify(activity, times(1)).startPostponedEnterTransition() + verify(windowMock, never()).setWindowAnimations(anyInt()) + } + + @Test + fun test_postponeTransition_animation_resumes_only_once() { + testSubject.postponeTransition() + testSubject.markOffsetCalculated() + testSubject.markImagePreviewReady(true) + testSubject.markOffsetCalculated() + testSubject.markImagePreviewReady(true) + + scheduler.advanceTimeBy(TIMEOUT_MS + 1L) + verify(activity, times(1)).startPostponedEnterTransition() + } + + @Test + fun test_postponeTransition_resume_animation_conditions() { + testSubject.postponeTransition() + verify(activity, never()).startPostponedEnterTransition() + + testSubject.markOffsetCalculated() + verify(activity, never()).startPostponedEnterTransition() + + testSubject.markImagePreviewReady(true) + verify(activity, times(1)).startPostponedEnterTransition() + } +} diff --git a/java/tests/src/com/android/intentresolver/TestLifecycleOwner.kt b/java/tests/src/com/android/intentresolver/TestLifecycleOwner.kt new file mode 100644 index 00000000..f47e343f --- /dev/null +++ b/java/tests/src/com/android/intentresolver/TestLifecycleOwner.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry + +internal class TestLifecycleOwner : LifecycleOwner { + private val lifecycleRegistry = LifecycleRegistry.createUnsafe(this) + + override fun getLifecycle(): Lifecycle = lifecycleRegistry + + var state: Lifecycle.State + get() = lifecycle.currentState + set(value) { + lifecycleRegistry.currentState = value + } +}
\ No newline at end of file diff --git a/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt b/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt new file mode 100644 index 00000000..fd617fdd --- /dev/null +++ b/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver + +import android.graphics.Bitmap +import android.net.Uri +import java.util.function.Consumer + +internal class TestPreviewImageLoader( + private val imageLoader: ImageLoader, + private val imageOverride: () -> Bitmap? +) : ImageLoader { + override fun loadImage(uri: Uri, callback: Consumer<Bitmap?>) { + val override = imageOverride() + if (override != null) { + callback.accept(override) + } else { + imageLoader.loadImage(uri, callback) + } + } + + override suspend fun invoke(uri: Uri): Bitmap? = imageOverride() ?: imageLoader(uri) +} |