mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
settings: exercise the keep-screen-on toggle in tests
The toggle's behaviour was untested: deleting the Modifier.keepScreenOn(), hard-coding the row's request or emptying the Switch handler all left the suite green, so none of the three new code paths were actually pinned. - NowPlayingKeepScreenOnTest renders Now Playing and asserts a view in the activity tree holds the screen on while the flag is set and releases it once the flag clears. - SettingsScreenTest now covers off->on and on->off on the row, and the Switch itself, instead of only the off->on row click. - Remember the keep-screen-on flow so NowPlayingRoute stops tearing down and rebuilding its DataStore collector on every position tick.
This commit is contained in:
@@ -196,7 +196,7 @@ fun NowPlayingRoute(
|
||||
userPreferences: UserPreferences = koinInject(),
|
||||
) {
|
||||
val state by controller.state.collectAsStateWithLifecycle()
|
||||
val keepScreenOn by userPreferences.keepScreenOn().collectAsStateWithLifecycle(initialValue = false)
|
||||
val keepScreenOn by remember { userPreferences.keepScreenOn() }.collectAsStateWithLifecycle(initialValue = false)
|
||||
val positionMs by controller.positionMs.collectAsStateWithLifecycle()
|
||||
val sourceId = state.context?.sourceId
|
||||
val songId = state.item?.id
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.subtracks.ui.playback
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.subtracks.data.model.CoverArtRef
|
||||
import com.subtracks.playback.PlaybackState
|
||||
import com.subtracks.playback.QueueItem
|
||||
import com.subtracks.ui.theme.SubtracksTheme
|
||||
import com.subtracks.ui.theme.artworkColorsFromSeed
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.annotation.GraphicsMode
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
||||
class NowPlayingKeepScreenOnTest {
|
||||
@get:Rule
|
||||
val composeRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
private val state =
|
||||
PlaybackState(
|
||||
item =
|
||||
QueueItem(
|
||||
id = "s-eiirp",
|
||||
title = "Everything In Its Right Place",
|
||||
artist = "Radiohead",
|
||||
album = "Kid A",
|
||||
coverArtId = "art-al-kid-a",
|
||||
),
|
||||
isPlaying = true,
|
||||
durationMs = 251_000,
|
||||
hasNext = true,
|
||||
hasPrevious = false,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun theScreenOnFlagTracksTheSetting() {
|
||||
var keepScreenOn by mutableStateOf(true)
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
NowPlayingScreen(
|
||||
state = state,
|
||||
positionMs = 62_000,
|
||||
title = "Kid A",
|
||||
coverArt = CoverArtRef("art-al-kid-a", "test:art-al-kid-a"),
|
||||
artwork = artworkColorsFromSeed(android.graphics.Color.rgb(120, 80, 200)),
|
||||
onBack = {},
|
||||
onQueue = {},
|
||||
onPlayPause = {},
|
||||
onNext = {},
|
||||
onPrevious = {},
|
||||
onSeek = {},
|
||||
keepScreenOn = keepScreenOn,
|
||||
)
|
||||
}
|
||||
}
|
||||
composeRule.waitForIdle()
|
||||
assertNotNull("now playing should hold the screen on", viewHoldingTheScreenOn())
|
||||
|
||||
composeRule.runOnIdle { keepScreenOn = false }
|
||||
composeRule.waitForIdle()
|
||||
assertNull("clearing the setting should release the screen-on flag", viewHoldingTheScreenOn())
|
||||
}
|
||||
|
||||
private fun viewHoldingTheScreenOn(): View? = findKeepingScreenOn(composeRule.activity.window.decorView)
|
||||
|
||||
private fun findKeepingScreenOn(view: View): View? {
|
||||
if (view.keepScreenOn) return view
|
||||
if (view is ViewGroup) {
|
||||
for (index in 0 until view.childCount) {
|
||||
findKeepingScreenOn(view.getChildAt(index))?.let { return it }
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.subtracks.ui.settings
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.hasAnySibling
|
||||
import androidx.compose.ui.test.hasScrollToNodeAction
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.isToggleable
|
||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
@@ -27,8 +29,44 @@ class SettingsScreenTest {
|
||||
val composeRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
@Test
|
||||
fun theKeepScreenOnRowToggles() {
|
||||
fun theKeepScreenOnRowTurnsTheSettingOn() {
|
||||
var requested: Boolean? = null
|
||||
renderSettings(keepScreenOn = false) { requested = it }
|
||||
|
||||
composeRule.onNodeWithText("Keep screen on").performClick()
|
||||
composeRule.waitForIdle()
|
||||
|
||||
assertEquals(true, requested)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun theKeepScreenOnRowTurnsTheSettingOff() {
|
||||
var requested: Boolean? = null
|
||||
renderSettings(keepScreenOn = true) { requested = it }
|
||||
|
||||
composeRule.onNodeWithText("Keep screen on").performClick()
|
||||
composeRule.waitForIdle()
|
||||
|
||||
assertEquals(false, requested)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun theKeepScreenOnSwitchTurnsTheSettingOn() {
|
||||
var requested: Boolean? = null
|
||||
renderSettings(keepScreenOn = false) { requested = it }
|
||||
|
||||
composeRule
|
||||
.onNode(isToggleable() and hasAnySibling(hasText("Keep screen on")), useUnmergedTree = true)
|
||||
.performClick()
|
||||
composeRule.waitForIdle()
|
||||
|
||||
assertEquals(true, requested)
|
||||
}
|
||||
|
||||
private fun renderSettings(
|
||||
keepScreenOn: Boolean,
|
||||
onKeepScreenOnChange: (Boolean) -> Unit,
|
||||
) {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
SettingsScreen(
|
||||
@@ -40,7 +78,7 @@ class SettingsScreenTest {
|
||||
downloadQuality = StreamQuality(),
|
||||
downloadOverMetered = false,
|
||||
scrobbling = false,
|
||||
keepScreenOn = false,
|
||||
keepScreenOn = keepScreenOn,
|
||||
onSelectSource = {},
|
||||
onEditServer = {},
|
||||
onWifiQualityChange = {},
|
||||
@@ -49,7 +87,7 @@ class SettingsScreenTest {
|
||||
onDownloadQualityChange = {},
|
||||
onDownloadOverMeteredChange = {},
|
||||
onScrobblingChange = {},
|
||||
onKeepScreenOnChange = { requested = it },
|
||||
onKeepScreenOnChange = onKeepScreenOnChange,
|
||||
onAddServer = {},
|
||||
onOpenDownloads = {},
|
||||
onOpenLicenses = {},
|
||||
@@ -60,9 +98,6 @@ class SettingsScreenTest {
|
||||
}
|
||||
awaitText("Add server")
|
||||
composeRule.onNode(hasScrollToNodeAction()).performScrollToNode(hasText("Keep screen on"))
|
||||
composeRule.onNodeWithText("Keep screen on").performClick()
|
||||
composeRule.waitForIdle()
|
||||
assertEquals(true, requested)
|
||||
}
|
||||
|
||||
private fun awaitText(text: String) {
|
||||
|
||||
Reference in New Issue
Block a user