-
Notifications
You must be signed in to change notification settings - Fork 5
fix: avoid animated switch to auto tab #1308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
35e5d21
fix: avoid animated switch to auto tab
jvsena42 beae203
fix: clear stale receive amount before opening sheet
jvsena42 47fdb14
chore: rename changelog fragment
jvsena42 fbc1dc2
test: cover receive auto tab wiring in compose
jvsena42 7ae8457
docs: add receive auto tab selection journey
jvsena42 c81d2a1
Merge remote-tracking branch 'origin/master' into fix/876-receive-aut…
jvsena42 007e933
Merge remote-tracking branch 'origin/master' into fix/876-receive-aut…
jvsena42 049c57f
docs: make auto tab journey steps prove the fix
jvsena42 c5b4923
docs: require the auto tab jump on tape to pass
jvsena42 0877e1d
Merge remote-tracking branch 'origin/master' into HEAD
jvsena42 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
99 changes: 99 additions & 0 deletions
99
app/src/androidTest/java/to/bitkit/ui/screens/wallets/receive/ReceiveAutoTabSelectionTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| package to.bitkit.ui.screens.wallets.receive | ||
|
|
||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.setValue | ||
| import androidx.compose.ui.test.assertIsDisplayed | ||
| import androidx.compose.ui.test.junit4.createComposeRule | ||
| import androidx.compose.ui.test.onAllNodesWithTag | ||
| import androidx.compose.ui.test.onNodeWithTag | ||
| import androidx.compose.ui.test.performClick | ||
| import kotlinx.collections.immutable.persistentListOf | ||
| import org.junit.Rule | ||
| import org.junit.Test | ||
| import to.bitkit.ext.createChannelDetails | ||
| import to.bitkit.models.NodeLifecycleState | ||
| import to.bitkit.repositories.LightningState | ||
| import to.bitkit.repositories.WalletState | ||
| import to.bitkit.test.annotations.ComposeUi | ||
| import to.bitkit.ui.theme.AppThemeSurface | ||
| import kotlin.test.assertEquals | ||
|
|
||
| @ComposeUi | ||
| class ReceiveAutoTabSelectionTest { | ||
| @get:Rule | ||
| val composeTestRule = createComposeRule() | ||
|
|
||
| private var lightningState by mutableStateOf(STATE_WITHOUT_INBOUND) | ||
| private val editedTabs = mutableListOf<ReceiveTab>() | ||
|
|
||
| @Test | ||
| fun keepsTabPickedByTapWhenAutoBecomesAvailable() { | ||
| setContent() | ||
|
|
||
| composeTestRule.onNodeWithTag("Tab-spending").performClick() | ||
| composeTestRule.onNodeWithTag("Tab-savings").performClick() | ||
| composeTestRule.waitForIdle() | ||
|
|
||
| makeAutoAvailable() | ||
|
|
||
| assertEquals(ReceiveTab.SAVINGS, selectedTab()) | ||
| } | ||
|
|
||
| @Test | ||
| fun jumpsToAutoWhenNoTabWasPicked() { | ||
| setContent() | ||
| composeTestRule.waitForIdle() | ||
|
|
||
| makeAutoAvailable() | ||
|
|
||
| assertEquals(ReceiveTab.AUTO, selectedTab()) | ||
| } | ||
|
|
||
| private fun setContent() { | ||
| composeTestRule.setContent { | ||
| AppThemeSurface { | ||
| ReceiveQrScreen( | ||
| cjitInvoice = null, | ||
| walletState = WALLET_STATE, | ||
| lightningState = lightningState, | ||
| onClickEditInvoice = { editedTabs += it }, | ||
| onClickReceiveCjit = {}, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun makeAutoAvailable() { | ||
| composeTestRule.runOnIdle { lightningState = STATE_WITH_INBOUND } | ||
| composeTestRule.waitForIdle() | ||
| composeTestRule.onNodeWithTag("Tab-auto").assertIsDisplayed() | ||
| } | ||
|
|
||
| private fun selectedTab(): ReceiveTab { | ||
| composeTestRule.onAllNodesWithTag("SpecifyInvoiceButton")[0].performClick() | ||
| composeTestRule.waitForIdle() | ||
| return editedTabs.last() | ||
| } | ||
|
|
||
| private companion object { | ||
| const val ADDRESS = "bcrt1qreceiveaddress" | ||
| const val BOLT11 = "lnbcrt1invoice" | ||
| val WALLET_STATE = WalletState( | ||
| onchainAddress = ADDRESS, | ||
| bolt11 = BOLT11, | ||
| bip21 = "bitcoin:$ADDRESS?lightning=$BOLT11", | ||
| ) | ||
| val STATE_WITHOUT_INBOUND = LightningState(nodeLifecycleState = NodeLifecycleState.Running) | ||
| val STATE_WITH_INBOUND = LightningState( | ||
| nodeLifecycleState = NodeLifecycleState.Running, | ||
| channels = persistentListOf( | ||
| createChannelDetails().copy( | ||
| isChannelReady = true, | ||
| isUsable = true, | ||
| inboundCapacityMsat = 100_000_000u, | ||
| ) | ||
| ), | ||
| ) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
app/src/test/java/to/bitkit/ui/screens/wallets/receive/ReceiveAutoTabSwitchTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| package to.bitkit.ui.screens.wallets.receive | ||
|
|
||
| import org.junit.Test | ||
| import kotlin.test.assertFalse | ||
| import kotlin.test.assertTrue | ||
|
|
||
| class ReceiveAutoTabSwitchTest { | ||
|
|
||
| @Test | ||
| fun `switches when lightning becomes available and user has not selected a tab`() { | ||
| assertTrue(decide()) | ||
| } | ||
|
|
||
| @Test | ||
| fun `does not switch when auto is already selected`() { | ||
| assertFalse(decide(selectedTab = ReceiveTab.AUTO)) | ||
| } | ||
|
|
||
| @Test | ||
| fun `does not switch after user selected a tab`() { | ||
| assertFalse(decide(hasUserSelectedTab = true)) | ||
| } | ||
|
|
||
| @Test | ||
| fun `does not switch when lightning invoice cannot be created`() { | ||
| assertFalse(decide(canCreateLightningInvoice = false)) | ||
| } | ||
|
|
||
| @Test | ||
| fun `does not switch when cjit invoice exists`() { | ||
| assertFalse(decide(cjitInvoice = "lnbcrt1cjit")) | ||
| } | ||
|
|
||
| @Test | ||
| fun `switches when cjit invoice is empty`() { | ||
| assertTrue(decide(cjitInvoice = "")) | ||
| } | ||
|
|
||
| @Test | ||
| fun `does not switch when an initial tab was requested`() { | ||
| assertFalse(decide(initialTab = ReceiveTab.SPENDING)) | ||
| } | ||
|
|
||
| private fun decide( | ||
| selectedTab: ReceiveTab = ReceiveTab.SAVINGS, | ||
| hasUserSelectedTab: Boolean = false, | ||
| canCreateLightningInvoice: Boolean = true, | ||
| cjitInvoice: String? = null, | ||
| initialTab: ReceiveTab? = null, | ||
| ) = shouldAutoSwitchToAuto( | ||
| selectedTab = selectedTab, | ||
| hasUserSelectedTab = hasUserSelectedTab, | ||
| canCreateLightningInvoice = canCreateLightningInvoice, | ||
| cjitInvoice = cjitInvoice, | ||
| initialTab = initialTab, | ||
| ) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Fixed the Receive sheet sliding to the Auto tab on open and overriding a tab you had already picked. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| <journey name="receive auto tab selection"> | ||
| <description> | ||
| Verifies that the Receive sheet opens on the Auto tab without sliding to it, that a tab the user | ||
| picks is not overridden by the Auto tab, and that a leftover invoice amount from an earlier Edit | ||
| Invoice session does not open the sheet on Savings. Requires a wallet with a usable spending | ||
| channel so the Auto tab is available once the Lightning node is running. The selected tab is | ||
| shown only by its underline, which `android layout` does not expose, so tab assertions need a | ||
| screenshot; the Auto tab's presence can be read from the testTag "Tab-auto". The underline itself | ||
| crossfades over 200 ms even when the switch is instant, so the two steps that check for an | ||
| animation read the QR pager out of a screen recording instead of the underline. Each of those | ||
| steps first requires the recording to contain the frames it reasons about; a recording that ended | ||
| before the node started, or before the sheet opened, is a rerun with a longer `--time-limit`, not | ||
| a pass. | ||
| </description> | ||
| <actions> | ||
| <action> | ||
| Launch the Bitkit app and go to the wallet home screen | ||
| </action> | ||
| <action> | ||
| Tap the Receive button (testTag "Receive"), take a screenshot within one second, and verify the | ||
| Auto tab (testTag "Tab-auto") is selected on the first frame of the sheet | ||
| </action> | ||
| <action> | ||
| Swipe the QR code area from left to right once and verify the Savings tab (testTag | ||
| "Tab-savings") is selected | ||
| </action> | ||
| <action> | ||
| Wait 3 seconds, take a screenshot and verify the Savings tab is still selected | ||
| </action> | ||
| <action> | ||
| Close the sheet, then run `adb shell am force-stop to.bitkit.dev` and launch the app again | ||
| </action> | ||
| <action> | ||
| As soon as the home screen shows, tap the Receive button and verify the tab row has no Auto tab | ||
| (testTag "Tab-auto" absent) while the Lightning node starts | ||
| </action> | ||
| <action> | ||
| Tap the Trezor tab (testTag "Tab-trezor") if present, then tap the Savings tab (testTag | ||
| "Tab-savings") | ||
| </action> | ||
| <action> | ||
| Wait until the Auto tab (testTag "Tab-auto") appears, wait 5 more seconds, take a screenshot and | ||
| verify the Savings tab is still selected | ||
| </action> | ||
| <action> | ||
| Close the sheet, force-stop and relaunch the app, and start `adb shell screenrecord | ||
| --time-limit 20 /sdcard/receive-auto.mp4`. As soon as the home screen shows, tap the Receive | ||
| button without touching the tabs and verify the Auto tab (testTag "Tab-auto") is absent; do not | ||
| wait for the node, the tab row must still be Savings-first when the sheet opens | ||
| </action> | ||
| <action> | ||
| Wait until the Auto tab (testTag "Tab-auto") appears, and check that it appeared while the | ||
| recording was still running. The node has to finish `lightningService.start` and load its | ||
| channels before the Auto tab exists, which on a cold process can outlast the 20 second window; | ||
| if the Auto tab is still absent when the recording ends, the jump happened off-tape and the run | ||
| holds no evidence, so repeat the previous step with a longer `--time-limit` rather than reading | ||
| the empty recording as a pass | ||
| </action> | ||
| <action> | ||
| Let the recording finish, pull it (`adb pull /sdcard/receive-auto.mp4`), extract frames (`ffmpeg | ||
| -i receive-auto.mp4 -vf fps=30 frames/%03d.png`) and verify first that the recording contains | ||
| the jump at all: a frame showing the Savings page centred in the QR pager, followed by a later | ||
| frame showing the Auto page centred. If either frame is missing, the step did not capture the | ||
| switch and has to be rerun; it is not a pass. Then verify that no frame between those two shows | ||
| the QR pager part-way between the Savings and the Auto page: the sheet jumps to Auto in one | ||
| frame instead of sliding | ||
| </action> | ||
| <action> | ||
| Tap "Edit" (testTag "SpecifyInvoiceButton"), tap the amount field (testTag | ||
| "ReceiveNumberPadTextField"), enter an amount above the inbound Lightning capacity (for example | ||
| N3 N0 N0 N0 in USD), tap Continue (testTag "ReceiveNumberPadSubmit") and then "QR Code" (testTag | ||
| "ShowQrReceive"); verify the Auto tab (testTag "Tab-auto") is absent | ||
| </action> | ||
| <action> | ||
| Start `adb shell screenrecord --time-limit 20 /sdcard/receive-reopen.mp4`, close the sheet and | ||
| tap the Receive button again, then verify the Auto tab (testTag "Tab-auto") is present | ||
| </action> | ||
| <action> | ||
| Let the recording finish, pull it (`adb pull /sdcard/receive-reopen.mp4`), extract frames | ||
| (`ffmpeg -i receive-reopen.mp4 -vf fps=30 frames/%03d.png`) and verify that the recording holds | ||
| frames in which the sheet is visible — if it holds none, rerun the step, it is not a pass — then | ||
| that the first such frame already shows the Auto tab in the tab row with the selected underline, | ||
| and that no frame shows Savings selected. A sheet that opens on Savings and only then gains the | ||
| Auto tab means the leftover invoice amount was not cleared | ||
| </action> | ||
| </actions> | ||
| </journey> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.