secant-android-wallet/ui-lib/src/androidTest/java/cash/z/ecc/ui/screen/restore/view/RestoreViewTest.kt

235 lines
7.0 KiB
Kotlin
Raw Normal View History

2021-12-09 12:21:30 -08:00
package cash.z.ecc.ui.screen.restore.view
import android.content.Context
import android.view.inputmethod.InputMethodManager
import androidx.compose.ui.test.assertIsFocused
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.MediumTest
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.sdk.fixture.SeedPhraseFixture
import cash.z.ecc.sdk.model.SeedPhrase
import cash.z.ecc.ui.R
import cash.z.ecc.ui.screen.common.CommonTag
import cash.z.ecc.ui.screen.restore.RestoreTag
import cash.z.ecc.ui.screen.restore.state.WordList
import cash.z.ecc.ui.test.getStringResource
import cash.z.ecc.ui.theme.ZcashTheme
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import java.util.Locale
class RestoreViewTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
@MediumTest
fun keyboard_appears_on_launch() {
newTestSetup(emptyList())
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.assertIsFocused()
}
val inputMethodManager = ApplicationProvider.getApplicationContext<Context>().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
assertTrue(inputMethodManager.isAcceptingText)
}
@Test
@MediumTest
fun autocomplete_suggestions_appear() {
newTestSetup(emptyList())
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.performTextInput("ab")
// Make sure text isn't cleared
it.assertTextContains("ab")
}
composeTestRule.onNode(hasText("abandon") and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)).also {
it.assertExists()
}
composeTestRule.onNode(hasText("able") and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)).also {
it.assertExists()
}
}
@Test
@MediumTest
fun choose_autocomplete() {
newTestSetup(emptyList())
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.performTextInput("ab")
}
composeTestRule.onNode(hasText("abandon") and hasTestTag(RestoreTag.AUTOCOMPLETE_ITEM)).also {
it.performClick()
}
composeTestRule.onNodeWithTag(RestoreTag.AUTOCOMPLETE_LAYOUT).also {
it.assertDoesNotExist()
}
composeTestRule.onNode(hasText("abandon") and hasTestTag(CommonTag.CHIP), useUnmergedTree = true).also {
it.assertExists()
}
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.assertTextEquals("")
}
}
@Test
@MediumTest
fun type_full_word() {
newTestSetup(emptyList())
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.performTextInput("abandon")
}
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.assertTextEquals("")
}
composeTestRule.onNodeWithTag(RestoreTag.AUTOCOMPLETE_LAYOUT).also {
it.assertDoesNotExist()
}
composeTestRule.onNode(hasText("abandon") and hasTestTag(CommonTag.CHIP), useUnmergedTree = true).also {
it.assertExists()
}
composeTestRule.onNodeWithTag(RestoreTag.SEED_WORD_TEXT_FIELD).also {
it.assertTextEquals("")
}
}
@Test
@MediumTest
fun invalid_phrase_does_not_progress() {
newTestSetup(generateSequence { "abandon" }.take(SeedPhrase.SEED_PHRASE_SIZE).toList())
composeTestRule.onNodeWithText(getStringResource(R.string.restore_complete_header)).also {
it.assertDoesNotExist()
}
}
@Test
@MediumTest
fun finish_appears_after_24_words() {
newTestSetup(SeedPhraseFixture.new().split)
composeTestRule.onNodeWithText(getStringResource(R.string.restore_complete_header)).also {
it.assertExists()
}
}
@Test
@MediumTest
fun click_take_to_wallet() {
val testSetup = newTestSetup(SeedPhraseFixture.new().split)
assertEquals(0, testSetup.getOnFinishedCount())
composeTestRule.onNodeWithText(getStringResource(R.string.restore_button_see_wallet)).also {
it.performClick()
}
assertEquals(1, testSetup.getOnFinishedCount())
}
@Test
@MediumTest
fun back() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.restore_back_content_description)).also {
it.performClick()
}
assertEquals(1, testSetup.getOnBackCount())
}
@Test
@MediumTest
fun clear() {
newTestSetup(listOf("abandon"))
composeTestRule.onNode(hasText("abandon") and hasTestTag(CommonTag.CHIP), useUnmergedTree = true).also {
it.assertExists()
}
composeTestRule.onNodeWithText(getStringResource(R.string.restore_button_clear)).also {
it.performClick()
}
composeTestRule.onNode(hasText("abandon") and hasTestTag(CommonTag.CHIP), useUnmergedTree = true).also {
it.assertDoesNotExist()
}
}
private fun newTestSetup(initialState: List<String> = emptyList()) = TestSetup(composeTestRule, initialState)
private class TestSetup(private val composeTestRule: ComposeContentTestRule, initialState: List<String>) {
private val state = WordList(initialState)
private var onBackCount = 0
private var onFinishedCount = 0
fun getUserInputWords(): List<String> {
composeTestRule.waitForIdle()
return state.current.value
}
fun getOnBackCount(): Int {
composeTestRule.waitForIdle()
return onBackCount
}
fun getOnFinishedCount(): Int {
composeTestRule.waitForIdle()
return onFinishedCount
}
init {
composeTestRule.setContent {
ZcashTheme {
RestoreWallet(
Mnemonics.getCachedWords(Locale.ENGLISH.language).toSortedSet(),
state,
onBack = {
onBackCount++
},
paste = { "" },
onFinished = {
onFinishedCount++
},
)
}
}
}
}
}