235 lines
7.0 KiB
Kotlin
235 lines
7.0 KiB
Kotlin
|
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++
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|