package co.electriccoin.zcash.ui.screen.request.view import androidx.compose.ui.test.assertIsNotEnabled 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.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextClearance import androidx.compose.ui.test.performTextInput import androidx.test.filters.MediumTest import cash.z.ecc.android.sdk.fixture.WalletAddressFixture import cash.z.ecc.android.sdk.model.MonetarySeparators import cash.z.ecc.android.sdk.model.Zatoshi import cash.z.ecc.sdk.fixture.ZecRequestFixture import cash.z.ecc.sdk.model.ZecRequest import cash.z.ecc.sdk.model.ZecRequestMessage import co.electriccoin.zcash.test.UiTestPrerequisites import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.test.getStringResource import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import java.util.concurrent.atomic.AtomicInteger import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue class RequestViewTest : UiTestPrerequisites() { @get:Rule val composeTestRule = createComposeRule() @Test @MediumTest fun create_button_disabled() { @Suppress("UNUSED_VARIABLE") val testSetup = TestSetup(composeTestRule) composeTestRule.assertSendDisabled() } @Test @MediumTest @OptIn(ExperimentalCoroutinesApi::class) fun create_request_no_message() = runTest { val testSetup = TestSetup(composeTestRule) assertEquals(0, testSetup.getOnCreateCount()) assertEquals(null, testSetup.getLastCreateZecRequest()) composeTestRule.setValidAmount() composeTestRule.clickCreateAndSend() assertEquals(1, testSetup.getOnCreateCount()) testSetup.getLastCreateZecRequest().also { assertNotNull(it) assertEquals(WalletAddressFixture.unified(), it.address) assertEquals(Zatoshi(12345600000), it.amount) assertTrue(it.message.value.isEmpty()) } } @Test @MediumTest @OptIn(ExperimentalCoroutinesApi::class) fun create_request_with_message() = runTest { val testSetup = TestSetup(composeTestRule) assertEquals(0, testSetup.getOnCreateCount()) assertEquals(null, testSetup.getLastCreateZecRequest()) composeTestRule.setValidAmount() composeTestRule.setValidMessage() composeTestRule.clickCreateAndSend() assertEquals(1, testSetup.getOnCreateCount()) testSetup.getLastCreateZecRequest().also { assertNotNull(it) assertEquals(WalletAddressFixture.unified(), it.address) assertEquals(Zatoshi(12345600000), it.amount) assertEquals(ZecRequestFixture.MESSAGE.value, it.message.value) } } @Test @MediumTest fun check_regex_functionality_valid_inputs() { val testSetup = TestSetup(composeTestRule) val separators = MonetarySeparators.current() assertEquals(0, testSetup.getOnCreateCount()) assertEquals(null, testSetup.getLastCreateZecRequest()) composeTestRule.setAmount("123") composeTestRule.clickCreateAndSend() assertEquals(1, testSetup.getOnCreateCount()) // e.g. 123,456 composeTestRule.setAmount("123${separators.grouping}456") composeTestRule.clickCreateAndSend() assertEquals(2, testSetup.getOnCreateCount()) // e.g. 123. composeTestRule.setAmount("123${separators.decimal}") composeTestRule.clickCreateAndSend() assertEquals(3, testSetup.getOnCreateCount()) // e.g. 123,456. composeTestRule.setAmount("123${separators.grouping}456${separators.decimal}") composeTestRule.clickCreateAndSend() assertEquals(4, testSetup.getOnCreateCount()) // e.g. 123,456.789 composeTestRule.setAmount("123${separators.grouping}456${separators.decimal}789") composeTestRule.clickCreateAndSend() assertEquals(5, testSetup.getOnCreateCount()) } @Test @MediumTest fun check_regex_functionality_invalid_inputs() { val testSetup = TestSetup(composeTestRule) val separators = MonetarySeparators.current() assertEquals(0, testSetup.getOnCreateCount()) assertEquals(null, testSetup.getLastCreateZecRequest()) composeTestRule.setAmount("aaa") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) composeTestRule.setAmount("123aaa") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) // e.g. ,. composeTestRule.setAmount("${separators.grouping}${separators.decimal}") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) // e.g. 123,. composeTestRule.setAmount("123${separators.grouping}${separators.decimal}") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) // e.g. 1,2,3 composeTestRule.setAmount("1${separators.grouping}2${separators.grouping}3") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) // e.g. 1.2.3 composeTestRule.setAmount("1${separators.decimal}2${separators.decimal}3") composeTestRule.clickCreateAndSend() assertEquals(0, testSetup.getOnCreateCount()) } @Test @MediumTest @OptIn(ExperimentalCoroutinesApi::class) fun max_message_length() = runTest { val testSetup = TestSetup(composeTestRule) composeTestRule.setValidAmount() composeTestRule.setMessage( buildString { repeat(ZecRequestMessage.MAX_MESSAGE_LENGTH + 1) { number -> append("$number") } } ) composeTestRule.clickCreateAndSend() assertEquals(1, testSetup.getOnCreateCount()) testSetup.getLastCreateZecRequest().also { assertNotNull(it) assertEquals(WalletAddressFixture.unified(), it.address) assertEquals(Zatoshi(12345600000), it.amount) assertTrue(it.message.value.isEmpty()) } } @Test @MediumTest fun back() { val testSetup = TestSetup(composeTestRule) assertEquals(0, testSetup.getOnBackCount()) composeTestRule.clickBack() assertEquals(1, testSetup.getOnBackCount()) } private class TestSetup(private val composeTestRule: ComposeContentTestRule) { private val onBackCount = AtomicInteger(0) private val onCreateCount = AtomicInteger(0) @Volatile private var onCreateZecRequest: ZecRequest? = null fun getOnBackCount(): Int { composeTestRule.waitForIdle() return onBackCount.get() } fun getOnCreateCount(): Int { composeTestRule.waitForIdle() return onCreateCount.get() } fun getLastCreateZecRequest(): ZecRequest? { composeTestRule.waitForIdle() return onCreateZecRequest } init { composeTestRule.setContent { ZcashTheme { Request( myAddress = runBlocking { WalletAddressFixture.unified() }, goBack = { onBackCount.incrementAndGet() }, onCreateAndSend = { onCreateCount.incrementAndGet() onCreateZecRequest = it } ) } } } } } private fun ComposeContentTestRule.clickBack() { onNodeWithContentDescription(getStringResource(R.string.request_back_content_description)).also { it.performClick() } } private fun ComposeContentTestRule.setValidAmount() { onNodeWithText(getStringResource(R.string.request_amount)).also { val separators = MonetarySeparators.current() it.performTextClearance() it.performTextInput("123${separators.decimal}456") } } private fun ComposeContentTestRule.setAmount(amount: String) { onNodeWithText(getStringResource(R.string.request_amount)).also { it.performTextClearance() it.performTextInput(amount) } } private fun ComposeContentTestRule.setValidMessage() { onNodeWithText(getStringResource(R.string.request_message)).also { it.performTextClearance() it.performTextInput(ZecRequestFixture.MESSAGE.value) } } private fun ComposeContentTestRule.setMessage(message: String) { onNodeWithText(getStringResource(R.string.request_message)).also { it.performTextClearance() it.performTextInput(message) } } private fun ComposeContentTestRule.clickCreateAndSend() { onNodeWithText(getStringResource(R.string.request_create), ignoreCase = true).also { it.performClick() } } private fun ComposeContentTestRule.assertSendDisabled() { onNodeWithText(getStringResource(R.string.request_create), ignoreCase = true).also { it.assertIsNotEnabled() } }