Keep shell state reads safe in read-only snapshots
All checks were successful
review/code-claude Hotfix verified on the real Xiaomi box (B3 runs, no crash across Home/Discover/Movies/Shows/title/Settings/Requests); 5-file delta read by firstmate: ShellState.rememberedView no longer writes on read, 3 regression tests incl. snapshotFlow and an audit
All checks were successful
review/code-claude Hotfix verified on the real Xiaomi box (B3 runs, no crash across Home/Discover/Movies/Shows/title/Settings/Requests); 5-file delta read by firstmate: ShellState.rememberedView no longer writes on read, 3 regression tests incl. snapshotFlow and an audit
This commit is contained in:
parent
e9a92eba49
commit
4e6377b628
5 changed files with 199 additions and 3 deletions
|
|
@ -0,0 +1,56 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
package org.justinvisser.wolfskin.tv
|
||||
|
||||
import android.app.Application
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.justinvisser.wolfskin.conductarr.MemoryCacheStore
|
||||
import org.justinvisser.wolfskin.design.*
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
/** No drawn screen may prewarm memory before the production Discover observer starts. */
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [34], application = Application::class)
|
||||
class DiscoverSnapshotReadTest {
|
||||
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
@Test fun signedInHostObservesFreshShellThroughTheRealAsyncProvider() {
|
||||
FakeConductarr().use { fake ->
|
||||
ConductarrSession(MemoryCacheStore()).use { session ->
|
||||
session.select("server:shared", SHARED_TOKEN, fake.url)
|
||||
runBlocking { session.authenticate() }
|
||||
val identity = requireNotNull(session.identity.value)
|
||||
assertTrue(identity.signedIn)
|
||||
val shell = ShellState(listOf(ShellPerson("shared", "Shared", "S", true)), "shared")
|
||||
lateinit var current: DiscoverState
|
||||
rule.setContent {
|
||||
current = rememberDiscoverState(shell, shell::enterDestination, {}, identity = identity, fixtures = false,
|
||||
loadFixture = { error("Production observer must not load fixtures") })
|
||||
}
|
||||
rule.waitUntil(30_000) {
|
||||
org.robolectric.Shadows.shadowOf(android.os.Looper.getMainLooper()).idle()
|
||||
current.snapshot.status == DiscoverStatus.Ready
|
||||
}
|
||||
rule.waitForIdle()
|
||||
rule.runOnIdle {
|
||||
assertTrue(fake.calls.any { it.url.encodedPath.endsWith("/feed") })
|
||||
assertEquals(0, current.focusedRow)
|
||||
assertEquals(0, current.column)
|
||||
current.focus(current.firstShelf)
|
||||
}
|
||||
rule.waitForIdle()
|
||||
rule.runOnIdle {
|
||||
assertNotNull(current.focusedLane)
|
||||
assertEquals(current.firstShelf, current.focusedRow)
|
||||
assertEquals(0, current.column)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue