[#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:
parent
07a12f8832
commit
550df810c9
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue