Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class DrawerMenuWidgetsTest {
}

@Test
fun paymentRequestsIsAvailableFromDrawerWhenPaykitIsEnabled() {
fun subscriptionsIsTheOnlyPaykitEntryInDrawerWhenPaykitIsEnabled() {
composeTestRule.setContent {
val navController = rememberNavController()
val drawerState = rememberDrawerState(DrawerValue.Open)
Expand All @@ -166,8 +166,8 @@ class DrawerMenuWidgetsTest {
composable<Routes.Home> {
Text("Home", modifier = Modifier.testTag("HomeRoute"))
}
composable<Routes.PaymentRequests> {
Text("Payment Requests", modifier = Modifier.testTag("PaymentRequestsRoute"))
composable<Routes.Subscriptions> {
Text("Subscriptions", modifier = Modifier.testTag("SubscriptionsRoute"))
}
}
DrawerMenu(
Expand All @@ -182,14 +182,13 @@ class DrawerMenuWidgetsTest {
}
}

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

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

@Test
fun paymentRequestsIsHiddenFromDrawerWhenPaykitIsDisabled() {
fun paykitEntriesAreHiddenFromDrawerWhenPaykitIsDisabled() {
composeTestRule.setContent {
val navController = rememberNavController()
val drawerState = rememberDrawerState(DrawerValue.Open)
Expand All @@ -207,7 +206,7 @@ class DrawerMenuWidgetsTest {
}
}

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

Expand Down
36 changes: 36 additions & 0 deletions app/src/androidTest/java/to/bitkit/ui/components/SheetHostTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.platform.testTag
Expand Down Expand Up @@ -84,4 +85,39 @@ class SheetHostTest {
assertEquals(0, dismissCount)
assertEquals(0, backgroundClickCount)
}

@Test
fun programmaticHideDoesNotInvokeDismissalCallback() {
val shouldExpand = mutableStateOf(true)
val visibilityKey = mutableStateOf<Any?>("subscription")
var dismissCount = 0
composeTestRule.setContent {
AppThemeSurface {
SheetHost(
shouldExpand = shouldExpand.value,
onDismiss = { dismissCount++ },
visibilityKey = visibilityKey.value,
sheets = {
Box(
modifier = Modifier
.fillMaxWidth()
.height(320.dp)
.testTag("ProgrammaticSheet")
)
},
content = { Box(Modifier.fillMaxSize()) },
)
}
}
composeTestRule.onNodeWithTag("ProgrammaticSheet").assertIsDisplayed()

composeTestRule.runOnIdle {
shouldExpand.value = false
visibilityKey.value = null
}
composeTestRule.mainClock.advanceTimeBy(1_000)
composeTestRule.waitForIdle()

assertEquals(0, dismissCount)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,75 @@ import to.bitkit.ui.theme.AppThemeSurface
import to.bitkit.viewmodels.AmountInputViewModel
import kotlin.time.ExperimentalTime
import kotlin.time.Instant
import kotlin.test.assertEquals

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

@Test
fun detailsShowsAmountNoteExpiryAndContinue() {
fun detailsShowsAmountNoteExpiryAndSend() {
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestDetailsContent(
amountInputViewModel = AmountInputViewModel(AmountInputHandler.stub()),
initialDraft = draft,
contact = PubkyProfile.placeholder(target.publicKey),
isCreating = false,
onBack = {},
onContinue = {},
onEditAmount = {},
onSend = {},
)
}
}

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

composeTestRule.onNodeWithTag("PaymentRequestEditAmount").performClick()
@Test
fun amountShowsNumberPadAndContinue() {
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestAmountContent(
amountInputViewModel = AmountInputViewModel(AmountInputHandler.stub()),
initialDraft = draft,
contact = PubkyProfile.placeholder(target.publicKey),
onBack = {},
onContinue = {},
)
}
}

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

@Test
fun recipientShowsEligibleContactAndSendAction() {
fun recipientShowsEligibleContactAndAdvancesOnSelection() {
var selectedTarget: PaykitPaymentRequestTarget? = null
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestRecipientContent(
targets = persistentListOf(target),
contacts = persistentListOf(PubkyProfile.placeholder(target.publicKey)),
isCreating = false,
onEditExpiration = {},
onBack = {},
onPaste = { target.publicKey },
onSend = {},
onSelected = { selectedTarget = it },
)
}
}

composeTestRule.onNodeWithTag("PaymentRequestContact${target.publicKey}").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestRecipientSearch").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestEditExpiration").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestRecipientPaste", useUnmergedTree = true).assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestSend").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestSend").assertDoesNotExist()
composeTestRule.onNodeWithTag("PaymentRequestContact${target.publicKey}").performClick()
assertEquals(target, selectedTarget)

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

Expand All @@ -81,11 +99,12 @@ class CreatePaymentRequestScreenTest {

@Test
fun sentShowsSuccessSurface() {
val contact = PubkyProfile.forDisplay(target.publicKey, "Anna", imageUrl = null)
composeTestRule.setContent {
AppThemeSurface {
PaymentRequestSentContent(
request = request.copy(deliveryStatus = PaykitPaymentRequestDeliveryStatus.Sent),
contact = PubkyProfile.placeholder(target.publicKey),
contact = contact,
onDone = {},
)
}
Expand All @@ -94,7 +113,8 @@ class CreatePaymentRequestScreenTest {
composeTestRule.onNodeWithTag("PaymentRequestSent").assertIsDisplayed()
composeTestRule.onNodeWithTag("PaymentRequestSentCheck").assertIsDisplayed()
composeTestRule.onNodeWithText("PAYMENT REQUESTED").assertIsDisplayed()
composeTestRule.onNodeWithText("Waiting for payment").assertIsDisplayed()
composeTestRule.onNodeWithText("Anna").assertIsDisplayed()
composeTestRule.onNodeWithText("Dinner").assertIsDisplayed()
}

private val draft = PaykitPaymentRequestDraft(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ import com.synonym.paykit.PaymentRequestLifecycleState
import kotlinx.collections.immutable.persistentListOf
import org.junit.Rule
import org.junit.Test
import to.bitkit.models.PubkyProfile
import to.bitkit.repositories.PaykitBillingPeriod
import to.bitkit.repositories.PaykitPaymentRequest
import to.bitkit.repositories.PaykitPaymentRequestDeliveryStatus
import to.bitkit.repositories.PaykitPaymentRequestDirection
import to.bitkit.repositories.PaykitRecurrenceUnit
import to.bitkit.repositories.PaykitSubscription
import to.bitkit.repositories.PaykitSubscriptionMetadata
import to.bitkit.repositories.PaykitSubscriptionRecurrence
import to.bitkit.test.annotations.ComposeUi
import to.bitkit.ui.theme.AppThemeSurface
import kotlin.time.Clock
Expand All @@ -36,10 +42,12 @@ class PaymentRequestsScreenTest {
PaymentRequestsSheetContent(
requests = persistentListOf(request),
contacts = persistentListOf(),
subscriptions = persistentListOf(),
onNotNow = {},
onSeeAll = {},
onPay = {},
onReject = { Result.success(Unit) },
onDismiss = { Result.success(Unit) },
onDetails = {},
)
}
}
Expand All @@ -51,6 +59,37 @@ class PaymentRequestsScreenTest {
composeTestRule.onNodeWithText("Dismiss").assertIsDisplayed()
}

@Test
fun recurringQueueCardShowsProviderThenSubscriptionName() {
val contact = PubkyProfile.forDisplay(request().counterparty, "Coffee House", imageUrl = null)
val subscription = subscription(note = "Weekly coffee")
val recurringRequest = request(id = subscription.paymentRequestId).copy(
lifecycleState = PaymentRequestLifecycleState.ACTIVE_RECURRING,
billingPeriod = PaykitBillingPeriod(
startsAt = Instant.parse("2027-01-15T08:00:00Z"),
endsAt = Instant.parse("2027-01-22T08:00:00Z"),
),
)

composeTestRule.setContent {
PaymentRequestsTestSurface {
PaymentRequestsSheetContent(
requests = persistentListOf(recurringRequest),
contacts = persistentListOf(contact),
subscriptions = persistentListOf(subscription),
onNotNow = {},
onSeeAll = {},
onPay = {},
onDismiss = { Result.success(Unit) },
onDetails = {},
)
}
}

composeTestRule.onNodeWithText("Coffee House").assertIsDisplayed()
composeTestRule.onNodeWithText("Weekly coffee").assertIsDisplayed()
}

@Test
fun historyGroupsCompletedRequestsAndKeepsActiveOutgoingRequests() {
val now = Clock.System.now()
Expand All @@ -70,11 +109,13 @@ class PaymentRequestsScreenTest {
requests = persistentListOf(outgoing, accepted),
pending = persistentListOf(),
contacts = persistentListOf(),
subscriptions = persistentListOf(),
canRequestPayment = true,
onBack = {},
onRequestPayment = {},
onPay = {},
onReject = { Result.success(Unit) },
onDismiss = { Result.success(Unit) },
onDetails = {},
)
}
}
Expand All @@ -95,11 +136,13 @@ class PaymentRequestsScreenTest {
requests = persistentListOf(),
pending = persistentListOf(),
contacts = persistentListOf(),
subscriptions = persistentListOf(),
canRequestPayment = true,
onBack = {},
onRequestPayment = {},
onPay = {},
onReject = { Result.success(Unit) },
onDismiss = { Result.success(Unit) },
onDetails = {},
)
}
}
Expand All @@ -120,19 +163,21 @@ class PaymentRequestsScreenTest {
requests = persistentListOf(),
pending = persistentListOf(),
contacts = persistentListOf(),
subscriptions = persistentListOf(),
canRequestPayment = false,
onBack = {},
onRequestPayment = {},
onPay = {},
onReject = { Result.success(Unit) },
onDismiss = { Result.success(Unit) },
onDetails = {},
)
}
}

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

private fun request(id: String) = PaykitPaymentRequest(
private fun request(id: String = "request") = PaykitPaymentRequest(
paymentRequestId = id,
counterparty = "pubky3rsduhcxpw74snwyct86m38c63j3pq8x4ycqikxg64roik8yw5xg",
counterpartyReceiverPath = "bitkit/wallet",
Expand All @@ -143,6 +188,28 @@ class PaymentRequestsScreenTest {
expiresAt = null,
acceptedPaymentEndpointIdentifiers = listOf("btc-lightning-bolt11"),
)

private fun subscription(note: String) = PaykitSubscription(
paymentRequestId = "subscription",
counterparty = request().counterparty,
counterpartyReceiverPath = "bitkit/wallet",
amountValue = "0.00025",
amountSats = 25_000uL,
note = note,
createdAt = Instant.parse("2027-01-15T08:00:00Z"),
proposalExpiresAt = null,
recurrence = PaykitSubscriptionRecurrence(
every = 1,
unit = PaykitRecurrenceUnit.Week,
startsAt = Instant.parse("2027-01-15T08:00:00Z"),
anchor = Instant.parse("2027-01-15T08:00:00Z"),
endsAt = null,
),
metadata = PaykitSubscriptionMetadata(description = null, benefits = emptyList()),
acceptedPaymentEndpointIdentifiers = listOf("btc-lightning-bolt11"),
lifecycleState = PaymentRequestLifecycleState.ACTIVE_RECURRING,
paidPeriods = emptyList(),
)
}

@Composable
Expand Down
Loading
Loading