Merge main into feat-160-app-password-disclaimer
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
package org.libremail.ui.onboarding
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.libremail.R
|
||||
import org.libremail.ui.theme.LibreMailTheme
|
||||
|
||||
/**
|
||||
* Component test for [LicenseScreen] (#172), in isolation from the real onboarding nav graph (that
|
||||
* wiring — persisting acceptance, popping the license off the back stack, calling `finish()` on
|
||||
* Decline — belongs to `onboardingGraph()` in `LibreMailApp.kt`, not this composable). This test only
|
||||
* owns the screen's own contract: Agree is gated on having scrolled to the end, Decline (and back)
|
||||
* always works, and the real bundled GPL-3.0 text actually renders.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class LicenseScreenTest {
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
private fun string(resId: Int) = composeTestRule.activity.getString(resId)
|
||||
|
||||
private fun setContent(onAgree: () -> Unit = {}, onDecline: () -> Unit = {}) {
|
||||
composeTestRule.setContent {
|
||||
LibreMailTheme(darkTheme = false, dynamicColor = false) {
|
||||
LicenseScreen(onAgree = onAgree, onDecline = onDecline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun licenseText_rendersTheRealBundledGplText() {
|
||||
setContent()
|
||||
|
||||
// Proves res/raw/license.txt actually loaded, not just that some placeholder text exists —
|
||||
// an empty or missing resource would make agreeButton_isDisabledUntilScrolledToTheEnd below
|
||||
// pass for the wrong reason (nothing to scroll).
|
||||
composeTestRule.onNodeWithText("GNU GENERAL PUBLIC LICENSE", substring = true).assertExists()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun agreeButton_isDisabledUntilScrolledToTheEnd() {
|
||||
setContent()
|
||||
|
||||
composeTestRule.onNodeWithText(string(R.string.license_agree)).assertIsNotEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun agreeButton_scrolledToEnd_becomesEnabledAndInvokesOnAgree() {
|
||||
var agreed = false
|
||||
setContent(onAgree = { agreed = true })
|
||||
|
||||
composeTestRule.onNodeWithTag(LICENSE_SCROLL_END_TAG).performScrollTo()
|
||||
|
||||
composeTestRule.onNodeWithText(string(R.string.license_agree)).assertIsEnabled().performClick()
|
||||
assertTrue(agreed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun declineButton_worksWithoutScrolling_andInvokesOnDecline() {
|
||||
var declined = false
|
||||
setContent(onDecline = { declined = true })
|
||||
|
||||
// No scrolling first: Decline must never be gated the way Agree is.
|
||||
composeTestRule.onNodeWithText(string(R.string.license_decline)).assertIsEnabled().performClick()
|
||||
|
||||
assertTrue(declined)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun systemBack_invokesOnDeclineJustLikeTheButton() {
|
||||
var declined = false
|
||||
setContent(onDecline = { declined = true })
|
||||
|
||||
Espresso.pressBack()
|
||||
|
||||
assertTrue(declined)
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,12 @@ class OnboardingFlowTest {
|
||||
// Real collaborators are cheap here: the manager just wraps PowerManager and the repository
|
||||
// reads the on-device settings DataStore. This test drives its own nav graph (without the
|
||||
// battery step), so the onboarding view model's battery decision is inert for this flow.
|
||||
//
|
||||
// This hand-rolled graph starts at ONBOARDING_WELCOME directly, deliberately bypassing the
|
||||
// GPL-3.0 license gate (#172) that precedes it in the real onboardingGraph() in
|
||||
// LibreMailApp.kt: this test owns the picker → setup → finish tail, not the license screen's
|
||||
// own contract (scroll-to-agree, decline-exits, hard-gating), which LicenseScreenTest covers
|
||||
// in isolation instead.
|
||||
val appContext = composeTestRule.activity.applicationContext
|
||||
val onboarding = OnboardingViewModel(
|
||||
BatteryOptimizationManager(appContext),
|
||||
|
||||
Reference in New Issue
Block a user