Compile updater fixtures through the existing app test source set
This commit is contained in:
parent
ee3f3ae11e
commit
2b8c729f62
8 changed files with 45 additions and 33 deletions
|
|
@ -73,6 +73,11 @@ import javax.inject.Singleton
|
|||
object TestModule {
|
||||
val testDispatcher = StandardTestDispatcher()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun updateController(): org.justinvisser.wolfskin.tv.update.UpdateController =
|
||||
org.justinvisser.wolfskin.tv.update.FakeUpdateController()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun deviceInfo(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
package org.justinvisser.wolfskin.tv
|
||||
package org.justinvisser.wolfskin.tv.update
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.justinvisser.wolfskin.design.ShellKey
|
||||
import org.justinvisser.wolfskin.tv.update.*
|
||||
|
||||
/** Behavior boundaries are controller outcomes, not incidental UI wording. */
|
||||
class UpdateBehaviorTest {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
package org.justinvisser.wolfskin.tv
|
||||
package org.justinvisser.wolfskin.tv.update
|
||||
|
||||
import android.app.Application
|
||||
import android.view.View
|
||||
|
|
@ -25,7 +25,6 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.justinvisser.wolfskin.design.*
|
||||
import org.justinvisser.wolfskin.tv.update.*
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.GraphicsMode
|
||||
|
|
@ -78,7 +77,7 @@ class UpdatesCaptureTest {
|
|||
rule.onRoot().captureRoboImage(file.absolutePath)
|
||||
}
|
||||
|
||||
private fun press(vararg keys: Key) {
|
||||
private fun press(keys: List<Key>) {
|
||||
keys.forEach { key -> rule.onNodeWithTag("wolfskin-shell").performKeyInput { pressKey(key) } }
|
||||
rule.mainClock.advanceTimeBy(320)
|
||||
rule.waitForIdle()
|
||||
|
|
@ -87,7 +86,7 @@ class UpdatesCaptureTest {
|
|||
@Test fun settings() { launch(UpdateUiState.Checking, settings = true); capture("settings") }
|
||||
@Test fun classic() {
|
||||
launch(UpdateUiState.Checking, settings = true)
|
||||
repeat(8) { press(Key.DirectionDown) }
|
||||
repeat(8) { press(listOf(Key.DirectionDown)) }
|
||||
assertEquals(9, shell.settingsRow)
|
||||
assertEquals(4, shell.view.listState.firstVisibleItemIndex)
|
||||
capture("classic")
|
||||
|
|
@ -95,8 +94,8 @@ class UpdatesCaptureTest {
|
|||
@Test fun checking() { launch(UpdateUiState.Checking); capture("checking") }
|
||||
@Test fun current() { launch(UpdateUiState.UpToDate); capture("current") }
|
||||
@Test fun available() { launch(updateReleaseFixture()); capture("available") }
|
||||
@Test fun notes() { launch(updateReleaseFixture()); press(Key.DirectionRight); capture("notes") }
|
||||
@Test fun notesOpen() { launch(updateReleaseFixture()); press(Key.DirectionRight, Key.DirectionCenter); capture("notes-open") }
|
||||
@Test fun notes() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight)); capture("notes") }
|
||||
@Test fun notesOpen() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight, Key.DirectionCenter)); capture("notes-open") }
|
||||
@Test fun downloading() { launch(UpdateUiState.Downloading(20_100_000, 47_800_000)); capture("downloading") }
|
||||
@Test fun ready() { launch(UpdateUiState.Ready("1.1.1")); capture("ready") }
|
||||
@Test fun permission() { launch(UpdateUiState.PermissionNeeded); capture("permission") }
|
||||
|
|
@ -107,8 +106,8 @@ class UpdatesCaptureTest {
|
|||
@Test fun noInstaller() { launch(UpdateUiState.NoInstaller); capture("no-installer") }
|
||||
@Test fun noReleasePublished() { launch(UpdateUiState.NoReleasePublished); capture("no-release") }
|
||||
@Test fun unknownDownloadLength() { launch(UpdateUiState.Downloading(20_100_000, null)); capture("unknown-total") }
|
||||
@Test fun autoOn() { launch(updateReleaseFixture()); press(Key.DirectionDown); capture("auto-on") }
|
||||
@Test fun autoOff() { launch(updateReleaseFixture()); press(Key.DirectionDown, Key.DirectionCenter); capture("auto-off") }
|
||||
@Test fun autoOn() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown)); capture("auto-on") }
|
||||
@Test fun autoOff() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown, Key.DirectionCenter)); capture("auto-off") }
|
||||
@Test fun updated() {
|
||||
launch(UpdateUiState.UpToDate)
|
||||
rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) }
|
||||
|
|
@ -118,14 +117,14 @@ class UpdatesCaptureTest {
|
|||
|
||||
@Test fun notesTrapRealKeysAndBackPreservesSettingsRowAndScroller() {
|
||||
launch(updateReleaseFixture())
|
||||
press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionUp, Key.DirectionRight, Key.DirectionDown)
|
||||
press(listOf(Key.DirectionRight, Key.DirectionCenter, Key.DirectionUp, Key.DirectionRight, Key.DirectionDown))
|
||||
assertTrue(shell.contentOverlayVisible)
|
||||
assertFalse(shell.navFocused)
|
||||
assertTrue(controller.autoCheck.value)
|
||||
press(Key.Back)
|
||||
press(listOf(Key.Back))
|
||||
assertFalse(shell.contentOverlayVisible)
|
||||
assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex)
|
||||
press(Key.Back)
|
||||
press(listOf(Key.Back))
|
||||
assertEquals("settings", shell.route)
|
||||
assertEquals(1, shell.settingsRow)
|
||||
assertEquals(0, shell.view.listState.firstVisibleItemIndex)
|
||||
|
|
@ -133,12 +132,12 @@ class UpdatesCaptureTest {
|
|||
|
||||
@Test fun longNotesScrollWithoutEscapingToNavOrAutoCheck() {
|
||||
launch(updateReleaseFixture().copy(notes = (1..30).joinToString("\n") { "Release detail $it" }))
|
||||
press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionDown, Key.DirectionDown)
|
||||
press(listOf(Key.DirectionRight, Key.DirectionCenter, Key.DirectionDown, Key.DirectionDown))
|
||||
val range = rule.onNodeWithTag("update-notes").fetchSemanticsNode().config[SemanticsProperties.VerticalScrollAxisRange]
|
||||
assertTrue(range.value() > 0f)
|
||||
assertFalse(shell.navFocused)
|
||||
assertFalse((shell.contentFocus as UpdateFocus).autoFocused)
|
||||
press(Key.Back)
|
||||
press(listOf(Key.Back))
|
||||
assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex)
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +166,7 @@ class UpdatesCaptureTest {
|
|||
if (target != null) {
|
||||
repeat(101) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/download-%03d".format(frame)) }
|
||||
}
|
||||
press(Key.DirectionDown)
|
||||
press(listOf(Key.DirectionDown))
|
||||
rule.runOnIdle { controller.show(UpdateUiState.Downloading(31_000_000, 47_800_000)) }
|
||||
rule.mainClock.advanceTimeBy(16)
|
||||
assertTrue((shell.contentFocus as UpdateFocus).autoFocused)
|
||||
|
|
@ -165,18 +165,22 @@ private fun AutoCheckRow(enabled: Boolean, focused: Boolean, modifier: Modifier,
|
|||
@Composable
|
||||
private fun NotesPanel(release: UpdateUiState.Available?, scroll: androidx.compose.foundation.ScrollState) {
|
||||
val shape = RoundedCornerShape(U.radius)
|
||||
Column(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes")
|
||||
val paragraphs = remember(release?.notes) { release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.toList().orEmpty() }
|
||||
val notesStyle = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal)
|
||||
CssColumn(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes")
|
||||
.focusRing(true, U.radius, WolfskinTokens.Focus.ringControlRing)
|
||||
.background(C.surface, shape).border(U.border, C.border, shape)
|
||||
.verticalScroll(scroll).padding(U.padding + U.border)) {
|
||||
Text(updateMetadata(release), Modifier.exactLineBox(T.stateTitle), style = T.stateTitle.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Bold), color = C.fg)
|
||||
Spacer(Modifier.height(U.notesTitleBottom))
|
||||
release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.forEach { paragraph ->
|
||||
Row(Modifier.padding(vertical = U.notesGap / 2)) {
|
||||
Text("•", Modifier.width(U.padding / 2), style = T.nav, color = C.muted)
|
||||
Text(paragraph.removePrefix("- "), Modifier.exactLineBox(T.nav), style = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted)
|
||||
Spacer(Modifier.height(U.notesListTop))
|
||||
paragraphs.forEachIndexed { index, paragraph ->
|
||||
Row(Modifier.padding(start = U.notesMarkerOffset).exactLineBox(notesStyle)) {
|
||||
Text("•", Modifier.width(U.notesMarkerWidth).exactLineBox(notesStyle), style = notesStyle, color = C.muted)
|
||||
Text(paragraph.removePrefix("- "), Modifier.exactLineBox(notesStyle), style = notesStyle, color = C.muted)
|
||||
}
|
||||
if (index != paragraphs.lastIndex) Spacer(Modifier.height(U.notesGap))
|
||||
}
|
||||
Text("Sign-in stays on this TV. Android asks before installing.", Modifier.padding(top = U.notesGap), style = T.body, color = C.muted)
|
||||
Spacer(Modifier.height(U.notesListBottom))
|
||||
Text("Sign-in stays on this TV. Android asks before installing.", Modifier.exactLineBox(T.body), style = T.body, color = C.muted)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue