From c2e77c08a9da327d34d4b68f978e7ba3273bff0c Mon Sep 17 00:00:00 2001 From: Blazebrain Date: Wed, 9 Apr 2025 17:18:24 +0100 Subject: [PATCH] feat: Modify Exchange and send tests to fit new flow --- .../components/common_test_cases.dart | 33 +++++++++++++ .../components/common_test_flows.dart | 13 ------ .../robots/dashboard_menu_widget_robot.dart | 2 +- .../robots/dashboard_page_robot.dart | 4 ++ integration_test/robots/send_page_robot.dart | 30 ++++++------ .../robots/transactions_page_robot.dart | 25 +++++++--- .../robots/wallet_keys_robot.dart | 1 - .../test_suites/confirm_seeds_flow_test.dart | 3 +- .../test_suites/create_wallet_flow_test.dart | 4 +- ...estore_wallet_through_seeds_flow_test.dart | 5 +- .../transaction_history_flow_test.dart | 46 +++++++++---------- .../widgets/standard_slide_button_widget.dart | 32 ++++++++----- 12 files changed, 120 insertions(+), 78 deletions(-) diff --git a/integration_test/components/common_test_cases.dart b/integration_test/components/common_test_cases.dart index 96bb7b8bf..78585423a 100644 --- a/integration_test/components/common_test_cases.dart +++ b/integration_test/components/common_test_cases.dart @@ -71,6 +71,14 @@ class CommonTestCases { } Future startGesture(String key, Offset gestureOffset) async { + await tester.pumpAndSettle(); + + final hasKey = isKeyPresent(key); + + tester.printToConsole("Has gestureKey: $hasKey"); + + if (!hasKey) return; + final gesture = await tester.startGesture(tester.getCenter(find.byKey(ValueKey(key)))); // Drag to the left @@ -176,6 +184,31 @@ class CommonTestCases { } } + Future scrollItemIntoView( + String itemKeyId, + double scrollPixels, + String scrollableFinderKey, + ) async { + final Finder itemFinder = find.byKey(ValueKey(itemKeyId)); + + final scrollableFinder = find.descendant( + of: find.byKey(ValueKey(scrollableFinderKey)), + matching: find.byType(Scrollable), + ); + + try { + await tester.scrollUntilVisible( + itemFinder, + scrollPixels, + scrollable: scrollableFinder, + ); + } catch (e) { + tester.printToConsole('Could not find $itemKeyId'); + } + + await tester.pumpAndSettle(); + } + Future enterText(String text, String editableTextKey) async { final editableTextWidget = find.byKey(ValueKey((editableTextKey))); diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart index 0e26cff6c..c8e9fe6ad 100644 --- a/integration_test/components/common_test_flows.dart +++ b/integration_test/components/common_test_flows.dart @@ -10,8 +10,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:cake_wallet/main.dart' as app; import '../robots/create_pin_welcome_page_robot.dart'; -import '../robots/dashboard_page_robot.dart'; -import '../robots/disclaimer_page_robot.dart'; import '../robots/new_wallet_page_robot.dart'; import '../robots/new_wallet_type_page_robot.dart'; import '../robots/pre_seed_page_robot.dart'; @@ -34,9 +32,7 @@ class CommonTestFlows { _welcomePageRobot = WelcomePageRobot(_tester), _preSeedPageRobot = PreSeedPageRobot(_tester), _setupPinCodeRobot = SetupPinCodeRobot(_tester), - _dashboardPageRobot = DashboardPageRobot(_tester), _newWalletPageRobot = NewWalletPageRobot(_tester), - _disclaimerPageRobot = DisclaimerPageRobot(_tester), _walletSeedPageRobot = WalletSeedPageRobot(_tester), _walletListPageRobot = WalletListPageRobot(_tester), _newWalletTypePageRobot = NewWalletTypePageRobot(_tester), @@ -53,8 +49,6 @@ class CommonTestFlows { final PreSeedPageRobot _preSeedPageRobot; final SetupPinCodeRobot _setupPinCodeRobot; final NewWalletPageRobot _newWalletPageRobot; - final DashboardPageRobot _dashboardPageRobot; - final DisclaimerPageRobot _disclaimerPageRobot; final WalletSeedPageRobot _walletSeedPageRobot; final WalletListPageRobot _walletListPageRobot; final NewWalletTypePageRobot _newWalletTypePageRobot; @@ -113,13 +107,6 @@ class CommonTestFlows { await _restoreFromKeys(); } - //* ========== Handles switching to wallet list or menu from dashboard =============== - Future switchToWalletMenuFromDashboardPage() async { - _tester.printToConsole('Switching to Wallet Menu'); - - await _dashboardPageRobot.dashboardMenuWidgetRobot.navigateToWalletMenu(); - } - void confirmAllAvailableWalletTypeIconsDisplayCorrectly() { for (var walletType in availableWalletTypes) { final imageUrl = walletTypeToCryptoCurrency(walletType).iconPath; diff --git a/integration_test/robots/dashboard_menu_widget_robot.dart b/integration_test/robots/dashboard_menu_widget_robot.dart index 052d2bea9..34c76aa7d 100644 --- a/integration_test/robots/dashboard_menu_widget_robot.dart +++ b/integration_test/robots/dashboard_menu_widget_robot.dart @@ -27,7 +27,7 @@ class DashboardMenuWidgetRobot { } Future navigateToWalletMenu() async { - await commonTestCases.tapItemByKey('dashboard_page_Wallets_action_button_key'); + await commonTestCases.tapItemByKey('dashboard_page_menu_widget_wallet_menu_button_key'); await commonTestCases.defaultSleepTime(); } diff --git a/integration_test/robots/dashboard_page_robot.dart b/integration_test/robots/dashboard_page_robot.dart index 81d654955..070a754d5 100644 --- a/integration_test/robots/dashboard_page_robot.dart +++ b/integration_test/robots/dashboard_page_robot.dart @@ -92,6 +92,10 @@ class DashboardPageRobot { await commonTestCases.tapItemByKey('dashboard_page_${S.current.buy}_action_button_key'); } + Future navigateToWalletsListPage() async { + await commonTestCases.tapItemByKey('dashboard_page_${S.current.wallets}_action_button_key'); + } + Future navigateToSendPage() async { await commonTestCases.tapItemByKey('dashboard_page_${S.current.send}_action_button_key'); } diff --git a/integration_test/robots/send_page_robot.dart b/integration_test/robots/send_page_robot.dart index 359085f02..5899696af 100644 --- a/integration_test/robots/send_page_robot.dart +++ b/integration_test/robots/send_page_robot.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/send/send_page.dart'; +import 'package:cake_wallet/src/widgets/standard_slide_button_widget.dart'; import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -299,37 +300,36 @@ class SendPageRobot { //* ------ On Sending Success ------------ Future onSendSliderOnConfirmSendingBottomSheetDragged() async { - tester.printToConsole('Inside confirm sending dialog: For sending'); await commonTestCases.defaultSleepTime(); await tester.pumpAndSettle(); - bool hasConfirmSendBottomSheet = - commonTestCases.isKeyPresent('send_page_confirm_sending_bottom_sheet_key'); + if (commonTestCases.isKeyPresent('send_page_confirm_sending_bottom_sheet_key')) { + final state = tester.state(find.byType(StandardSlideButton)); + final double effectiveMaxWidth = state.effectiveMaxWidth; + final double sliderWidth = state.sliderWidth; + final double threshold = effectiveMaxWidth - sliderWidth - 10; - tester.printToConsole('Has Confirm Send BottomSheet: $hasConfirmSendBottomSheet'); + final sliderFinder = + find.byKey(const ValueKey('standard_slide_button_widget_slider_container_key')); + expect(sliderFinder, findsOneWidget); - if (hasConfirmSendBottomSheet) { - await commonTestCases.startGesture( - 'standard_slide_button_widget_slider_key', - Offset(200, 0), - ); + // Using the center of the container as the drag start. + final Offset dragStart = tester.getCenter(sliderFinder); - tester.printToConsole('Slider moved'); - + // Dragging by an offset sufficient to exceed the threshold. + await tester.dragFrom(dragStart, Offset(threshold + 20, 0)); await tester.pumpAndSettle(); - tester.printToConsole('Slider pump done'); + tester.printToConsole('Final slider dragPosition: ${state.dragPosition}'); // Loop to wait for the operation to commit transaction await _waitForCommitTransactionCompletion(); - await tester.pump(); - await commonTestCases.defaultSleepTime(seconds: 4); } else { await commonTestCases.defaultSleepTime(); await tester.pump(); - onSendSliderOnConfirmSendingBottomSheetDragged(); + await onSendSliderOnConfirmSendingBottomSheetDragged(); } } diff --git a/integration_test/robots/transactions_page_robot.dart b/integration_test/robots/transactions_page_robot.dart index fd22796ad..99d0d3945 100644 --- a/integration_test/robots/transactions_page_robot.dart +++ b/integration_test/robots/transactions_page_robot.dart @@ -52,10 +52,10 @@ class TransactionsPageRobot { // Define a timeout to prevent infinite loops // Putting at one hour for cases like monero that takes time to sync final timeout = Duration(hours: 1); - final pollingInterval = Duration(seconds: 2); final endTime = DateTime.now().add(timeout); while (DateTime.now().isBefore(endTime)) { + await tester.pump(Duration(seconds: 5)); final isSynced = dashboardViewModel.status is SyncedSyncStatus; final itemsLoaded = dashboardViewModel.items.isNotEmpty; @@ -64,21 +64,29 @@ class TransactionsPageRobot { await _performItemChecks(dashboardViewModel); } else { // Verify placeholder when items are not loaded + await tester.pump(Duration(seconds: 5)); _verifyPlaceholder(); + tester.printToConsole('No item to check for'); } // Determine if we should exit the loop - if (_shouldExitLoop(hasTxHistoryWhileSyncing, isSynced, itemsLoaded)) { + bool shouldExit = _shouldExitLoop(hasTxHistoryWhileSyncing, isSynced, itemsLoaded); + await tester.pump(Duration(seconds: 2)); + + if (shouldExit) { + await tester.pump(Duration(seconds: 2)); break; } // Pump the UI and wait for the next polling interval - await tester.pumpAndSettle(pollingInterval); + await commonTestCases.defaultSleepTime(); + await tester.pump(Duration(seconds: 2)); + await tester.pumpAndSettle(); } // After the loop, verify that both status is synced and items are loaded if (!_isFinalStateValid(dashboardViewModel)) { - throw TimeoutException('Dashboard did not sync and load items within the allotted time.'); + tester.printToConsole('Dashboard did not sync and load items within the allotted time.'); } } @@ -119,10 +127,14 @@ class TransactionsPageRobot { await tester.pumpAndSettle(); // Scroll the item into view - await commonTestCases.dragUntilVisible(keyId, 'transactions_page_list_view_builder_key'); + await commonTestCases.scrollItemIntoView( + keyId, + 20, + 'transactions_page_list_view_builder_key', + ); await tester.pumpAndSettle(); - // Check if the widget is visible + // Verify the widget is visible; if not, skip to the next one. if (!tester.any(find.byKey(ValueKey(keyId)))) { tester.printToConsole('Item not visible: $keyId. Moving to the next.'); continue; @@ -130,6 +142,7 @@ class TransactionsPageRobot { await tester.pumpAndSettle(); + // Execute the proper check depending on item type. switch (item.runtimeType) { case TransactionListItem: final transactionItem = item as TransactionListItem; diff --git a/integration_test/robots/wallet_keys_robot.dart b/integration_test/robots/wallet_keys_robot.dart index df86e03cf..07fad4bfd 100644 --- a/integration_test/robots/wallet_keys_robot.dart +++ b/integration_test/robots/wallet_keys_robot.dart @@ -183,6 +183,5 @@ class WalletKeysAndSeedPageRobot { tester.printToConsole('Going back to dashboard from credentials page'); await commonTestCases.goBack(); await commonTestCases.goBack(); - await commonTestCases.goBack(); } } diff --git a/integration_test/test_suites/confirm_seeds_flow_test.dart b/integration_test/test_suites/confirm_seeds_flow_test.dart index 6716c8055..40566bf51 100644 --- a/integration_test/test_suites/confirm_seeds_flow_test.dart +++ b/integration_test/test_suites/confirm_seeds_flow_test.dart @@ -1,4 +1,3 @@ - import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; @@ -58,7 +57,7 @@ void main() { continue; } - await commonTestFlows.switchToWalletMenuFromDashboardPage(); + await dashboardPageRobot.navigateToWalletsListPage(); await commonTestFlows.createNewWalletFromWalletMenu(walletType); diff --git a/integration_test/test_suites/create_wallet_flow_test.dart b/integration_test/test_suites/create_wallet_flow_test.dart index 2a50dbbe8..a82443ccc 100644 --- a/integration_test/test_suites/create_wallet_flow_test.dart +++ b/integration_test/test_suites/create_wallet_flow_test.dart @@ -39,7 +39,7 @@ void main() { continue; } - await commonTestFlows.switchToWalletMenuFromDashboardPage(); + await dashboardPageRobot.navigateToWalletsListPage(); await commonTestFlows.createNewWalletFromWalletMenu(walletType); @@ -47,7 +47,7 @@ void main() { } // Goes to the wallet menu and provides a confirmation that all the wallets were correctly restored - await commonTestFlows.switchToWalletMenuFromDashboardPage(); + await dashboardPageRobot.navigateToWalletsListPage(); commonTestFlows.confirmAllAvailableWalletTypeIconsDisplayCorrectly(); diff --git a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart index 67c704ebf..1364aa0f0 100644 --- a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart +++ b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart @@ -1,4 +1,3 @@ - import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -51,7 +50,7 @@ void main() { continue; } - await commonTestFlows.switchToWalletMenuFromDashboardPage(); + await dashboardPageRobot.navigateToWalletsListPage(); await commonTestFlows.restoreWalletFromWalletMenu( walletType, @@ -62,7 +61,7 @@ void main() { } // Goes to the wallet menu and provides a visual confirmation that all the wallets were correctly restored - await commonTestFlows.switchToWalletMenuFromDashboardPage(); + await dashboardPageRobot.navigateToWalletsListPage(); commonTestFlows.confirmAllAvailableWalletTypeIconsDisplayCorrectly(); diff --git a/integration_test/test_suites/transaction_history_flow_test.dart b/integration_test/test_suites/transaction_history_flow_test.dart index 8af6d39fd..4927d58d7 100644 --- a/integration_test/test_suites/transaction_history_flow_test.dart +++ b/integration_test/test_suites/transaction_history_flow_test.dart @@ -28,33 +28,13 @@ void main() { ValueKey('confirm_creds_display_correctly_flow_app_key'), ); - /// Test Scenario 1 - Displays transaction history list after fully synchronizing. - /// - /// For Solana/Tron WalletTypes. - await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow( - WalletType.solana, - secrets.solanaTestWalletSeeds, - CommonTestConstants.pin, - ); - - await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana); - - await dashboardPageRobot.swipeDashboardTab(true); - - await transactionsPageRobot.isTransactionsPage(); - - await transactionsPageRobot.confirmTransactionsPageConstantsDisplayProperly(); - - await transactionsPageRobot.confirmTransactionHistoryListDisplaysCorrectly(false); - - /// Test Scenario 2 - Displays transaction history list while synchronizing. + /// Test Scenario 1 - Displays transaction history list while synchronizing. /// /// For bitcoin/Monero/Wownero WalletTypes. - await commonTestFlows.switchToWalletMenuFromDashboardPage(); - - await commonTestFlows.restoreWalletFromWalletMenu( + await commonTestFlows.welcomePageToRestoreWalletThroughSeedsFlow( WalletType.bitcoin, secrets.bitcoinTestWalletSeeds, + CommonTestConstants.pin, ); await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.bitcoin); @@ -65,6 +45,26 @@ void main() { await transactionsPageRobot.confirmTransactionsPageConstantsDisplayProperly(); + await transactionsPageRobot.confirmTransactionHistoryListDisplaysCorrectly(false); + + /// Test Scenario 2 - Displays transaction history list after fully synchronizing. + /// + /// For Solana/Tron WalletTypes. + await dashboardPageRobot.navigateToWalletsListPage(); + + await commonTestFlows.restoreWalletFromWalletMenu( + WalletType.solana, + secrets.solanaTestWalletSeeds, + ); + + await dashboardPageRobot.confirmWalletTypeIsDisplayedCorrectly(WalletType.solana); + + await dashboardPageRobot.swipeDashboardTab(true); + + await transactionsPageRobot.isTransactionsPage(); + + await transactionsPageRobot.confirmTransactionsPageConstantsDisplayProperly(); + await transactionsPageRobot.confirmTransactionHistoryListDisplaysCorrectly(true); }); } diff --git a/lib/src/widgets/standard_slide_button_widget.dart b/lib/src/widgets/standard_slide_button_widget.dart index 93313373f..185b480a6 100644 --- a/lib/src/widgets/standard_slide_button_widget.dart +++ b/lib/src/widgets/standard_slide_button_widget.dart @@ -20,31 +20,33 @@ class StandardSlideButton extends StatefulWidget { final ThemeBase currentTheme; @override - _StandardSlideButtonState createState() => _StandardSlideButtonState(); + StandardSlideButtonState createState() => StandardSlideButtonState(); } -class _StandardSlideButtonState extends State { +class StandardSlideButtonState extends State { double _dragPosition = 0.0; + double get dragPosition => _dragPosition; + + double sideMargin = 4.0; + double effectiveMaxWidth = 0.0; + double sliderWidth = 42.0; @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { final double maxWidth = constraints.maxWidth; - const double sideMargin = 4.0; - final double effectiveMaxWidth = maxWidth - 2 * sideMargin; - const double sliderWidth = 42.0; + effectiveMaxWidth = maxWidth - 2 * sideMargin; final tileBackgroundColor = widget.currentTheme.type == ThemeType.light ? Theme.of(context).extension()!.syncedBackgroundColor : widget.currentTheme.type == ThemeType.oled - ? Colors.black.withOpacity(0.5) - : Theme.of(context).extension()!.buttonColor; + ? Colors.black.withOpacity(0.5) + : Theme.of(context).extension()!.buttonColor; return Container( height: widget.height, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: tileBackgroundColor), + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(10), color: tileBackgroundColor), child: Stack( alignment: Alignment.centerLeft, children: [ @@ -76,6 +78,7 @@ class _StandardSlideButtonState extends State { } }, child: Container( + key: ValueKey('standard_slide_button_widget_slider_container_key'), width: sliderWidth, height: widget.height - 8, decoration: BoxDecoration( @@ -83,8 +86,13 @@ class _StandardSlideButtonState extends State { color: Theme.of(context).extension()!.titleColor, ), alignment: Alignment.center, - child: Icon(Icons.arrow_forward, - color: widget.currentTheme.type == ThemeType.bright ? Theme.of(context).extension()!.backgroundColor : Theme.of(context).extension()!.buttonColor), + child: Icon( + key: ValueKey('standard_slide_button_widget_slider_icon_key'), + Icons.arrow_forward, + color: widget.currentTheme.type == ThemeType.bright + ? Theme.of(context).extension()!.backgroundColor + : Theme.of(context).extension()!.buttonColor, + ), ), ), )