Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ val e2eBackendEnv = providers.environmentVariable("E2E_BACKEND").orElse("local")
val e2eLocalHostEnv = providers.environmentVariable("E2E_LOCAL_HOST").orElse("10.0.2.2")
val e2eHomegateUrlEnv = providers.environmentVariable("E2E_HOMEGATE_URL")
.orElse(e2eLocalHostEnv.map { "http://$it:6288" })
val e2eHomeserverPubkyEnv = providers.environmentVariable("E2E_HOMESERVER_PUBKY").orElse("")
val geoEnv = envFlag("GEO", default = true)
val paykitUiDisabledEnv = envFlag("PAYKIT_UI_DISABLED", default = false)
val trezorBridgeEnv = localProp("TREZOR_BRIDGE").map { it.toBoolean().toString() }.orElse("false")
Expand Down Expand Up @@ -323,6 +324,7 @@ androidComponents {
buildConfigFields.put("E2E_BACKEND", e2eBackendEnv.stringField())
buildConfigFields.put("E2E_LOCAL_HOST", e2eLocalHostEnv.stringField())
buildConfigFields.put("E2E_HOMEGATE_URL", e2eHomegateUrlEnv.stringField())
buildConfigFields.put("E2E_HOMESERVER_PUBKY", e2eHomeserverPubkyEnv.stringField())
buildConfigFields.put("TREZOR_BRIDGE", trezorBridgeEnv.booleanField())
buildConfigFields.put("TREZOR_BRIDGE_URL", trezorBridgeUrlEnv.stringField())
buildConfigFields.put("GEO", geoEnv.booleanField())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
Expand Down Expand Up @@ -150,6 +151,64 @@ class DrawerMenuWidgetsTest {

composeTestRule.onNodeWithTag("WidgetsSheetRequested").assertIsDisplayed()
}

@Test
fun paymentRequestsIsAvailableFromDrawerWhenPaykitIsEnabled() {
composeTestRule.setContent {
val navController = rememberNavController()
val drawerState = rememberDrawerState(DrawerValue.Open)

DrawerMenuTestSurface {
NavHost(
navController = navController,
startDestination = Routes.Home,
) {
composable<Routes.Home> {
Text("Home", modifier = Modifier.testTag("HomeRoute"))
}
composable<Routes.PaymentRequests> {
Text("Payment Requests", modifier = Modifier.testTag("PaymentRequestsRoute"))
}
}
DrawerMenu(
drawerState = drawerState,
rootNavController = navController,
hasSeenWidgetsIntro = true,
hasSeenShopIntro = true,
onBeforeNavigate = {},
showWidgets = true,
isPaykitEnabled = true,
)
}
}

composeTestRule.onNodeWithText("REQUESTS").assertIsDisplayed()
composeTestRule.onNodeWithTag("DrawerPaymentRequests").performClick()

composeTestRule.onNodeWithTag("PaymentRequestsRoute").assertIsDisplayed()
}

@Test
fun paymentRequestsIsHiddenFromDrawerWhenPaykitIsDisabled() {
composeTestRule.setContent {
val navController = rememberNavController()
val drawerState = rememberDrawerState(DrawerValue.Open)

DrawerMenuTestSurface {
DrawerMenu(
drawerState = drawerState,
rootNavController = navController,
hasSeenWidgetsIntro = true,
hasSeenShopIntro = true,
onBeforeNavigate = {},
showWidgets = true,
isPaykitEnabled = false,
)
}
}

composeTestRule.onNodeWithTag("DrawerPaymentRequests").assertDoesNotExist()
}
}

@Composable
Expand Down
87 changes: 87 additions & 0 deletions app/src/androidTest/java/to/bitkit/ui/components/SheetHostTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package to.bitkit.ui.components

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.click
import androidx.compose.ui.test.junit4.v2.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeDown
import androidx.compose.ui.unit.dp
import androidx.test.espresso.Espresso.pressBack
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import to.bitkit.test.annotations.ComposeUi
import to.bitkit.ui.theme.AppThemeSurface
import kotlin.test.assertEquals

@HiltAndroidTest
@ComposeUi
class SheetHostTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)

@get:Rule
val composeTestRule = createComposeRule()

@Before
fun setup() {
hiltRule.inject()
}

