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.haptics.msdl.qs 18 19 import android.service.quicksettings.Tile 20 import androidx.test.ext.junit.runners.AndroidJUnit4 21 import androidx.test.filters.SmallTest 22 import com.android.systemui.SysuiTestCase 23 import com.android.systemui.haptics.msdl.fakeMSDLPlayer 24 import com.android.systemui.haptics.msdl.tileHapticsViewModelFactory 25 import com.android.systemui.kosmos.testScope 26 import com.android.systemui.lifecycle.activateIn 27 import com.android.systemui.plugins.qs.QSTile 28 import com.android.systemui.qs.panels.ui.viewmodel.fakeQsTile 29 import com.android.systemui.qs.panels.ui.viewmodel.tileViewModel 30 import com.android.systemui.testKosmos 31 import com.google.android.msdl.data.model.MSDLToken 32 import com.google.common.truth.Truth.assertThat 33 import kotlinx.coroutines.ExperimentalCoroutinesApi 34 import kotlinx.coroutines.test.TestScope 35 import kotlinx.coroutines.test.runCurrent 36 import kotlinx.coroutines.test.runTest 37 import org.junit.Before 38 import org.junit.Test 39 import org.junit.runner.RunWith 40 41 @SmallTest 42 @OptIn(ExperimentalCoroutinesApi::class) 43 @RunWith(AndroidJUnit4::class) 44 class TileHapticsViewModelTest : SysuiTestCase() { 45 46 private val kosmos = testKosmos() 47 private val testScope = kosmos.testScope 48 private val qsTile = kosmos.fakeQsTile 49 private val msdlPlayer = kosmos.fakeMSDLPlayer 50 private val tileViewModel = kosmos.tileViewModel 51 52 private val underTest = kosmos.tileHapticsViewModelFactory.create(tileViewModel) 53 54 @Before setUpnull55 fun setUp() { 56 underTest.activateIn(testScope) 57 } 58 59 @Test whenTileTogglesOnFromClick_playsSwitchOnHapticsnull60 fun whenTileTogglesOnFromClick_playsSwitchOnHaptics() = 61 testScope.runTest { 62 // WHEN the tile toggles on after being clicked 63 underTest.setTileInteractionState(TileHapticsViewModel.TileInteractionState.CLICKED) 64 toggleOn() 65 66 // THEN the switch on token plays 67 assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWITCH_ON) 68 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 69 } 70 71 @Test whenTileTogglesOffFromClick_playsSwitchOffHapticsnull72 fun whenTileTogglesOffFromClick_playsSwitchOffHaptics() = 73 testScope.runTest { 74 // WHEN the tile toggles off after being clicked 75 underTest.setTileInteractionState(TileHapticsViewModel.TileInteractionState.CLICKED) 76 toggleOff() 77 78 // THEN the switch off token plays 79 assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWITCH_OFF) 80 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 81 } 82 83 @Test whenTileTogglesOnWhileIdle_doesNotPlaySwitchOnHapticsnull84 fun whenTileTogglesOnWhileIdle_doesNotPlaySwitchOnHaptics() = 85 testScope.runTest { 86 // WHEN the tile toggles on without being clicked 87 toggleOn() 88 89 // THEN no token plays 90 assertThat(msdlPlayer.latestTokenPlayed).isNull() 91 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 92 } 93 94 @Test whenTileTogglesOffWhileIdle_doesNotPlaySwitchOffHapticsnull95 fun whenTileTogglesOffWhileIdle_doesNotPlaySwitchOffHaptics() = 96 testScope.runTest { 97 // WHEN the tile toggles off without being clicked 98 toggleOff() 99 100 // THEN no token plays 101 assertThat(msdlPlayer.latestTokenPlayed).isNull() 102 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 103 } 104 105 @Test whenLaunchingFromLongClick_playsLongPressHapticsnull106 fun whenLaunchingFromLongClick_playsLongPressHaptics() = 107 testScope.runTest { 108 // WHEN the tile is long-clicked and its action state changes accordingly 109 underTest.setTileInteractionState( 110 TileHapticsViewModel.TileInteractionState.LONG_CLICKED 111 ) 112 // WHEN the activity transition (from the long-click) starts 113 underTest.onActivityLaunchTransitionStart() 114 runCurrent() 115 116 // THEN the long-press token plays 117 assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.LONG_PRESS) 118 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 119 } 120 121 @Test whenLaunchingFromClick_doesNotPlayHapticsnull122 fun whenLaunchingFromClick_doesNotPlayHaptics() = 123 testScope.runTest { 124 // WHEN the tile is clicked and its action state changes accordingly 125 underTest.setTileInteractionState(TileHapticsViewModel.TileInteractionState.CLICKED) 126 // WHEN an activity transition starts (from clicking) 127 underTest.onActivityLaunchTransitionStart() 128 runCurrent() 129 130 // THEN no haptics play 131 assertThat(msdlPlayer.latestTokenPlayed).isNull() 132 assertThat(msdlPlayer.latestPropertiesPlayed).isNull() 133 } 134 TestScopenull135 private fun TestScope.toggleOn() { 136 qsTile.changeState(QSTile.State().apply { state = Tile.STATE_INACTIVE }) 137 runCurrent() 138 139 qsTile.changeState(QSTile.State().apply { state = Tile.STATE_ACTIVE }) 140 runCurrent() 141 } 142 toggleOffnull143 private fun TestScope.toggleOff() { 144 qsTile.changeState(QSTile.State().apply { state = Tile.STATE_ACTIVE }) 145 runCurrent() 146 147 qsTile.changeState(QSTile.State().apply { state = Tile.STATE_INACTIVE }) 148 runCurrent() 149 } 150 } 151