Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e3c0c44 authored by Yalan Yiue's avatar Yalan Yiue Committed by Android (Google) Code Review
Browse files

Merge "TutorialSchedulerInteractorTest" into main

parents 48d98a08 187f1e28
Loading
Loading
Loading
Loading
+164 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.inputdevice.tutorial.domain.interactor

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.TutorialType
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.hours
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class TutorialSchedulerInteractorTest : SysuiTestCase() {

    private lateinit var underTest: TutorialSchedulerInteractor
    private val kosmos = Kosmos()
    private val testScope = kosmos.testScope
    private lateinit var dataStoreScope: CoroutineScope
    private val keyboardRepository = FakeKeyboardRepository()
    private val touchpadRepository = FakeTouchpadRepository()
    private lateinit var schedulerRepository: TutorialSchedulerRepository

    @Before
    fun setup() {
        dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
        schedulerRepository =
            TutorialSchedulerRepository(
                context,
                dataStoreScope,
                dataStoreName = "TutorialSchedulerInteractorTest"
            )
        underTest =
            TutorialSchedulerInteractor(
                testScope.backgroundScope,
                keyboardRepository,
                touchpadRepository,
                schedulerRepository
            )
        underTest.start()
    }

    @After
    fun clear() {
        runBlocking { schedulerRepository.clearDataStore() }
        dataStoreScope.cancel()
    }

    @Test
    fun connectKeyboard_delayElapse_launchForKeyboard() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(true)
            advanceTimeBy(LAUNCH_DELAY)
            assertLaunch(TutorialType.KEYBOARD)
        }

    @Test
    fun connectBothDevices_delayElapse_launchForBoth() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(true)
            touchpadRepository.setIsAnyTouchpadConnected(true)
            advanceTimeBy(LAUNCH_DELAY)
            assertLaunch(TutorialType.BOTH)
        }

    @Test
    fun connectBothDevice_delayNotElapse_launchNothing() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(true)
            touchpadRepository.setIsAnyTouchpadConnected(true)
            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
            assertLaunch(TutorialType.NONE)
        }

    @Test
    fun nothingConnect_delayElapse_launchNothing() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(false)
            touchpadRepository.setIsAnyTouchpadConnected(false)
            advanceTimeBy(LAUNCH_DELAY)
            assertLaunch(TutorialType.NONE)
        }

    @Test
    fun connectKeyboard_thenTouchpad_delayElapse_launchForBoth() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(true)
            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
            touchpadRepository.setIsAnyTouchpadConnected(true)
            advanceTimeBy(REMAINING_TIME)
            assertLaunch(TutorialType.BOTH)
        }

    @Test
    fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_launchNothing() =
        testScope.runTest {
            keyboardRepository.setIsAnyKeyboardConnected(true)
            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
            touchpadRepository.setIsAnyTouchpadConnected(true)
            keyboardRepository.setIsAnyKeyboardConnected(false)
            advanceTimeBy(REMAINING_TIME)
            assertLaunch(TutorialType.NONE)
        }

    // TODO: likely to be changed after we update TutorialSchedulerInteractor.launchTutorial
    private suspend fun assertLaunch(tutorialType: TutorialType) {
        when (tutorialType) {
            TutorialType.KEYBOARD -> {
                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
            }
            TutorialType.TOUCHPAD -> {
                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
            }
            TutorialType.BOTH -> {
                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
            }
            TutorialType.NONE -> {
                assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
                assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
            }
        }
    }

    companion object {
        private val LAUNCH_DELAY = 72.hours
        private val A_SHORT_PERIOD_OF_TIME = 2.hours
        private val REMAINING_TIME = 70.hours
    }
}
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.touchpad.data.repository

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow

class FakeTouchpadRepository : TouchpadRepository {

    private val _isAnyTouchpadConnected = MutableStateFlow(false)
    override val isAnyTouchpadConnected: Flow<Boolean> = _isAnyTouchpadConnected

    fun setIsAnyTouchpadConnected(connected: Boolean) {
        _isAnyTouchpadConnected.value = connected
    }
}