feat: Modify Exchange and send tests to fit new flow

This commit is contained in:
Blazebrain 2025-04-09 17:18:24 +01:00
parent 9faec1c640
commit c2e77c08a9
12 changed files with 120 additions and 78 deletions

View file

@ -71,6 +71,14 @@ class CommonTestCases {
}
Future<void> 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<void> 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<void> enterText(String text, String editableTextKey) async {
final editableTextWidget = find.byKey(ValueKey((editableTextKey)));

View file

@ -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<void> switchToWalletMenuFromDashboardPage() async {
_tester.printToConsole('Switching to Wallet Menu');
await _dashboardPageRobot.dashboardMenuWidgetRobot.navigateToWalletMenu();
}
void confirmAllAvailableWalletTypeIconsDisplayCorrectly() {
for (var walletType in availableWalletTypes) {
final imageUrl = walletTypeToCryptoCurrency(walletType).iconPath;

View file

@ -27,7 +27,7 @@ class DashboardMenuWidgetRobot {
}
Future<void> 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();
}

View file

@ -92,6 +92,10 @@ class DashboardPageRobot {
await commonTestCases.tapItemByKey('dashboard_page_${S.current.buy}_action_button_key');
}
Future<void> navigateToWalletsListPage() async {
await commonTestCases.tapItemByKey('dashboard_page_${S.current.wallets}_action_button_key');
}
Future<void> navigateToSendPage() async {
await commonTestCases.tapItemByKey('dashboard_page_${S.current.send}_action_button_key');
}

View file

@ -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<void> 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<StandardSlideButtonState>(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();
}
}

View file

@ -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;

View file

@ -183,6 +183,5 @@ class WalletKeysAndSeedPageRobot {
tester.printToConsole('Going back to dashboard from credentials page');
await commonTestCases.goBack();
await commonTestCases.goBack();
await commonTestCases.goBack();
}
}

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -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);
});
}

View file

@ -20,31 +20,33 @@ class StandardSlideButton extends StatefulWidget {
final ThemeBase currentTheme;
@override
_StandardSlideButtonState createState() => _StandardSlideButtonState();
StandardSlideButtonState createState() => StandardSlideButtonState();
}
class _StandardSlideButtonState extends State<StandardSlideButton> {
class StandardSlideButtonState extends State<StandardSlideButton> {
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<SyncIndicatorTheme>()!.syncedBackgroundColor
: widget.currentTheme.type == ThemeType.oled
? Colors.black.withOpacity(0.5)
: Theme.of(context).extension<FilterTheme>()!.buttonColor;
? Colors.black.withOpacity(0.5)
: Theme.of(context).extension<FilterTheme>()!.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<StandardSlideButton> {
}
},
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<StandardSlideButton> {
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
alignment: Alignment.center,
child: Icon(Icons.arrow_forward,
color: widget.currentTheme.type == ThemeType.bright ? Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor : Theme.of(context).extension<FilterTheme>()!.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<CakeMenuTheme>()!.backgroundColor
: Theme.of(context).extension<FilterTheme>()!.buttonColor,
),
),
),
)