diff options
| author | 2023-11-03 15:24:27 +0000 | |
|---|---|---|
| committer | 2023-11-06 14:12:27 +0000 | |
| commit | 6568631fd13f928adc1e43f89a0f7873e24cf5e8 (patch) | |
| tree | 287c9a77885470800e0f30f16981d2b908776879 | |
| parent | 7a17d7899945f400a7ad67b3ebd51ecf18a88e08 (diff) | |
Add test utilities to simplify writing tests for new tiles
Test: atest QsTileIntentUserInputHandlerTest
Flag: LEGACY QS_PIPELINE_NEW_TILES DISABLED
Bug: 299909368
Change-Id: I85ecbe35fb8784a0f7a2ef8feffa63818c5bb891
6 files changed, 182 insertions, 5 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt index 905d8effdadf..840db260a8d6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandler.kt @@ -29,12 +29,18 @@ import javax.inject.Inject * Provides a shortcut to start an activity from [QSTileUserActionInteractor]. It supports keyguard * dismissing and tile from-view animations. */ +interface QSTileIntentUserInputHandler { + + fun handle(view: View?, intent: Intent) + fun handle(view: View?, pendingIntent: PendingIntent) +} + @SysUISingleton -class QSTileIntentUserInputHandler +class QSTileIntentUserInputHandlerImpl @Inject -constructor(private val activityStarter: ActivityStarter) { +constructor(private val activityStarter: ActivityStarter) : QSTileIntentUserInputHandler { - fun handle(view: View?, intent: Intent) { + override fun handle(view: View?, intent: Intent) { val animationController: ActivityLaunchAnimator.Controller? = view?.let { ActivityLaunchAnimator.Controller.fromView( @@ -46,7 +52,7 @@ constructor(private val activityStarter: ActivityStarter) { } // TODO(b/249804373): make sure to allow showing activities over the lockscreen. See b/292112939 - fun handle(view: View?, pendingIntent: PendingIntent) { + override fun handle(view: View?, pendingIntent: PendingIntent) { if (!pendingIntent.isActivity) { return } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt index 32522ad66626..94137c88098e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt @@ -16,6 +16,8 @@ package com.android.systemui.qs.tiles.di +import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler +import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerImpl import com.android.systemui.qs.tiles.impl.custom.di.CustomTileComponent import com.android.systemui.qs.tiles.viewmodel.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider @@ -45,4 +47,9 @@ interface QSTilesModule { @Multibinds fun tileViewModelMap(): Map<String, QSTileViewModel> @Binds fun bindQSTileConfigProvider(impl: QSTileConfigProviderImpl): QSTileConfigProvider + + @Binds + fun bindQSTileIntentUserInputHandler( + impl: QSTileIntentUserInputHandlerImpl + ): QSTileIntentUserInputHandler } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt index 95ee3b7a8495..bd1c310ab8de 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerTest.kt @@ -41,7 +41,7 @@ class QSTileIntentUserInputHandlerTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - underTest = QSTileIntentUserInputHandler(activityStarted) + underTest = QSTileIntentUserInputHandlerImpl(activityStarted) } @Test diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt new file mode 100644 index 000000000000..1185f2edef3b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/FakeQSTileIntentUserInputHandler.kt @@ -0,0 +1,52 @@ +/* + * 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.systemui.qs.tiles.base.actions + +import android.app.PendingIntent +import android.content.Intent +import android.view.View + +/** + * Fake implementation of [QSTileIntentUserInputHandler] interface. Consider using this alongside + * [QSTileIntentUserInputHandlerSubject]. + */ +class FakeQSTileIntentUserInputHandler : QSTileIntentUserInputHandler { + + val handledInputs: List<Input> + get() = mutableInputs + + private val mutableInputs = mutableListOf<Input>() + + override fun handle(view: View?, intent: Intent) { + mutableInputs.add(Input.Intent(view, intent)) + } + + override fun handle(view: View?, pendingIntent: PendingIntent) { + mutableInputs.add(Input.PendingIntent(view, pendingIntent)) + } + + sealed interface Input { + data class Intent(val view: View?, val intent: android.content.Intent) : Input + data class PendingIntent(val view: View?, val pendingIntent: android.app.PendingIntent) : + Input + } +} + +val FakeQSTileIntentUserInputHandler.intentInputs + get() = handledInputs.mapNotNull { it as? FakeQSTileIntentUserInputHandler.Input.Intent } +val FakeQSTileIntentUserInputHandler.pendingIntentInputs + get() = handledInputs.mapNotNull { it as? FakeQSTileIntentUserInputHandler.Input.PendingIntent } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerSubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerSubject.kt new file mode 100644 index 000000000000..e09f2806ce5c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserInputHandlerSubject.kt @@ -0,0 +1,76 @@ +/* + * 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.systemui.qs.tiles.base.actions + +import com.google.common.truth.FailureMetadata +import com.google.common.truth.Subject +import com.google.common.truth.Truth + +/** [Truth] [Subject] to assert inputs handled by [FakeQSTileIntentUserInputHandler] */ +class QSTileIntentUserInputHandlerSubject +private constructor( + failureMetadata: FailureMetadata, + private val subject: FakeQSTileIntentUserInputHandler +) : Subject(failureMetadata, subject) { + + fun handledOneIntentInput( + intentAssertions: (FakeQSTileIntentUserInputHandler.Input.Intent) -> Unit = {}, + ) { + // check that there are no other inputs + check("handledInputs").that(subject.handledInputs).hasSize(1) + // check there is an intent input + check("intentInputs").that(subject.intentInputs).hasSize(1) + + intentAssertions(subject.intentInputs.first()) + } + + fun handledOnePendingIntentInput( + intentAssertions: (FakeQSTileIntentUserInputHandler.Input.PendingIntent) -> Unit = {}, + ) { + // check that there are no other inputs + check("handledInputs").that(subject.handledInputs).hasSize(1) + // check there is a pending intent input + check("intentInputs").that(subject.pendingIntentInputs).hasSize(1) + + intentAssertions(subject.pendingIntentInputs.first()) + } + + fun handledNoInputs() { + check("handledInputs").that(subject.handledInputs).isEmpty() + } + + companion object { + + /** + * [Truth.assertThat]-like factory to initialize the assertion. Example: + * ``` + * assertThat(inputHandler).handledOneIntentInput { + * assertThat(it.intent.action).isEqualTo("action.Test") + * } + * ``` + */ + fun assertThat( + handler: FakeQSTileIntentUserInputHandler + ): QSTileIntentUserInputHandlerSubject = + Truth.assertAbout { + failureMetadata: FailureMetadata, + subject: FakeQSTileIntentUserInputHandler -> + QSTileIntentUserInputHandlerSubject(failureMetadata, subject) + } + .that(handler) + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt new file mode 100644 index 000000000000..832b07a0763b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/base/interactor/QSTileInputTestKtx.kt @@ -0,0 +1,36 @@ +/* + * 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.systemui.qs.tiles.base.interactor + +import android.os.UserHandle +import android.view.View +import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction + +object QSTileInputTestKtx { + + fun <T> click( + data: T, + user: UserHandle = UserHandle.CURRENT, + view: View? = null, + ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.Click(view), data) + + fun <T> longClick( + data: T, + user: UserHandle = UserHandle.CURRENT, + view: View? = null, + ): QSTileInput<T> = QSTileInput(user, QSTileUserAction.LongClick(view), data) +} |