[#71] Add re-creation test for onboarding

- Created dedicated test activity for integration tests.
- Created Onboarding integration test class with two state restoration tests.
- Moved OnboardingTestSetup to its own class.
- Filed related issues.
This commit is contained in:
Honza Rychnovsky 2022-04-14 18:34:12 +02:00 committed by GitHub
parent 07a12f8832
commit 550df810c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 189 additions and 41 deletions

View File

@ -4,6 +4,10 @@
package="co.electriccoin.zcash.ui">
<application
android:label="zcash-ui-test"/>
android:label="zcash-ui-test" >
<activity
android:name=".screen.onboarding.TestOnboardingActivity"
android:exported="false" />
</application>
</manifest>

View File

@ -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<OnboardingViewModel>()
// 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()
}
}
}

View File

@ -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<TestOnboardingActivity>()
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())
}
}

View File

@ -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()
}
}
}

View File

@ -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() }
)
}
}
}
}
}

View File

@ -132,6 +132,7 @@ class MainActivity : ComponentActivity() {
private fun WrapOnboarding() {
val onboardingViewModel by viewModels<OnboardingViewModel>()
// TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383
if (!onboardingViewModel.isImporting.collectAsState().value) {
Onboarding(
onboardingState = onboardingViewModel.onboardingState,