[#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">
|
package="co.electriccoin.zcash.ui">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="zcash-ui-test"/>
|
android:label="zcash-ui-test" >
|
||||||
|
<activity
|
||||||
|
android:name=".screen.onboarding.TestOnboardingActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</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.assertHasClickAction
|
||||||
import androidx.compose.ui.test.assertIsEnabled
|
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.junit4.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.test.performClick
|
import androidx.compose.ui.test.performClick
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import co.electriccoin.zcash.ui.R
|
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.model.OnboardingStage
|
||||||
import co.electriccoin.zcash.ui.screen.onboarding.state.OnboardingState
|
|
||||||
import co.electriccoin.zcash.ui.test.getStringResource
|
import co.electriccoin.zcash.ui.test.getStringResource
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
class OnboardingViewTest {
|
class OnboardingViewTest {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
|
private fun newTestSetup(initialStage: OnboardingStage): OnboardingTestSetup {
|
||||||
|
return OnboardingTestSetup(composeTestRule, initialStage).apply {
|
||||||
|
setDefaultContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check the TestSetup
|
// Sanity check the TestSetup
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
|
@ -238,40 +240,4 @@ class OnboardingViewTest {
|
||||||
|
|
||||||
assertEquals(OnboardingStage.Wallet, testSetup.getOnboardingStage())
|
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() {
|
private fun WrapOnboarding() {
|
||||||
val onboardingViewModel by viewModels<OnboardingViewModel>()
|
val onboardingViewModel by viewModels<OnboardingViewModel>()
|
||||||
|
|
||||||
|
// TODO [#383]: https://github.com/zcash/secant-android-wallet/issues/383
|
||||||
if (!onboardingViewModel.isImporting.collectAsState().value) {
|
if (!onboardingViewModel.isImporting.collectAsState().value) {
|
||||||
Onboarding(
|
Onboarding(
|
||||||
onboardingState = onboardingViewModel.onboardingState,
|
onboardingState = onboardingViewModel.onboardingState,
|
||||||
|
|
Loading…
Reference in New Issue