summaryrefslogtreecommitdiff
path: root/tests/src/com/android/customization/picker
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/com/android/customization/picker')
-rw-r--r--tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt89
-rw-r--r--tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt73
-rw-r--r--tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt120
-rw-r--r--tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt82
-rw-r--r--tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt156
-rw-r--r--tests/src/com/android/customization/picker/notifications/data/repository/NotificationsRepositoryTest.kt94
-rw-r--r--tests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt101
7 files changed, 715 insertions, 0 deletions
diff --git a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
new file mode 100644
index 00000000..2ef4e974
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.customization.picker.clock.data.repository
+
+import android.graphics.Color
+import androidx.annotation.ColorInt
+import androidx.annotation.IntRange
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository.Companion.fakeClocks
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+
+/** By default [FakeClockPickerRepository] uses [fakeClocks]. */
+open class FakeClockPickerRepository(clocks: List<ClockMetadataModel> = fakeClocks) :
+ ClockPickerRepository {
+ override val allClocks: Flow<List<ClockMetadataModel>> = MutableStateFlow(clocks).asStateFlow()
+
+ private val selectedClockId = MutableStateFlow(fakeClocks[0].clockId)
+ @ColorInt private val selectedColorId = MutableStateFlow<String?>(null)
+ private val colorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
+ @ColorInt private val seedColor = MutableStateFlow<Int?>(null)
+ override val selectedClock: Flow<ClockMetadataModel> =
+ combine(
+ selectedClockId,
+ selectedColorId,
+ colorTone,
+ seedColor,
+ ) { selectedClockId, selectedColor, colorTone, seedColor ->
+ val selectedClock = fakeClocks.find { clock -> clock.clockId == selectedClockId }
+ checkNotNull(selectedClock)
+ ClockMetadataModel(
+ selectedClock.clockId,
+ selectedClock.name,
+ selectedColor,
+ colorTone,
+ seedColor,
+ )
+ }
+
+ private val _selectedClockSize = MutableStateFlow(ClockSize.SMALL)
+ override val selectedClockSize: Flow<ClockSize> = _selectedClockSize.asStateFlow()
+
+ override fun setSelectedClock(clockId: String) {
+ selectedClockId.value = clockId
+ }
+
+ override fun setClockColor(
+ selectedColorId: String?,
+ @IntRange(from = 0, to = 100) colorToneProgress: Int,
+ @ColorInt seedColor: Int?,
+ ) {
+ this.selectedColorId.value = selectedColorId
+ this.colorTone.value = colorToneProgress
+ this.seedColor.value = seedColor
+ }
+
+ override suspend fun setClockSize(size: ClockSize) {
+ _selectedClockSize.value = size
+ }
+
+ companion object {
+ val fakeClocks =
+ listOf(
+ ClockMetadataModel("clock0", "clock0", null, 50, null),
+ ClockMetadataModel("clock1", "clock1", null, 50, null),
+ ClockMetadataModel("clock2", "clock2", null, 50, null),
+ ClockMetadataModel("clock3", "clock3", null, 50, null),
+ )
+ const val CLOCK_COLOR_ID = "RED"
+ const val CLOCK_COLOR_TONE_PROGRESS = 87
+ const val SEED_COLOR = Color.RED
+ }
+}
diff --git a/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
new file mode 100644
index 00000000..cd41d7d0
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
@@ -0,0 +1,73 @@
+package com.android.customization.picker.clock.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockPickerInteractorTest {
+
+ private lateinit var underTest: ClockPickerInteractor
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ underTest = ClockPickerInteractor(FakeClockPickerRepository())
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun setSelectedClock() = runTest {
+ val observedSelectedClockId = collectLastValue(underTest.selectedClockId)
+ underTest.setSelectedClock(FakeClockPickerRepository.fakeClocks[1].clockId)
+ Truth.assertThat(observedSelectedClockId())
+ .isEqualTo(FakeClockPickerRepository.fakeClocks[1].clockId)
+ }
+
+ @Test
+ fun setClockSize() = runTest {
+ val observedClockSize = collectLastValue(underTest.selectedClockSize)
+ underTest.setClockSize(ClockSize.DYNAMIC)
+ Truth.assertThat(observedClockSize()).isEqualTo(ClockSize.DYNAMIC)
+
+ underTest.setClockSize(ClockSize.SMALL)
+ Truth.assertThat(observedClockSize()).isEqualTo(ClockSize.SMALL)
+ }
+
+ @Test
+ fun setColor() = runTest {
+ val observedSelectedColor = collectLastValue(underTest.selectedColorId)
+ val observedColorToneProgress = collectLastValue(underTest.colorToneProgress)
+ val observedSeedColor = collectLastValue(underTest.seedColor)
+ underTest.setClockColor(
+ FakeClockPickerRepository.CLOCK_COLOR_ID,
+ FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS,
+ FakeClockPickerRepository.SEED_COLOR,
+ )
+ Truth.assertThat(observedSelectedColor())
+ .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_ID)
+ Truth.assertThat(observedColorToneProgress())
+ .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS)
+ Truth.assertThat(observedSeedColor()).isEqualTo(FakeClockPickerRepository.SEED_COLOR)
+ }
+}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
new file mode 100644
index 00000000..63f77bd6
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.customization.picker.clock.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockCarouselViewModelTest {
+ private val repositoryWithMultipleClocks by lazy { FakeClockPickerRepository() }
+ private val repositoryWithSingleClock by lazy {
+ FakeClockPickerRepository(
+ listOf(
+ ClockMetadataModel(
+ "clock0",
+ "clock0",
+ null,
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
+ null,
+ ),
+ )
+ )
+ }
+ private lateinit var underTest: ClockCarouselViewModel
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun setSelectedClock() = runTest {
+ underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
+ val observedSelectedIndex = collectLastValue(underTest.selectedIndex)
+ advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ underTest.setSelectedClock(FakeClockPickerRepository.fakeClocks[2].clockId)
+ assertThat(observedSelectedIndex()).isEqualTo(2)
+ }
+
+ @Test
+ fun setShouldShowCarousel() = runTest {
+ underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
+ val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
+ advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ underTest.showClockCarousel(false)
+ assertThat(observedIsCarouselVisible()).isFalse()
+ underTest.showClockCarousel(true)
+ assertThat(observedIsCarouselVisible()).isTrue()
+ }
+
+ @Test
+ fun shouldNotShowCarouselWhenSingleClock() = runTest {
+ underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
+ val observedIsCarouselVisible = collectLastValue(underTest.isCarouselVisible)
+ advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ underTest.showClockCarousel(false)
+ assertThat(observedIsCarouselVisible()).isFalse()
+ underTest.showClockCarousel(true)
+ assertThat(observedIsCarouselVisible()).isFalse()
+ }
+
+ @Test
+ fun setShouldShowSingleClock() = runTest {
+ underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithSingleClock))
+ val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
+ advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ underTest.showClockCarousel(false)
+ assertThat(observedIsSingleClockViewVisible()).isFalse()
+ underTest.showClockCarousel(true)
+ assertThat(observedIsSingleClockViewVisible()).isTrue()
+ }
+
+ @Test
+ fun shouldNotShowSingleClockWhenMultipleClocks() = runTest {
+ underTest = ClockCarouselViewModel(ClockPickerInteractor(repositoryWithMultipleClocks))
+ val observedIsSingleClockViewVisible = collectLastValue(underTest.isSingleClockViewVisible)
+ advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+ underTest.showClockCarousel(false)
+ assertThat(observedIsSingleClockViewVisible()).isFalse()
+ underTest.showClockCarousel(true)
+ assertThat(observedIsSingleClockViewVisible()).isFalse()
+ }
+}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
new file mode 100644
index 00000000..61976ad6
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.customization.picker.clock.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockSectionViewModelTest {
+
+ private lateinit var clockColorMap: Map<String, ClockColorViewModel>
+ private lateinit var interactor: ClockPickerInteractor
+ private lateinit var underTest: ClockSectionViewModel
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ clockColorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+ interactor = ClockPickerInteractor(FakeClockPickerRepository())
+ underTest =
+ ClockSectionViewModel(
+ context,
+ interactor,
+ )
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun setSelectedClock() = runTest {
+ val colorRed = clockColorMap.values.first()
+ val observedSelectedClockColorAndSizeText =
+ collectLastValue(underTest.selectedClockColorAndSizeText)
+ interactor.setClockColor(
+ colorRed.colorId,
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
+ ClockSettingsViewModel.blendColorWithTone(
+ colorRed.color,
+ colorRed.getColorTone(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS),
+ )
+ )
+ interactor.setClockSize(ClockSize.DYNAMIC)
+ assertThat(observedSelectedClockColorAndSizeText()).isEqualTo("Red, dynamic")
+ }
+}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
new file mode 100644
index 00000000..d53288d0
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -0,0 +1,156 @@
+package com.android.customization.picker.clock.ui.viewmodel
+
+import android.content.Context
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.customization.picker.color.data.repository.FakeColorPickerRepository
+import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
+import com.android.wallpaper.testing.FakeSnapshotStore
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockSettingsViewModelTest {
+
+ private lateinit var context: Context
+ private lateinit var colorPickerInteractor: ColorPickerInteractor
+ private lateinit var underTest: ClockSettingsViewModel
+ private lateinit var colorMap: Map<String, ClockColorViewModel>
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ context = InstrumentationRegistry.getInstrumentation().targetContext
+ colorPickerInteractor =
+ ColorPickerInteractor(
+ repository = FakeColorPickerRepository(context = context),
+ snapshotRestorer = {
+ ColorPickerSnapshotRestorer(interactor = colorPickerInteractor).apply {
+ runBlocking { setUpSnapshotRestorer(store = FakeSnapshotStore()) }
+ }
+ },
+ )
+ underTest =
+ ClockSettingsViewModel.Factory(
+ context = context,
+ clockPickerInteractor = ClockPickerInteractor(FakeClockPickerRepository()),
+ colorPickerInteractor = colorPickerInteractor,
+ )
+ .create(ClockSettingsViewModel::class.java)
+ colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun clickOnColorSettingsTab() = runTest {
+ val tabs = collectLastValue(underTest.tabs)
+ assertThat(tabs()?.get(0)?.name).isEqualTo("Color")
+ assertThat(tabs()?.get(0)?.isSelected).isTrue()
+ assertThat(tabs()?.get(1)?.name).isEqualTo("Size")
+ assertThat(tabs()?.get(1)?.isSelected).isFalse()
+
+ tabs()?.get(1)?.onClicked?.invoke()
+ assertThat(tabs()?.get(0)?.isSelected).isFalse()
+ assertThat(tabs()?.get(1)?.isSelected).isTrue()
+ }
+
+ @Test
+ fun setSelectedColor() = runTest {
+ val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+ val observedSelectedColorOptionPosition =
+ collectLastValue(underTest.selectedColorOptionPosition)
+ val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+ val observedSeedColor = collectLastValue(underTest.seedColor)
+ // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+ advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+ assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
+ assertThat(observedClockColorOptions()!![0].onClick).isNull()
+ assertThat(observedSelectedColorOptionPosition()).isEqualTo(0)
+
+ observedClockColorOptions()!![1].onClick?.invoke()
+ // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+ advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+ assertThat(observedClockColorOptions()!![1].isSelected).isTrue()
+ assertThat(observedClockColorOptions()!![1].onClick).isNull()
+ assertThat(observedSelectedColorOptionPosition()).isEqualTo(1)
+ assertThat(observedSliderProgress())
+ .isEqualTo(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
+ val expectedSelectedColorModel = colorMap.values.first() // RED
+ assertThat(observedSeedColor())
+ .isEqualTo(
+ ClockSettingsViewModel.blendColorWithTone(
+ expectedSelectedColorModel.color,
+ expectedSelectedColorModel.getColorTone(
+ ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
+ ),
+ )
+ )
+ }
+
+ @Test
+ fun setColorTone() = runTest {
+ val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+ val observedIsSliderEnabled = collectLastValue(underTest.isSliderEnabled)
+ val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+ val observedSeedColor = collectLastValue(underTest.seedColor)
+ // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+ advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+ assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
+ assertThat(observedIsSliderEnabled()).isFalse()
+
+ observedClockColorOptions()!![1].onClick?.invoke()
+
+ // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
+ advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
+ assertThat(observedIsSliderEnabled()).isTrue()
+ val targetProgress1 = 99
+ underTest.onSliderProgressChanged(targetProgress1)
+ assertThat(observedSliderProgress()).isEqualTo(targetProgress1)
+ val targetProgress2 = 55
+ underTest.onSliderProgressStop(targetProgress2)
+ assertThat(observedSliderProgress()).isEqualTo(targetProgress2)
+ val expectedSelectedColorModel = colorMap.values.first() // RED
+ assertThat(observedSeedColor())
+ .isEqualTo(
+ ClockSettingsViewModel.blendColorWithTone(
+ expectedSelectedColorModel.color,
+ expectedSelectedColorModel.getColorTone(targetProgress2),
+ )
+ )
+ }
+
+ @Test
+ fun setClockSize() = runTest {
+ val observedClockSize = collectLastValue(underTest.selectedClockSize)
+ underTest.setClockSize(ClockSize.DYNAMIC)
+ assertThat(observedClockSize()).isEqualTo(ClockSize.DYNAMIC)
+
+ underTest.setClockSize(ClockSize.SMALL)
+ assertThat(observedClockSize()).isEqualTo(ClockSize.SMALL)
+ }
+}
diff --git a/tests/src/com/android/customization/picker/notifications/data/repository/NotificationsRepositoryTest.kt b/tests/src/com/android/customization/picker/notifications/data/repository/NotificationsRepositoryTest.kt
new file mode 100644
index 00000000..be799db3
--- /dev/null
+++ b/tests/src/com/android/customization/picker/notifications/data/repository/NotificationsRepositoryTest.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.customization.picker.notifications.data.repository
+
+import android.provider.Settings
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.notifications.shared.model.NotificationSettingsModel
+import com.android.wallpaper.testing.FakeSecureSettingsRepository
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class NotificationsRepositoryTest {
+
+ private lateinit var underTest: NotificationsRepository
+
+ private lateinit var testScope: TestScope
+ private lateinit var secureSettingsRepository: FakeSecureSettingsRepository
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+ secureSettingsRepository = FakeSecureSettingsRepository()
+
+ underTest =
+ NotificationsRepository(
+ scope = testScope.backgroundScope,
+ backgroundDispatcher = testDispatcher,
+ secureSettingsRepository = secureSettingsRepository,
+ )
+ }
+
+ @Test
+ fun settings() =
+ testScope.runTest {
+ val settings = collectLastValue(underTest.settings)
+
+ secureSettingsRepository.set(
+ name = Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ value = 1,
+ )
+ assertThat(settings())
+ .isEqualTo(NotificationSettingsModel(isShowNotificationsOnLockScreenEnabled = true))
+
+ secureSettingsRepository.set(
+ name = Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ value = 0,
+ )
+ assertThat(settings())
+ .isEqualTo(
+ NotificationSettingsModel(isShowNotificationsOnLockScreenEnabled = false)
+ )
+ }
+
+ @Test
+ fun setSettings() =
+ testScope.runTest {
+ val settings = collectLastValue(underTest.settings)
+
+ val model1 = NotificationSettingsModel(isShowNotificationsOnLockScreenEnabled = true)
+ underTest.setSettings(model1)
+ assertThat(settings()).isEqualTo(model1)
+
+ val model2 = NotificationSettingsModel(isShowNotificationsOnLockScreenEnabled = false)
+ underTest.setSettings(model2)
+ assertThat(settings()).isEqualTo(model2)
+ }
+}
diff --git a/tests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt b/tests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt
new file mode 100644
index 00000000..64426094
--- /dev/null
+++ b/tests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.customization.picker.notifications.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.notifications.data.repository.NotificationsRepository
+import com.android.customization.picker.notifications.domain.interactor.NotificationsInteractor
+import com.android.customization.picker.notifications.domain.interactor.NotificationsSnapshotRestorer
+import com.android.wallpaper.testing.FakeSecureSettingsRepository
+import com.android.wallpaper.testing.FakeSnapshotStore
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class NotificationSectionViewModelTest {
+
+ private lateinit var underTest: NotificationSectionViewModel
+
+ private lateinit var testScope: TestScope
+ private lateinit var interactor: NotificationsInteractor
+
+ @Before
+ fun setUp() {
+ val testDispatcher = UnconfinedTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ testScope = TestScope(testDispatcher)
+ interactor =
+ NotificationsInteractor(
+ repository =
+ NotificationsRepository(
+ scope = testScope.backgroundScope,
+ backgroundDispatcher = testDispatcher,
+ secureSettingsRepository = FakeSecureSettingsRepository(),
+ ),
+ snapshotRestorer = {
+ NotificationsSnapshotRestorer(
+ interactor = interactor,
+ )
+ .apply { runBlocking { setUpSnapshotRestorer(FakeSnapshotStore()) } }
+ },
+ )
+
+ underTest =
+ NotificationSectionViewModel(
+ interactor = interactor,
+ )
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun `toggles back and forth`() =
+ testScope.runTest {
+ val subtitleStringResId = collectLastValue(underTest.subtitleStringResourceId)
+ val isSwitchOn = collectLastValue(underTest.isSwitchOn)
+
+ val initialSubtitleStringRes = subtitleStringResId()
+ val initialIsSwitchOn = isSwitchOn()
+
+ underTest.onClicked()
+ assertThat(subtitleStringResId()).isNotEqualTo(initialSubtitleStringRes)
+ assertThat(isSwitchOn()).isNotEqualTo(initialIsSwitchOn)
+
+ underTest.onClicked()
+ assertThat(subtitleStringResId()).isEqualTo(initialSubtitleStringRes)
+ assertThat(isSwitchOn()).isEqualTo(initialIsSwitchOn)
+ }
+}