diff --git a/ui-lib/src/androidTest/AndroidManifest.xml b/ui-lib/src/androidTest/AndroidManifest.xml index 0eb99368..a6743563 100644 --- a/ui-lib/src/androidTest/AndroidManifest.xml +++ b/ui-lib/src/androidTest/AndroidManifest.xml @@ -4,6 +4,10 @@ package="co.electriccoin.zcash.ui"> + android:label="zcash-ui-test" > + + diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/TestOnboardingActivity.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/TestOnboardingActivity.kt new file mode 100644 index 00000000..d8780cf8 --- /dev/null +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/TestOnboardingActivity.kt @@ -0,0 +1,53 @@ +package co.electriccoin.zcash.ui.screen.onboarding + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.viewModels +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import co.electriccoin.zcash.ui.design.component.GradientSurface +import co.electriccoin.zcash.ui.design.theme.ZcashTheme +import co.electriccoin.zcash.ui.screen.onboarding.view.Onboarding +import co.electriccoin.zcash.ui.screen.onboarding.viewmodel.OnboardingViewModel + +class TestOnboardingActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setupUiContent() + } + + private fun setupUiContent() { + setContent { + ZcashTheme { + GradientSurface( + Modifier + .fillMaxWidth() + .fillMaxHeight() + ) { + WrapOnboarding() + } + } + } + } + + @Composable + private fun WrapOnboarding() { + val onboardingViewModel by viewModels() + + // TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383 + if (!onboardingViewModel.isImporting.collectAsState().value) { + Onboarding( + onboardingState = onboardingViewModel.onboardingState, + onImportWallet = { onboardingViewModel.isImporting.value = true }, + onCreateWallet = {} + ) + + reportFullyDrawn() + } + } +} diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingIntegrationTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingIntegrationTest.kt new file mode 100644 index 00000000..b90e8415 --- /dev/null +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingIntegrationTest.kt @@ -0,0 +1,72 @@ +package co.electriccoin.zcash.ui.screen.onboarding.view + +import androidx.compose.ui.test.junit4.StateRestorationTester +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.filters.MediumTest +import co.electriccoin.zcash.ui.R +import co.electriccoin.zcash.ui.screen.onboarding.TestOnboardingActivity +import co.electriccoin.zcash.ui.screen.onboarding.model.OnboardingStage +import co.electriccoin.zcash.ui.test.getStringResource +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test + +// TODO [#382]: https://github.com/zcash/secant-android-wallet/issues/382 +class OnboardingIntegrationTest { + @get:Rule + val composeTestRule = createAndroidComposeRule() + + private fun newTestSetup(initialStage: OnboardingStage) = OnboardingTestSetup(composeTestRule, initialStage) + + /** + * The test semantics are built upon StateRestorationTester component. We simulate screen state + * restoration with method emulateSavedInstanceStateRestore(), which needs to have setContent() + * method called beforehand. Then, after state restores after emulateSavedInstanceStateRestore(), + * setContent() callback is called again. + */ + @Test + @MediumTest + fun current_stage_restoration() { + val restorationTester = StateRestorationTester(composeTestRule) + val testSetup = newTestSetup(OnboardingStage.UnifiedAddresses) + + restorationTester.setContent { + testSetup.getDefaultContent() + } + + assertEquals(OnboardingStage.UnifiedAddresses, testSetup.getOnboardingStage()) + + composeTestRule.onNodeWithText(getStringResource(R.string.onboarding_next)).also { + it.performClick() + } + + assertEquals(OnboardingStage.More, testSetup.getOnboardingStage()) + + restorationTester.emulateSavedInstanceStateRestore() + + assertEquals(OnboardingStage.More, testSetup.getOnboardingStage()) + } + + @Test + @MediumTest + fun current_stage_restoration_activity() { + val testSetup = newTestSetup(OnboardingStage.ShieldedByDefault) + testSetup.setDefaultContent() + + assertEquals(OnboardingStage.ShieldedByDefault, testSetup.getOnboardingStage()) + + composeTestRule.onNodeWithText(getStringResource(R.string.onboarding_next)).also { + it.performClick() + } + + assertEquals(OnboardingStage.UnifiedAddresses, testSetup.getOnboardingStage()) + + composeTestRule.activityRule.scenario.onActivity { + it.recreate() + } + + assertEquals(OnboardingStage.UnifiedAddresses, testSetup.getOnboardingStage()) + } +} diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingTestSetup.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingTestSetup.kt new file mode 100644 index 00000000..ba301fe7 --- /dev/null +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingTestSetup.kt @@ -0,0 +1,52 @@ +package co.electriccoin.zcash.ui.screen.onboarding.view + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.junit4.ComposeContentTestRule +import co.electriccoin.zcash.ui.design.theme.ZcashTheme +import co.electriccoin.zcash.ui.screen.onboarding.model.OnboardingStage +import co.electriccoin.zcash.ui.screen.onboarding.state.OnboardingState +import java.util.concurrent.atomic.AtomicInteger + +class OnboardingTestSetup( + private val composeTestRule: ComposeContentTestRule, + initialStage: OnboardingStage +) { + private val onboardingState = OnboardingState(initialStage) + + private val onCreateWalletCallbackCount = AtomicInteger(0) + private val onImportWalletCallbackCount = AtomicInteger(0) + + fun getOnCreateWalletCallbackCount(): Int { + composeTestRule.waitForIdle() + return onCreateWalletCallbackCount.get() + } + + fun getOnImportWalletCallbackCount(): Int { + composeTestRule.waitForIdle() + return onImportWalletCallbackCount.get() + } + + fun getOnboardingStage(): OnboardingStage { + composeTestRule.waitForIdle() + return onboardingState.current.value + } + + @SuppressLint("ComposableNaming") + @Composable + fun getDefaultContent() { + ZcashTheme { + Onboarding( + onboardingState, + onCreateWallet = { onCreateWalletCallbackCount.incrementAndGet() }, + onImportWallet = { onImportWalletCallbackCount.incrementAndGet() } + ) + } + } + + fun setDefaultContent() { + composeTestRule.setContent { + getDefaultContent() + } + } +} diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingViewTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingViewTest.kt index 5b0653cf..0f982c49 100644 --- a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingViewTest.kt +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/onboarding/view/OnboardingViewTest.kt @@ -2,25 +2,27 @@ package co.electriccoin.zcash.ui.screen.onboarding.view import androidx.compose.ui.test.assertHasClickAction import androidx.compose.ui.test.assertIsEnabled -import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.filters.MediumTest import co.electriccoin.zcash.ui.R -import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.screen.onboarding.model.OnboardingStage -import co.electriccoin.zcash.ui.screen.onboarding.state.OnboardingState import co.electriccoin.zcash.ui.test.getStringResource import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test -import java.util.concurrent.atomic.AtomicInteger class OnboardingViewTest { @get:Rule val composeTestRule = createComposeRule() + private fun newTestSetup(initialStage: OnboardingStage): OnboardingTestSetup { + return OnboardingTestSetup(composeTestRule, initialStage).apply { + setDefaultContent() + } + } + // Sanity check the TestSetup @Test @MediumTest @@ -238,40 +240,4 @@ class OnboardingViewTest { assertEquals(OnboardingStage.Wallet, testSetup.getOnboardingStage()) } - - private fun newTestSetup(initalStage: OnboardingStage) = TestSetup(composeTestRule, initalStage) - - private class TestSetup(private val composeTestRule: ComposeContentTestRule, initalStage: OnboardingStage) { - private val onboardingState = OnboardingState(initalStage) - - private val onCreateWalletCallbackCount = AtomicInteger(0) - private val onImportWalletCallbackCount = AtomicInteger(0) - - fun getOnCreateWalletCallbackCount(): Int { - composeTestRule.waitForIdle() - return onCreateWalletCallbackCount.get() - } - - fun getOnImportWalletCallbackCount(): Int { - composeTestRule.waitForIdle() - return onImportWalletCallbackCount.get() - } - - fun getOnboardingStage(): OnboardingStage { - composeTestRule.waitForIdle() - return onboardingState.current.value - } - - init { - composeTestRule.setContent { - ZcashTheme { - Onboarding( - onboardingState, - onCreateWallet = { onCreateWalletCallbackCount.incrementAndGet() }, - onImportWallet = { onImportWalletCallbackCount.incrementAndGet() } - ) - } - } - } - } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/MainActivity.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/MainActivity.kt index b94fffc4..338267a1 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/MainActivity.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/MainActivity.kt @@ -132,6 +132,7 @@ class MainActivity : ComponentActivity() { private fun WrapOnboarding() { val onboardingViewModel by viewModels() + // TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383 if (!onboardingViewModel.isImporting.collectAsState().value) { Onboarding( onboardingState = onboardingViewModel.onboardingState,