@Test
fun disabledDismissalBlocksBackDragAndScrim() {
var dismissCount = 0
var backgroundClickCount = 0
composeTestRule.setContent {
AppThemeSurface {
SheetHost(
shouldExpand = true,
onDismiss = { dismissCount++ },
dismissEnabled = false,
sheets = {
Box(
modifier = Modifier
.fillMaxWidth()
.height(320.dp)
.testTag("LockedSheet")
)
},
content = {
Box(
Modifier
.fillMaxSize()
.clickable { backgroundClickCount++ }
)
},
)
}
}
composeTestRule.onNodeWithTag("LockedSheet").assertIsDisplayed()

pressBack()
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("LockedSheet").assertIsDisplayed()

composeTestRule.onNodeWithTag("LockedSheet").performTouchInput { swipeDown() }
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("LockedSheet").assertIsDisplayed()

composeTestRule.onRoot().performTouchInput { click(Offset(center.x, 50f)) }
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("LockedSheet").assertIsDisplayed()
assertEquals(0, dismissCount)
assertEquals(0, backgroundClickCount)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@file:OptIn(ExperimentalTime::class)

package to.bitkit.ui.screens.paymentrequests

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.v2.createComposeRule
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 kotlinx.collections.immutable.persistentListOf
import org.junit.Rule
import org.junit.Test
import to.bitkit.models.PubkyProfile
import to.bitkit.repositories.AmountInputHandler
import to.bitkit.repositories.PaykitPaymentRequest
import to.bitkit.repositories.PaykitPaymentRequestDeliveryStatus
import to.bitkit.repositories.PaykitPaymentRequestDraft
import to.bitkit.repositories.PaykitPaymentRequestTarget
import to.bitkit.test.annotations.ComposeUi
import to.bitkit.ui.theme.AppThemeSurface
import to.bitkit.viewmodels.AmountInputViewModel
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

@ComposeUi
class CreatePaymentRequestScreenTest {
@get:Rule
val composeTestRule = createComposeRule()

@Test
fun detailsShowsAmountNoteExpiryAndContinue() {
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestDetailsContent(
amountInputViewModel = AmountInputViewModel(AmountInputHandler.stub()),
initialDraft = draft,
onBack = {},
onContinue = {},
)
}
}

composeTestRule.onNodeWithTag("PaymentRequestAmountField").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestNote").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestExpiryWeek").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestAmountContinue").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestNumberPad").assertDoesNotExist()

composeTestRule.onNodeWithTag("PaymentRequestEditAmount").performClick()

composeTestRule.onNodeWithTag("PaymentRequestNumberPad").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestNote").assertDoesNotExist()
}

@Test
fun recipientShowsEligibleContactAndSendAction() {
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestRecipientContent(
targets = persistentListOf(target),
contacts = persistentListOf(PubkyProfile.placeholder(target.publicKey)),
isCreating = false,
onEditExpiration = {},
onPaste = { target.publicKey },
onSend = {},
)
}
}

composeTestRule.onNodeWithTag("PaymentRequestContact${target.publicKey}").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestRecipientSearch").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestEditExpiration").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestRecipientPaste").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestSend").assertIsDisplayed()

composeTestRule.onNodeWithTag("PaymentRequestRecipientSearch").performTextInput("not this contact")

composeTestRule.onNodeWithTag("PaymentRequestContact${target.publicKey}").assertDoesNotExist()
}

@Test
fun sentShowsSuccessSurface() {
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestSentContent(
request = request.copy(deliveryStatus = PaykitPaymentRequestDeliveryStatus.Sent),
contact = PubkyProfile.placeholder(target.publicKey),
onDone = {},
)
}
}

composeTestRule.onNodeWithTag("PaymentRequestSent").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestSentCheck").assertIsDisplayed()
composeTestRule.onNodeWithText("PAYMENT REQUESTED").assertIsDisplayed()
composeTestRule.onNodeWithText("Waiting for payment").assertIsDisplayed()
}

private val draft = PaykitPaymentRequestDraft(
amountSats = 25_000uL,
note = "Dinner",
expiresAt = Instant.parse("2027-01-15T09:00:00Z"),
)

private val target = PaykitPaymentRequestTarget(
publicKey = "pubky3rsduhcxpw74snwyct86m38c63j3pq8x4ycqikxg64roik8yw5xg",
receiverPath = "bitkit/wallet",
)

private val request = PaykitPaymentRequest(
paymentRequestId = "payment-request",
counterparty = target.publicKey,
counterpartyReceiverPath = target.receiverPath,
amountValue = "0.00025",
amountSats = draft.amountSats,
note = draft.note,
createdAt = Instant.parse("2027-01-15T08:00:00Z"),
expiresAt = draft.expiresAt,
acceptedPaymentEndpointIdentifiers = listOf("btc-lightning-bolt11"),
)
}
Loading
Loading