diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d1c5cf3..6c5de0d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -141,7 +141,6 @@ dependencies { ksp(libs.hilt.compiler) testImplementation("androidx.compose.ui:ui-test-junit4") - debugImplementation("androidx.compose.ui:ui-test-manifest") testImplementation(libs.kotlin.test) testImplementation(libs.junit) testImplementation(libs.kotlinx.coroutines.test) diff --git a/app/src/test/kotlin/tv/streamer/app/storage/StorageStartupScreenTest.kt b/app/src/test/kotlin/tv/streamer/app/storage/StorageStartupScreenTest.kt index 409afc8..a40e349 100644 --- a/app/src/test/kotlin/tv/streamer/app/storage/StorageStartupScreenTest.kt +++ b/app/src/test/kotlin/tv/streamer/app/storage/StorageStartupScreenTest.kt @@ -1,6 +1,7 @@ package tv.streamer.app.storage import android.app.Application +import android.content.ComponentName import androidx.activity.ComponentActivity import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf @@ -15,7 +16,10 @@ import kotlinx.coroutines.awaitCancellation import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.junit.rules.ExternalResource +import org.junit.rules.RuleChain import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows.shadowOf import org.robolectric.annotation.Config import tv.streamer.app.home.HomeScreen import tv.streamer.core.database.LibraryStore @@ -26,7 +30,19 @@ import kotlin.test.assertEquals @Config(sdk = [28], application = Application::class) @OptIn(ExperimentalTestApi::class) class StorageStartupScreenTest { - @get:Rule val compose = createAndroidComposeRule() + private val compose = createAndroidComposeRule() + + // Unit-test AAR manifests are not merged into the app manifest. Register the + // host only in Robolectric, before ActivityScenario launches, for any variant. + // No test activity declaration or ui-test-manifest dependency ships in an APK. + @get:Rule val rules: RuleChain = RuleChain.outerRule(object : ExternalResource() { + override fun before() { + val context = ApplicationProvider.getApplicationContext() + shadowOf(context.packageManager).addActivityIfNotPresent( + ComponentName(context, ComponentActivity::class.java) + ) + } + }).around(compose) @Test fun loadingFailureRetryThenHomePreservesBackBehavior() { val context = ApplicationProvider.getApplicationContext() diff --git a/docs/app-storage-startup.md b/docs/app-storage-startup.md index 1f0c0f3..2a5be8e 100644 --- a/docs/app-storage-startup.md +++ b/docs/app-storage-startup.md @@ -116,10 +116,19 @@ Robolectric/controller coverage includes: Passed with the installed SDK supplied through `ANDROID_HOME`: ```sh -ANDROID_HOME=/home/dev/android-sdk ./gradlew :app:testDebugUnitTest :app:assembleDebug :core:database:testDebugUnitTest :core:model:test :merge:test --max-workers=2 +ANDROID_HOME=/home/dev/android-sdk ./gradlew test :app:assembleDebug --max-workers=2 --console=plain git diff --check ``` +The landing gate includes all test variants: 16 app tests pass in each of debug and +release, with no skips or exclusions. `StorageStartupScreenTest` registers its generic +`ComponentActivity` host only in Robolectric's package manager via an outer JUnit rule, +before the Compose rule launches ActivityScenario. This replaces the debug-only +`ui-test-manifest` dependency; merely moving that AAR to `testImplementation` did not +merge its activity declaration in this build. Test bodies and assertions are unchanged. +The release packaged manifest was checked: only HomeActivity and DetailActivity are +declared, not the generic test host. No test activity declaration ships in the release APK. + ## Remaining acceptance (device required) Host tests do **not** establish physical-TV acceptance. Before claiming the full startup / diff --git a/handoff.md b/handoff.md index 26c9793..e0720a9 100644 --- a/handoff.md +++ b/handoff.md @@ -2,9 +2,20 @@ ## Resume Here -HOST integration goal is met and verified on `track/app-storage-startup`. Next step for -this bounded deliverable is `/land` review; full physical-device acceptance remains blocked -on access to target hardware and must not be represented as complete. +HOST integration and the all-variant landing-gate fix are verified on this track. +Next step is `/land` via the coordinator, who owns the later rebase onto main (which now +contains provider-progress). No merge/rebase/main/core edits were performed here. +Physical-device acceptance remains blocked on target hardware and is not complete. + +Latest narrow fix: removed debugImplementation(ui-test-manifest); an outer JUnit RuleChain +registers ComponentActivity only in Robolectric's package manager before the Compose rule +launches ActivityScenario. Moving the AAR to testImplementation alone was tried and failed +with the same 3 release errors, so that attempt was replaced. All original test methods and +assertions remain enabled and unchanged. Release packaged manifest contains only HomeActivity +and DetailActivity, with no test host declaration. Dedicated doc updated. + +Note: handoff.md is tracked in this worktree (git ls-files), not ignored; its update is +included in the fix commit. The coordinator already integrated provider-progress tip `466a44d` via `07e163b` before this session. The former merge/core-dependency blocker is stale and resolved. This session @@ -33,12 +44,12 @@ performed no merge/rebase/push or other-worktree edits. No core or credentials c Passed: ```sh -ANDROID_HOME=/home/dev/android-sdk ./gradlew :app:testDebugUnitTest :app:assembleDebug :core:database:testDebugUnitTest :core:model:test :merge:test --max-workers=2 +ANDROID_HOME=/home/dev/android-sdk ./gradlew test :app:assembleDebug --max-workers=2 --console=plain git diff --check ``` -16 app tests passed; database tests and assembly passed; model/merge tests passed via Gradle -cache/up-to-date results. Initial new Home retry tests timed out using semantic performClick +Latest full authorized gate passed: 16 app tests in debug and 16 in release, zero failures, +errors or skips; debug assembly passed. Other module tests passed via up-to-date results. Initial new Home retry tests timed out using semantic performClick on TV Button; changed to the actual focused D-pad center activation, then the entire required command passed. No unresolved host failures or core defect found.