mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
CW-727/728-Automated-Integrated-Tests (#1514)
* feat: Integration tests setup and tests for Disclaimer, Welcome and Setup Pin Code pages * feat: Integration test flow from start to restoring a wallet successfully done * test: Dashboard view test and linking to flow * feat: Testing the Exchange flow section, selecting sending and receiving currencies * test: Successfully create an exchange section * feat: Implement flow up to sending section * test: Complete Exchange flow * fix dependency issue * test: Final cleanups * feat: Add CI to run automated integration tests withan android emulator * feat: Adjust Automated integration test CI to run on ubuntu 20.04-a * fix: Move integration test CI into PR test build CI * ci: Add automated test ci which is a streamlined replica of pr test build ci * ci: Re-add step to access branch name * ci: Add KVM * ci: Add filepath to trigger the test run from * ci: Add required key * ci: Add required key * ci: Add missing secret key * ci: Add missing secret key * ci: Add nano secrets to workflow * ci: Switch step to free space on runner * ci: Remove timeout from workflow * ci: Confirm impact that removing copy_monero_deps would have on entire workflow time * ci: Update CI and temporarily remove cache related to emulator * ci: Remove dynamic java version * ci: Temporarily switch CI * ci: Switch to 11.x jdk * ci: Temporarily switch CI * ci: Revert ubuntu version * ci: Add more api levels * ci: Add more target options * ci: Settled on stable emulator matrix options * ci: Add more target options * ci: Modify flow * ci: Streamline api levels to 28 and 29 * ci: One more trial * ci: Switch to flutter drive * ci: Reduce options * ci: Remove haven from test * ci: Check for solana in list * ci: Adjust amounts and currencies for exchange flow * ci: Set write response on failure to true * ci: Split ci to funds and non funds related tests * test: Test for Send flow scenario and minor restructuring for test folders and files * chore: cleanup * ci: Pause CI for now * ci: Pause CI for now * ci: Pause CI for now * Fix: Add keys back to currency amount textfield widget * fix: Switch variable name * fix: remove automation for now * test: Updating send page robot and also syncing branch with main --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
32e119e24f
commit
4adb81c4dc
67 changed files with 2381 additions and 240 deletions
96
integration_test/components/common_test_cases.dart
Normal file
96
integration_test/components/common_test_cases.dart
Normal file
|
@ -0,0 +1,96 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
class CommonTestCases {
|
||||
WidgetTester tester;
|
||||
CommonTestCases(this.tester);
|
||||
|
||||
Future<void> isSpecificPage<T>() async {
|
||||
await tester.pumpAndSettle();
|
||||
hasType<T>();
|
||||
}
|
||||
|
||||
Future<void> tapItemByKey(String key, {bool shouldPumpAndSettle = true}) async {
|
||||
final widget = find.byKey(ValueKey(key));
|
||||
await tester.tap(widget);
|
||||
shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
|
||||
}
|
||||
|
||||
Future<void> tapItemByFinder(Finder finder, {bool shouldPumpAndSettle = true}) async {
|
||||
await tester.tap(finder);
|
||||
shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
|
||||
}
|
||||
|
||||
void hasText(String text, {bool hasWidget = true}) {
|
||||
final textWidget = find.text(text);
|
||||
expect(textWidget, hasWidget ? findsOneWidget : findsNothing);
|
||||
}
|
||||
|
||||
void hasType<T>() {
|
||||
final typeWidget = find.byType(T);
|
||||
expect(typeWidget, findsOneWidget);
|
||||
}
|
||||
|
||||
void hasValueKey(String key) {
|
||||
final typeWidget = find.byKey(ValueKey(key));
|
||||
expect(typeWidget, findsOneWidget);
|
||||
}
|
||||
|
||||
Future<void> swipePage({bool swipeRight = true}) async {
|
||||
await tester.drag(find.byType(PageView), Offset(swipeRight ? -300 : 300, 0));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> swipeByPageKey({required String key, bool swipeRight = true}) async {
|
||||
await tester.drag(find.byKey(ValueKey(key)), Offset(swipeRight ? -300 : 300, 0));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> goBack() async {
|
||||
tester.printToConsole('Routing back to previous screen');
|
||||
final NavigatorState navigator = tester.state(find.byType(Navigator));
|
||||
navigator.pop();
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> scrollUntilVisible(String childKey, String parentScrollableKey,
|
||||
{double delta = 300}) async {
|
||||
final scrollableWidget = find.descendant(
|
||||
of: find.byKey(Key(parentScrollableKey)),
|
||||
matching: find.byType(Scrollable),
|
||||
);
|
||||
|
||||
final isAlreadyVisibile = isWidgetVisible(find.byKey(ValueKey(childKey)));
|
||||
|
||||
if (isAlreadyVisibile) return;
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.byKey(ValueKey(childKey)),
|
||||
delta,
|
||||
scrollable: scrollableWidget,
|
||||
);
|
||||
}
|
||||
|
||||
bool isWidgetVisible(Finder finder) {
|
||||
try {
|
||||
final Element element = finder.evaluate().single;
|
||||
final RenderBox renderBox = element.renderObject as RenderBox;
|
||||
return renderBox.paintBounds
|
||||
.shift(renderBox.localToGlobal(Offset.zero))
|
||||
.overlaps(tester.binding.renderViews.first.paintBounds);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> enterText(String text, String editableTextKey) async {
|
||||
final editableTextWidget = find.byKey(ValueKey((editableTextKey)));
|
||||
|
||||
await tester.enterText(editableTextWidget, text);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> defaultSleepTime({int seconds = 2}) async =>
|
||||
await Future.delayed(Duration(seconds: seconds));
|
||||
}
|
13
integration_test/components/common_test_constants.dart
Normal file
13
integration_test/components/common_test_constants.dart
Normal file
|
@ -0,0 +1,13 @@
|
|||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
class CommonTestConstants {
|
||||
static final pin = [0, 8, 0, 1];
|
||||
static final String sendTestAmount = '0.00008';
|
||||
static final String exchangeTestAmount = '8';
|
||||
static final WalletType testWalletType = WalletType.solana;
|
||||
static final String testWalletName = 'Integrated Testing Wallet';
|
||||
static final CryptoCurrency testReceiveCurrency = CryptoCurrency.sol;
|
||||
static final CryptoCurrency testDepositCurrency = CryptoCurrency.usdtSol;
|
||||
static final String testWalletAddress = 'An2Y2fsUYKfYvN1zF89GAqR1e6GUMBg3qA83Y5ZWDf8L';
|
||||
}
|
101
integration_test/components/common_test_flows.dart
Normal file
101
integration_test/components/common_test_flows.dart
Normal file
|
@ -0,0 +1,101 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:cake_wallet/main.dart' as app;
|
||||
|
||||
import '../robots/disclaimer_page_robot.dart';
|
||||
import '../robots/new_wallet_type_page_robot.dart';
|
||||
import '../robots/restore_from_seed_or_key_robot.dart';
|
||||
import '../robots/restore_options_page_robot.dart';
|
||||
import '../robots/setup_pin_code_robot.dart';
|
||||
import '../robots/welcome_page_robot.dart';
|
||||
import 'common_test_cases.dart';
|
||||
import 'common_test_constants.dart';
|
||||
|
||||
class CommonTestFlows {
|
||||
CommonTestFlows(this._tester)
|
||||
: _commonTestCases = CommonTestCases(_tester),
|
||||
_welcomePageRobot = WelcomePageRobot(_tester),
|
||||
_setupPinCodeRobot = SetupPinCodeRobot(_tester),
|
||||
_disclaimerPageRobot = DisclaimerPageRobot(_tester),
|
||||
_newWalletTypePageRobot = NewWalletTypePageRobot(_tester),
|
||||
_restoreOptionsPageRobot = RestoreOptionsPageRobot(_tester),
|
||||
_restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(_tester);
|
||||
|
||||
final WidgetTester _tester;
|
||||
final CommonTestCases _commonTestCases;
|
||||
|
||||
final WelcomePageRobot _welcomePageRobot;
|
||||
final SetupPinCodeRobot _setupPinCodeRobot;
|
||||
final DisclaimerPageRobot _disclaimerPageRobot;
|
||||
final NewWalletTypePageRobot _newWalletTypePageRobot;
|
||||
final RestoreOptionsPageRobot _restoreOptionsPageRobot;
|
||||
final RestoreFromSeedOrKeysPageRobot _restoreFromSeedOrKeysPageRobot;
|
||||
|
||||
Future<void> startAppFlow(Key key) async {
|
||||
await app.main(topLevelKey: ValueKey('send_flow_test_app_key'));
|
||||
|
||||
await _tester.pumpAndSettle();
|
||||
|
||||
// --------- Disclaimer Page ------------
|
||||
// Tap checkbox to accept disclaimer
|
||||
await _disclaimerPageRobot.tapDisclaimerCheckbox();
|
||||
|
||||
// Tap accept button
|
||||
await _disclaimerPageRobot.tapAcceptButton();
|
||||
}
|
||||
|
||||
Future<void> restoreWalletThroughSeedsFlow() async {
|
||||
await _welcomeToRestoreFromSeedsPath();
|
||||
await _restoreFromSeeds();
|
||||
}
|
||||
|
||||
Future<void> restoreWalletThroughKeysFlow() async {
|
||||
await _welcomeToRestoreFromSeedsPath();
|
||||
await _restoreFromKeys();
|
||||
}
|
||||
|
||||
Future<void> _welcomeToRestoreFromSeedsPath() async {
|
||||
// --------- Welcome Page ---------------
|
||||
await _welcomePageRobot.navigateToRestoreWalletPage();
|
||||
|
||||
// ----------- Restore Options Page -----------
|
||||
// Route to restore from seeds page to continue flow
|
||||
await _restoreOptionsPageRobot.navigateToRestoreFromSeedsPage();
|
||||
|
||||
// ----------- SetupPinCode Page -------------
|
||||
// Confirm initial defaults - Widgets to be displayed etc
|
||||
await _setupPinCodeRobot.isSetupPinCodePage();
|
||||
|
||||
await _setupPinCodeRobot.enterPinCode(CommonTestConstants.pin, true);
|
||||
await _setupPinCodeRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
await _setupPinCodeRobot.tapSuccessButton();
|
||||
|
||||
// ----------- NewWalletType Page -------------
|
||||
// Confirm scroll behaviour works properly
|
||||
await _newWalletTypePageRobot
|
||||
.findParticularWalletTypeInScrollableList(CommonTestConstants.testWalletType);
|
||||
|
||||
// Select a wallet and route to next page
|
||||
await _newWalletTypePageRobot.selectWalletType(CommonTestConstants.testWalletType);
|
||||
await _newWalletTypePageRobot.onNextButtonPressed();
|
||||
}
|
||||
|
||||
Future<void> _restoreFromSeeds() async {
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await _restoreFromSeedOrKeysPageRobot.enterWalletNameText(CommonTestConstants.testWalletName);
|
||||
await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore(secrets.solanaTestWalletSeeds);
|
||||
await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
}
|
||||
|
||||
Future<void> _restoreFromKeys() async {
|
||||
await _commonTestCases.swipePage();
|
||||
await _commonTestCases.defaultSleepTime();
|
||||
|
||||
await _restoreFromSeedOrKeysPageRobot.enterWalletNameText(CommonTestConstants.testWalletName);
|
||||
|
||||
await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore('');
|
||||
await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
}
|
||||
}
|
84
integration_test/funds_related_tests.dart
Normal file
84
integration_test/funds_related_tests.dart
Normal file
|
@ -0,0 +1,84 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'components/common_test_constants.dart';
|
||||
import 'components/common_test_flows.dart';
|
||||
import 'robots/auth_page_robot.dart';
|
||||
import 'robots/dashboard_page_robot.dart';
|
||||
import 'robots/exchange_confirm_page_robot.dart';
|
||||
import 'robots/exchange_page_robot.dart';
|
||||
import 'robots/exchange_trade_page_robot.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
DashboardPageRobot dashboardPageRobot;
|
||||
ExchangePageRobot exchangePageRobot;
|
||||
ExchangeConfirmPageRobot exchangeConfirmPageRobot;
|
||||
AuthPageRobot authPageRobot;
|
||||
ExchangeTradePageRobot exchangeTradePageRobot;
|
||||
CommonTestFlows commonTestFlows;
|
||||
|
||||
group('Startup Test', () {
|
||||
testWidgets('Test for Exchange flow using Restore Wallet - Exchanging USDT(Sol) to SOL',
|
||||
(tester) async {
|
||||
authPageRobot = AuthPageRobot(tester);
|
||||
exchangePageRobot = ExchangePageRobot(tester);
|
||||
dashboardPageRobot = DashboardPageRobot(tester);
|
||||
exchangeTradePageRobot = ExchangeTradePageRobot(tester);
|
||||
exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
|
||||
commonTestFlows = CommonTestFlows(tester);
|
||||
|
||||
await commonTestFlows.startAppFlow(ValueKey('funds_exchange_test_app_key'));
|
||||
|
||||
await commonTestFlows.restoreWalletThroughSeedsFlow();
|
||||
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await dashboardPageRobot.navigateToExchangePage();
|
||||
|
||||
// ----------- Exchange Page -------------
|
||||
await exchangePageRobot.isExchangePage();
|
||||
exchangePageRobot.hasResetButton();
|
||||
await exchangePageRobot.displayBothExchangeCards();
|
||||
exchangePageRobot.confirmRightComponentsDisplayOnDepositExchangeCards();
|
||||
exchangePageRobot.confirmRightComponentsDisplayOnReceiveExchangeCards();
|
||||
|
||||
await exchangePageRobot.selectDepositCurrency(CommonTestConstants.testDepositCurrency);
|
||||
await exchangePageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
|
||||
|
||||
await exchangePageRobot.enterDepositAmount(CommonTestConstants.exchangeTestAmount);
|
||||
await exchangePageRobot.enterDepositRefundAddress(
|
||||
depositAddress: CommonTestConstants.testWalletAddress);
|
||||
|
||||
await exchangePageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
|
||||
|
||||
await exchangePageRobot.onExchangeButtonPressed();
|
||||
|
||||
await exchangePageRobot.handleErrors(CommonTestConstants.exchangeTestAmount);
|
||||
|
||||
final onAuthPage = authPageRobot.onAuthPage();
|
||||
if (onAuthPage) {
|
||||
await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
}
|
||||
|
||||
// ----------- Exchange Confirm Page -------------
|
||||
await exchangeConfirmPageRobot.isExchangeConfirmPage();
|
||||
|
||||
exchangeConfirmPageRobot.confirmComponentsOfTradeDisplayProperly();
|
||||
await exchangeConfirmPageRobot.confirmCopyTradeIdToClipBoardWorksProperly();
|
||||
await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
|
||||
|
||||
// ----------- Exchange Trade Page -------------
|
||||
await exchangeTradePageRobot.isExchangeTradePage();
|
||||
exchangeTradePageRobot.hasInformationDialog();
|
||||
await exchangeTradePageRobot.onGotItButtonPressed();
|
||||
|
||||
await exchangeTradePageRobot.onConfirmSendingButtonPressed();
|
||||
|
||||
await exchangeTradePageRobot.handleConfirmSendResult();
|
||||
|
||||
await exchangeTradePageRobot.onSendButtonOnConfirmSendingDialogPressed();
|
||||
});
|
||||
});
|
||||
}
|
25
integration_test/helpers/mocks.dart
Normal file
25
integration_test/helpers/mocks.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/store/authentication_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/store/wallet_list_store.dart';
|
||||
import 'package:cake_wallet/view_model/link_view_model.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockAppStore extends Mock implements AppStore{}
|
||||
class MockAuthService extends Mock implements AuthService{}
|
||||
class MockSettingsStore extends Mock implements SettingsStore {}
|
||||
class MockAuthenticationStore extends Mock implements AuthenticationStore{}
|
||||
class MockWalletListStore extends Mock implements WalletListStore{}
|
||||
|
||||
|
||||
|
||||
class MockLinkViewModel extends Mock implements LinkViewModel {}
|
||||
|
||||
class MockHiveInterface extends Mock implements HiveInterface {}
|
||||
|
||||
class MockHiveBox extends Mock implements Box<dynamic> {}
|
||||
|
||||
class MockSecureStorage extends Mock implements SecureStorage{}
|
100
integration_test/helpers/test_helpers.dart
Normal file
100
integration_test/helpers/test_helpers.dart
Normal file
|
@ -0,0 +1,100 @@
|
|||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/store/authentication_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/store/wallet_list_store.dart';
|
||||
import 'package:cake_wallet/view_model/link_view_model.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import 'mocks.dart';
|
||||
|
||||
class TestHelpers {
|
||||
static void setup() {
|
||||
// Fallback values can also be declared here
|
||||
registerDependencies();
|
||||
}
|
||||
|
||||
static void registerDependencies() {
|
||||
getAndRegisterAppStore();
|
||||
getAndRegisterAuthService();
|
||||
getAndRegisterSettingsStore();
|
||||
getAndRegisterAuthenticationStore();
|
||||
getAndRegisterWalletListStore();
|
||||
|
||||
getAndRegisterLinkViewModel();
|
||||
getAndRegisterSecureStorage();
|
||||
getAndRegisterHiveInterface();
|
||||
}
|
||||
|
||||
static MockSettingsStore getAndRegisterSettingsStore() {
|
||||
_removeRegistrationIfExists<SettingsStore>();
|
||||
final service = MockSettingsStore();
|
||||
getIt.registerSingleton<SettingsStore>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockAppStore getAndRegisterAppStore() {
|
||||
_removeRegistrationIfExists<AppStore>();
|
||||
final service = MockAppStore();
|
||||
final settingsStore = getAndRegisterSettingsStore();
|
||||
|
||||
when(() => service.settingsStore).thenAnswer((invocation) => settingsStore);
|
||||
getIt.registerSingleton<AppStore>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockAuthService getAndRegisterAuthService() {
|
||||
_removeRegistrationIfExists<AuthService>();
|
||||
final service = MockAuthService();
|
||||
getIt.registerSingleton<AuthService>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockAuthenticationStore getAndRegisterAuthenticationStore() {
|
||||
_removeRegistrationIfExists<AuthenticationStore>();
|
||||
final service = MockAuthenticationStore();
|
||||
when(() => service.state).thenReturn(AuthenticationState.uninitialized);
|
||||
getIt.registerSingleton<AuthenticationStore>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockWalletListStore getAndRegisterWalletListStore() {
|
||||
_removeRegistrationIfExists<WalletListStore>();
|
||||
final service = MockWalletListStore();
|
||||
getIt.registerSingleton<WalletListStore>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockLinkViewModel getAndRegisterLinkViewModel() {
|
||||
_removeRegistrationIfExists<LinkViewModel>();
|
||||
final service = MockLinkViewModel();
|
||||
getIt.registerSingleton<LinkViewModel>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockHiveInterface getAndRegisterHiveInterface() {
|
||||
_removeRegistrationIfExists<HiveInterface>();
|
||||
final service = MockHiveInterface();
|
||||
final box = MockHiveBox();
|
||||
getIt.registerSingleton<HiveInterface>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static MockSecureStorage getAndRegisterSecureStorage() {
|
||||
_removeRegistrationIfExists<SecureStorage>();
|
||||
final service = MockSecureStorage();
|
||||
getIt.registerSingleton<SecureStorage>(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
static void _removeRegistrationIfExists<T extends Object>() {
|
||||
if (getIt.isRegistered<T>()) {
|
||||
getIt.unregister<T>();
|
||||
}
|
||||
}
|
||||
|
||||
static void tearDown() => getIt.reset();
|
||||
}
|
1
integration_test/integration_response_data.json
Normal file
1
integration_test/integration_response_data.json
Normal file
|
@ -0,0 +1 @@
|
|||
null
|
30
integration_test/robots/auth_page_robot.dart
Normal file
30
integration_test/robots/auth_page_robot.dart
Normal file
|
@ -0,0 +1,30 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
import 'pin_code_widget_robot.dart';
|
||||
|
||||
class AuthPageRobot extends PinCodeWidgetRobot {
|
||||
AuthPageRobot(this.tester)
|
||||
: commonTestCases = CommonTestCases(tester),
|
||||
super(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
bool onAuthPage() {
|
||||
final hasPinButtons = find.byKey(ValueKey('pin_code_button_3_key'));
|
||||
final hasPin = hasPinButtons.tryEvaluate();
|
||||
return hasPin;
|
||||
}
|
||||
|
||||
Future<void> isAuthPage() async {
|
||||
await commonTestCases.isSpecificPage<AuthPage>();
|
||||
}
|
||||
|
||||
void hasTitle() {
|
||||
commonTestCases.hasText(S.current.setup_pin);
|
||||
}
|
||||
}
|
75
integration_test/robots/dashboard_page_robot.dart
Normal file
75
integration_test/robots/dashboard_page_robot.dart
Normal file
|
@ -0,0 +1,75 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class DashboardPageRobot {
|
||||
DashboardPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isDashboardPage() async {
|
||||
await commonTestCases.isSpecificPage<DashboardPage>();
|
||||
}
|
||||
|
||||
void confirmServiceUpdateButtonDisplays() {
|
||||
commonTestCases.hasValueKey('dashboard_page_services_update_button_key');
|
||||
}
|
||||
|
||||
void confirmSyncIndicatorButtonDisplays() {
|
||||
commonTestCases.hasValueKey('dashboard_page_sync_indicator_button_key');
|
||||
}
|
||||
|
||||
void confirmMenuButtonDisplays() {
|
||||
commonTestCases.hasValueKey('dashboard_page_wallet_menu_button_key');
|
||||
}
|
||||
|
||||
Future<void> confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType type,
|
||||
{bool isHaven = false}) async {
|
||||
//Balance Page
|
||||
final walletName = walletTypeToString(type);
|
||||
final assetName = isHaven ? '$walletName Assets' : walletName;
|
||||
commonTestCases.hasText(assetName);
|
||||
|
||||
// Swipe to Cake features Page
|
||||
await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key', swipeRight: false);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
commonTestCases.hasText('Cake ${S.current.features}');
|
||||
|
||||
// Swipe back to balance
|
||||
await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
// Swipe to Transactions Page
|
||||
await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
commonTestCases.hasText(S.current.transactions);
|
||||
|
||||
// Swipe back to balance
|
||||
await commonTestCases.swipeByPageKey(key: 'dashboard_page_view_key', swipeRight: false);
|
||||
await commonTestCases.defaultSleepTime(seconds: 5);
|
||||
}
|
||||
|
||||
Future<void> navigateToBuyPage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.buy}_action_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToSendPage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.send}_action_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToSellPage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.sell}_action_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToReceivePage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.receive}_action_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToExchangePage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.exchange}_action_button_key');
|
||||
}
|
||||
}
|
39
integration_test/robots/disclaimer_page_robot.dart
Normal file
39
integration_test/robots/disclaimer_page_robot.dart
Normal file
|
@ -0,0 +1,39 @@
|
|||
import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class DisclaimerPageRobot {
|
||||
DisclaimerPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isDisclaimerPage() async {
|
||||
await commonTestCases.isSpecificPage<DisclaimerPage>();
|
||||
}
|
||||
|
||||
void hasCheckIcon(bool hasBeenTapped) {
|
||||
// The checked Icon should not be available initially, until user taps the checkbox
|
||||
final checkIcon = find.byKey(ValueKey('disclaimer_check_icon_key'));
|
||||
expect(checkIcon, hasBeenTapped ? findsOneWidget : findsNothing);
|
||||
}
|
||||
|
||||
void hasDisclaimerCheckbox() {
|
||||
final checkBox = find.byKey(ValueKey('disclaimer_check_key'));
|
||||
expect(checkBox, findsOneWidget);
|
||||
}
|
||||
|
||||
Future<void> tapDisclaimerCheckbox() async {
|
||||
await commonTestCases.tapItemByKey('disclaimer_check_key');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> tapAcceptButton() async {
|
||||
await commonTestCases.tapItemByKey('disclaimer_accept_button_key');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
45
integration_test/robots/exchange_confirm_page_robot.dart
Normal file
45
integration_test/robots/exchange_confirm_page_robot.dart
Normal file
|
@ -0,0 +1,45 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangeConfirmPageRobot {
|
||||
ExchangeConfirmPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isExchangeConfirmPage() async {
|
||||
await commonTestCases.isSpecificPage<ExchangeConfirmPage>();
|
||||
}
|
||||
|
||||
void confirmComponentsOfTradeDisplayProperly() {
|
||||
final ExchangeConfirmPage exchangeConfirmPage = tester.widget(find.byType(ExchangeConfirmPage));
|
||||
final trade = exchangeConfirmPage.trade;
|
||||
|
||||
commonTestCases.hasText(trade.id);
|
||||
commonTestCases.hasText('${trade.provider.title} ${S.current.trade_id}');
|
||||
|
||||
commonTestCases.hasValueKey('exchange_confirm_page_saved_id_button_key');
|
||||
commonTestCases.hasValueKey('exchange_confirm_page_copy_to_clipboard_button_key');
|
||||
}
|
||||
|
||||
Future<void> confirmCopyTradeIdToClipBoardWorksProperly() async {
|
||||
final ExchangeConfirmPage exchangeConfirmPage = tester.widget(find.byType(ExchangeConfirmPage));
|
||||
final trade = exchangeConfirmPage.trade;
|
||||
|
||||
await commonTestCases.tapItemByKey('exchange_confirm_page_copy_to_clipboard_button_key');
|
||||
|
||||
ClipboardData? clipboardData = await Clipboard.getData('text/plain');
|
||||
|
||||
expect(clipboardData?.text, trade.id);
|
||||
}
|
||||
|
||||
Future<void> onSavedTradeIdButtonPressed() async {
|
||||
await tester.pumpAndSettle();
|
||||
await commonTestCases.defaultSleepTime();
|
||||
await commonTestCases.tapItemByKey('exchange_confirm_page_saved_id_button_key');
|
||||
}
|
||||
}
|
330
integration_test/robots/exchange_page_robot.dart
Normal file
330
integration_test/robots/exchange_page_robot.dart
Normal file
|
@ -0,0 +1,330 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangePageRobot {
|
||||
ExchangePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isExchangePage() async {
|
||||
await commonTestCases.isSpecificPage<ExchangePage>();
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
void hasResetButton() {
|
||||
commonTestCases.hasText(S.current.reset);
|
||||
}
|
||||
|
||||
void displaysPresentProviderPicker() {
|
||||
commonTestCases.hasType<PresentProviderPicker>();
|
||||
}
|
||||
|
||||
Future<void> displayBothExchangeCards() async {
|
||||
final ExchangePage exchangeCard = tester.widget<ExchangePage>(
|
||||
find.byType(ExchangePage),
|
||||
);
|
||||
|
||||
final depositKey = exchangeCard.depositKey;
|
||||
final receiveKey = exchangeCard.receiveKey;
|
||||
|
||||
final depositExchangeCard = find.byKey(depositKey);
|
||||
expect(depositExchangeCard, findsOneWidget);
|
||||
|
||||
final receiveExchangeCard = find.byKey(receiveKey);
|
||||
expect(receiveExchangeCard, findsOneWidget);
|
||||
}
|
||||
|
||||
void confirmRightComponentsDisplayOnDepositExchangeCards() {
|
||||
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||
final depositCardPrefix = 'deposit_exchange_card';
|
||||
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_title_key');
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_currency_picker_button_key');
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_selected_currency_text_key');
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_amount_textfield_key');
|
||||
|
||||
exchangePage.depositKey.currentState!.changeLimits(min: '0.1');
|
||||
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_min_limit_text_key');
|
||||
|
||||
final initialCurrency = exchangeViewModel.depositCurrency;
|
||||
if (initialCurrency.tag != null) {
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_selected_currency_tag_text_key');
|
||||
}
|
||||
|
||||
if (exchangeViewModel.hasAllAmount) {
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_send_all_button_key');
|
||||
}
|
||||
|
||||
if (exchangeViewModel.isMoneroWallet) {
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_address_book_button_key');
|
||||
}
|
||||
|
||||
if (exchangeViewModel.isDepositAddressEnabled) {
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_editable_address_textfield_key');
|
||||
} else {
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_non_editable_address_textfield_key');
|
||||
commonTestCases.hasValueKey('${depositCardPrefix}_copy_refund_address_button_key');
|
||||
}
|
||||
|
||||
// commonTestCases.hasValueKey('${depositCardPrefix}_max_limit_text_key');
|
||||
}
|
||||
|
||||
void confirmRightComponentsDisplayOnReceiveExchangeCards() {
|
||||
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||
final receiveCardPrefix = 'receive_exchange_card';
|
||||
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_title_key');
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_currency_picker_button_key');
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_selected_currency_text_key');
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_amount_textfield_key');
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_min_limit_text_key');
|
||||
|
||||
final initialCurrency = exchangeViewModel.receiveCurrency;
|
||||
if (initialCurrency.tag != null) {
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_selected_currency_tag_text_key');
|
||||
}
|
||||
|
||||
if (exchangeViewModel.hasAllAmount) {
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_send_all_button_key');
|
||||
}
|
||||
|
||||
if (exchangeViewModel.isMoneroWallet) {
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_address_book_button_key');
|
||||
}
|
||||
|
||||
commonTestCases.hasValueKey('${receiveCardPrefix}_editable_address_textfield_key');
|
||||
}
|
||||
|
||||
Future<void> selectDepositCurrency(CryptoCurrency depositCurrency) async {
|
||||
final depositPrefix = 'deposit_exchange_card';
|
||||
final currencyPickerKey = '${depositPrefix}_currency_picker_button_key';
|
||||
final currencyPickerDialogKey = '${depositPrefix}_currency_picker_dialog_button_key';
|
||||
|
||||
await commonTestCases.tapItemByKey(currencyPickerKey);
|
||||
commonTestCases.hasValueKey(currencyPickerDialogKey);
|
||||
|
||||
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||
|
||||
if (depositCurrency == exchangeViewModel.depositCurrency) {
|
||||
await commonTestCases.defaultSleepTime();
|
||||
await commonTestCases
|
||||
.tapItemByKey('picker_items_index_${depositCurrency.name}_selected_item_button_key');
|
||||
return;
|
||||
}
|
||||
|
||||
await commonTestCases.scrollUntilVisible(
|
||||
'picker_items_index_${depositCurrency.name}_button_key',
|
||||
'picker_scrollbar_key',
|
||||
);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await commonTestCases.tapItemByKey('picker_items_index_${depositCurrency.name}_button_key');
|
||||
}
|
||||
|
||||
Future<void> selectReceiveCurrency(CryptoCurrency receiveCurrency) async {
|
||||
final receivePrefix = 'receive_exchange_card';
|
||||
final currencyPickerKey = '${receivePrefix}_currency_picker_button_key';
|
||||
final currencyPickerDialogKey = '${receivePrefix}_currency_picker_dialog_button_key';
|
||||
|
||||
await commonTestCases.tapItemByKey(currencyPickerKey);
|
||||
commonTestCases.hasValueKey(currencyPickerDialogKey);
|
||||
|
||||
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||
|
||||
if (receiveCurrency == exchangeViewModel.receiveCurrency) {
|
||||
await commonTestCases
|
||||
.tapItemByKey('picker_items_index_${receiveCurrency.name}_selected_item_button_key');
|
||||
return;
|
||||
}
|
||||
|
||||
await commonTestCases.scrollUntilVisible(
|
||||
'picker_items_index_${receiveCurrency.name}_button_key',
|
||||
'picker_scrollbar_key',
|
||||
);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.name}_button_key');
|
||||
}
|
||||
|
||||
Future<void> enterDepositAmount(String amount) async {
|
||||
await commonTestCases.enterText(amount, 'deposit_exchange_card_amount_textfield_key');
|
||||
}
|
||||
|
||||
Future<void> enterDepositRefundAddress({String? depositAddress}) async {
|
||||
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||
|
||||
if (exchangeViewModel.isDepositAddressEnabled && depositAddress != null) {
|
||||
await commonTestCases.enterText(
|
||||
depositAddress, 'deposit_exchange_card_editable_address_textfield_key');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> enterReceiveAddress(String receiveAddress) async {
|
||||
await commonTestCases.enterText(
|
||||
receiveAddress,
|
||||
'receive_exchange_card_editable_address_textfield_key',
|
||||
);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> onExchangeButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('exchange_page_exchange_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
bool hasMaxLimitError() {
|
||||
final maxErrorText = find.text(S.current.error_text_input_above_maximum_limit);
|
||||
|
||||
bool hasMaxError = maxErrorText.tryEvaluate();
|
||||
|
||||
return hasMaxError;
|
||||
}
|
||||
|
||||
bool hasMinLimitError() {
|
||||
final minErrorText = find.text(S.current.error_text_input_below_minimum_limit);
|
||||
|
||||
bool hasMinError = minErrorText.tryEvaluate();
|
||||
|
||||
return hasMinError;
|
||||
}
|
||||
|
||||
bool hasTradeCreationFailureError() {
|
||||
final tradeCreationFailureDialogButton =
|
||||
find.byKey(ValueKey('exchange_page_trade_creation_failure_dialog_button_key'));
|
||||
|
||||
bool hasTradeCreationFailure = tradeCreationFailureDialogButton.tryEvaluate();
|
||||
tester.printToConsole('Trade not created error: $hasTradeCreationFailure');
|
||||
return hasTradeCreationFailure;
|
||||
}
|
||||
|
||||
Future<void> onTradeCreationFailureDialogButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('exchange_page_trade_creation_failure_dialog_button_key');
|
||||
}
|
||||
|
||||
/// Handling Trade Failure Errors or errors shown through the Failure Dialog.
|
||||
///
|
||||
/// Simulating the user's flow and response when this error comes up.
|
||||
/// Examples are:
|
||||
/// - No provider can handle this trade error,
|
||||
/// - Trade amount below limit error.
|
||||
Future<void> _handleTradeCreationFailureErrors() async {
|
||||
bool isTradeCreationFailure = false;
|
||||
|
||||
isTradeCreationFailure = hasTradeCreationFailureError();
|
||||
|
||||
int maxRetries = 20;
|
||||
int retries = 0;
|
||||
|
||||
while (isTradeCreationFailure && retries < maxRetries) {
|
||||
await tester.pump();
|
||||
|
||||
await onTradeCreationFailureDialogButtonPressed();
|
||||
|
||||
await commonTestCases.defaultSleepTime(seconds: 5);
|
||||
|
||||
await onExchangeButtonPressed();
|
||||
|
||||
isTradeCreationFailure = hasTradeCreationFailureError();
|
||||
retries++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the min limit error.
|
||||
///
|
||||
/// Simulates the user's flow and response when it comes up.
|
||||
///
|
||||
/// Has a max retry of 20 times.
|
||||
Future<void> _handleMinLimitError(String initialAmount) async {
|
||||
bool isMinLimitError = false;
|
||||
|
||||
isMinLimitError = hasMinLimitError();
|
||||
|
||||
double amount;
|
||||
|
||||
amount = double.parse(initialAmount);
|
||||
|
||||
int maxRetries = 20;
|
||||
int retries = 0;
|
||||
|
||||
while (isMinLimitError && retries < maxRetries) {
|
||||
amount++;
|
||||
tester.printToConsole('Amount: $amount');
|
||||
|
||||
enterDepositAmount(amount.toString());
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await onExchangeButtonPressed();
|
||||
|
||||
isMinLimitError = hasMinLimitError();
|
||||
|
||||
retries++;
|
||||
}
|
||||
|
||||
if (retries >= maxRetries) {
|
||||
tester.printToConsole('Max retries reached for minLimit Error. Exiting loop.');
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the max limit error.
|
||||
///
|
||||
/// Simulates the user's flow and response when it comes up.
|
||||
///
|
||||
/// Has a max retry of 20 times.
|
||||
Future<void> _handleMaxLimitError(String initialAmount) async {
|
||||
bool isMaxLimitError = false;
|
||||
|
||||
isMaxLimitError = hasMaxLimitError();
|
||||
|
||||
double amount;
|
||||
|
||||
amount = double.parse(initialAmount);
|
||||
|
||||
int maxRetries = 20;
|
||||
int retries = 0;
|
||||
|
||||
while (isMaxLimitError && retries < maxRetries) {
|
||||
amount++;
|
||||
tester.printToConsole('Amount: $amount');
|
||||
|
||||
enterDepositAmount(amount.toString());
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await onExchangeButtonPressed();
|
||||
|
||||
isMaxLimitError = hasMaxLimitError();
|
||||
|
||||
retries++;
|
||||
}
|
||||
|
||||
if (retries >= maxRetries) {
|
||||
tester.printToConsole('Max retries reached for maxLimit Error. Exiting loop.');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleErrors(String initialAmount) async {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await _handleMinLimitError(initialAmount);
|
||||
|
||||
await _handleMaxLimitError(initialAmount);
|
||||
|
||||
await _handleTradeCreationFailureErrors();
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
152
integration_test/robots/exchange_trade_page_robot.dart
Normal file
152
integration_test/robots/exchange_trade_page_robot.dart
Normal file
|
@ -0,0 +1,152 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangeTradePageRobot {
|
||||
ExchangeTradePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isExchangeTradePage() async {
|
||||
await commonTestCases.isSpecificPage<ExchangeTradePage>();
|
||||
}
|
||||
|
||||
void hasInformationDialog() {
|
||||
commonTestCases.hasValueKey('information_page_dialog_key');
|
||||
}
|
||||
|
||||
Future<void> onGotItButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('information_page_got_it_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> onConfirmSendingButtonPressed() async {
|
||||
tester.printToConsole('Now confirming sending');
|
||||
|
||||
await commonTestCases.tapItemByKey(
|
||||
'exchange_trade_page_confirm_sending_button_key',
|
||||
shouldPumpAndSettle: false,
|
||||
);
|
||||
|
||||
final Completer<void> completer = Completer<void>();
|
||||
|
||||
// Loop to wait for the async operation to complete
|
||||
while (true) {
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
final ExchangeTradeState state = tester.state(find.byType(ExchangeTradeForm));
|
||||
final execState = state.widget.exchangeTradeViewModel.sendViewModel.state;
|
||||
|
||||
bool isDone = execState is ExecutedSuccessfullyState;
|
||||
bool isFailed = execState is FailureState;
|
||||
|
||||
tester.printToConsole('isDone: $isDone');
|
||||
tester.printToConsole('isFailed: $isFailed');
|
||||
|
||||
if (isDone || isFailed) {
|
||||
tester.printToConsole(
|
||||
isDone ? 'Completer is done' : 'Completer is done though operation failed');
|
||||
completer.complete();
|
||||
await tester.pump();
|
||||
break;
|
||||
} else {
|
||||
tester.printToConsole('Completer is not done');
|
||||
await tester.pump();
|
||||
}
|
||||
}
|
||||
|
||||
await expectLater(completer.future, completes);
|
||||
|
||||
tester.printToConsole('Done confirming sending');
|
||||
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
}
|
||||
|
||||
Future<void> onSendButtonOnConfirmSendingDialogPressed() async {
|
||||
tester.printToConsole('Send Button on Confirm Dialog Triggered');
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
|
||||
final sendText = find.text(S.current.send);
|
||||
bool hasText = sendText.tryEvaluate();
|
||||
|
||||
if (hasText) {
|
||||
await commonTestCases.tapItemByFinder(sendText);
|
||||
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onCancelButtonOnConfirmSendingDialogPressed() async {
|
||||
tester.printToConsole('Cancel Button on Confirm Dialog Triggered');
|
||||
|
||||
await commonTestCases.tapItemByKey(
|
||||
'exchange_trade_page_confirm_sending_dialog_cancel_button_key',
|
||||
);
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> onSendFailureDialogButtonPressed() async {
|
||||
await commonTestCases.defaultSleepTime(seconds: 6);
|
||||
|
||||
tester.printToConsole('Send Button Failure Dialog Triggered');
|
||||
|
||||
await commonTestCases.tapItemByKey('exchange_trade_page_send_failure_dialog_button_key');
|
||||
}
|
||||
|
||||
Future<bool> hasErrorWhileSending() async {
|
||||
await tester.pump();
|
||||
|
||||
tester.printToConsole('Checking if there is an error');
|
||||
|
||||
final errorDialog = find.byKey(
|
||||
ValueKey('exchange_trade_page_send_failure_dialog_button_key'),
|
||||
);
|
||||
|
||||
bool hasError = errorDialog.tryEvaluate();
|
||||
|
||||
tester.printToConsole('Has error: $hasError');
|
||||
|
||||
return hasError;
|
||||
}
|
||||
|
||||
Future<void> handleConfirmSendResult() async {
|
||||
bool hasError = false;
|
||||
|
||||
hasError = await hasErrorWhileSending();
|
||||
|
||||
int maxRetries = 20;
|
||||
int retries = 0;
|
||||
|
||||
while (hasError && retries < maxRetries) {
|
||||
tester.printToConsole('hasErrorInLoop: $hasError');
|
||||
await tester.pump();
|
||||
|
||||
await onSendFailureDialogButtonPressed();
|
||||
tester.printToConsole('Failure button tapped');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await onConfirmSendingButtonPressed();
|
||||
tester.printToConsole('Confirm sending button tapped');
|
||||
|
||||
hasError = await hasErrorWhileSending();
|
||||
|
||||
retries++;
|
||||
}
|
||||
|
||||
if (!hasError) {
|
||||
tester.printToConsole('No error, proceeding with flow');
|
||||
await tester.pump();
|
||||
}
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
59
integration_test/robots/new_wallet_type_page_robot.dart
Normal file
59
integration_test/robots/new_wallet_type_page_robot.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class NewWalletTypePageRobot {
|
||||
NewWalletTypePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isNewWalletTypePage() async {
|
||||
await commonTestCases.isSpecificPage<NewWalletTypePage>();
|
||||
}
|
||||
|
||||
void displaysCorrectTitle(bool isCreate) {
|
||||
commonTestCases.hasText(
|
||||
isCreate ? S.current.wallet_list_create_new_wallet : S.current.wallet_list_restore_wallet,
|
||||
);
|
||||
}
|
||||
|
||||
void hasWalletTypeForm() {
|
||||
commonTestCases.hasType<WalletTypeForm>();
|
||||
}
|
||||
|
||||
void displaysCorrectImage(ThemeType type) {
|
||||
final walletTypeImage = Image.asset('assets/images/wallet_type.png').image;
|
||||
final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png').image;
|
||||
|
||||
find.image(
|
||||
type == ThemeType.dark ? walletTypeImage : walletTypeLightImage,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> findParticularWalletTypeInScrollableList(WalletType type) async {
|
||||
final scrollableWidget = find.descendant(
|
||||
of: find.byKey(Key('new_wallet_type_scrollable_key')),
|
||||
matching: find.byType(Scrollable),
|
||||
);
|
||||
|
||||
await tester.scrollUntilVisible(
|
||||
find.byKey(ValueKey('new_wallet_type_${type.name}_button_key')),
|
||||
300,
|
||||
scrollable: scrollableWidget,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> selectWalletType(WalletType type) async {
|
||||
await commonTestCases.tapItemByKey('new_wallet_type_${type.name}_button_key');
|
||||
}
|
||||
|
||||
Future<void> onNextButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('new_wallet_type_next_button_key');
|
||||
}
|
||||
}
|
38
integration_test/robots/pin_code_widget_robot.dart
Normal file
38
integration_test/robots/pin_code_widget_robot.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class PinCodeWidgetRobot {
|
||||
PinCodeWidgetRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
void hasPinCodeWidget() {
|
||||
final pinCodeWidget = find.bySubtype<PinCodeWidget>();
|
||||
expect(pinCodeWidget, findsOneWidget);
|
||||
}
|
||||
|
||||
void hasNumberButtonsVisible() {
|
||||
// Confirmation for buttons 1-9
|
||||
for (var i = 1; i < 10; i++) {
|
||||
commonTestCases.hasValueKey('pin_code_button_${i}_key');
|
||||
}
|
||||
|
||||
// Confirmation for 0 button
|
||||
commonTestCases.hasValueKey('pin_code_button_0_key');
|
||||
}
|
||||
|
||||
Future<void> pushPinButton(int index) async {
|
||||
await commonTestCases.tapItemByKey('pin_code_button_${index}_key');
|
||||
}
|
||||
|
||||
Future<void> enterPinCode(List<int> pinCode, bool isFirstEntry) async {
|
||||
for (int pin in pinCode) {
|
||||
await pushPinButton(pin);
|
||||
}
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
89
integration_test/robots/restore_from_seed_or_key_robot.dart
Normal file
89
integration_test/robots/restore_from_seed_or_key_robot.dart
Normal file
|
@ -0,0 +1,89 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class RestoreFromSeedOrKeysPageRobot {
|
||||
RestoreFromSeedOrKeysPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isRestoreFromSeedKeyPage() async {
|
||||
await commonTestCases.isSpecificPage<WalletRestorePage>();
|
||||
}
|
||||
|
||||
Future<void> confirmViewComponentsDisplayProperlyPerPageView() async {
|
||||
commonTestCases.hasText(S.current.wallet_name);
|
||||
commonTestCases.hasText(S.current.enter_seed_phrase);
|
||||
commonTestCases.hasText(S.current.restore_title_from_seed);
|
||||
|
||||
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_name_textfield_key');
|
||||
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_name_refresh_button_key');
|
||||
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_seeds_paste_button_key');
|
||||
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_seeds_textfield_key');
|
||||
|
||||
commonTestCases.hasText(S.current.private_key, hasWidget: false);
|
||||
commonTestCases.hasText(S.current.restore_title_from_keys, hasWidget: false);
|
||||
|
||||
await commonTestCases.swipePage();
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
commonTestCases.hasText(S.current.wallet_name);
|
||||
commonTestCases.hasText(S.current.private_key);
|
||||
commonTestCases.hasText(S.current.restore_title_from_keys);
|
||||
|
||||
commonTestCases.hasText(S.current.enter_seed_phrase, hasWidget: false);
|
||||
commonTestCases.hasText(S.current.restore_title_from_seed, hasWidget: false);
|
||||
|
||||
await commonTestCases.swipePage(swipeRight: false);
|
||||
}
|
||||
|
||||
void confirmRestoreButtonDisplays() {
|
||||
commonTestCases.hasValueKey('wallet_restore_seed_or_key_restore_button_key');
|
||||
}
|
||||
|
||||
void confirmAdvancedSettingButtonDisplays() {
|
||||
commonTestCases.hasValueKey('wallet_restore_advanced_settings_button_key');
|
||||
}
|
||||
|
||||
Future<void> enterWalletNameText(String walletName, {bool isSeedFormEntry = true}) async {
|
||||
await commonTestCases.enterText(
|
||||
walletName,
|
||||
'wallet_restore_from_${isSeedFormEntry ? 'seed' : 'keys'}_wallet_name_textfield_key',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> selectWalletNameFromAvailableOptions({bool isSeedFormEntry = true}) async {
|
||||
await commonTestCases.tapItemByKey(
|
||||
'wallet_restore_from_${isSeedFormEntry ? 'seed' : 'keys'}_wallet_name_refresh_button_key',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> enterSeedPhraseForWalletRestore(String text) async {
|
||||
ValidatableAnnotatedEditableTextState seedTextState =
|
||||
await tester.state(find.byType(ValidatableAnnotatedEditableText));
|
||||
|
||||
seedTextState.widget.controller.text = text;
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> onPasteSeedPhraseButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('wallet_restore_from_seed_wallet_seeds_paste_button_key');
|
||||
}
|
||||
|
||||
Future<void> enterPrivateKeyForWalletRestore(String privateKey) async {
|
||||
await commonTestCases.enterText(
|
||||
privateKey,
|
||||
'wallet_restore_from_key_private_key_textfield_key',
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> onRestoreWalletButtonPressed() async {
|
||||
await commonTestCases.tapItemByKey('wallet_restore_seed_or_key_restore_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
42
integration_test/robots/restore_options_page_robot.dart
Normal file
42
integration_test/robots/restore_options_page_robot.dart
Normal file
|
@ -0,0 +1,42 @@
|
|||
import 'package:cake_wallet/src/screens/restore/restore_options_page.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class RestoreOptionsPageRobot {
|
||||
RestoreOptionsPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isRestoreOptionsPage() async {
|
||||
await commonTestCases.isSpecificPage<RestoreOptionsPage>();
|
||||
}
|
||||
|
||||
void hasRestoreOptionsButton() {
|
||||
commonTestCases.hasValueKey('restore_options_from_seeds_button_key');
|
||||
commonTestCases.hasValueKey('restore_options_from_backup_button_key');
|
||||
commonTestCases.hasValueKey('restore_options_from_hardware_wallet_button_key');
|
||||
commonTestCases.hasValueKey('restore_options_from_qr_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreFromSeedsPage() async {
|
||||
await commonTestCases.tapItemByKey('restore_options_from_seeds_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreFromBackupPage() async {
|
||||
await commonTestCases.tapItemByKey('restore_options_from_backup_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreFromHardwareWalletPage() async {
|
||||
await commonTestCases.tapItemByKey('restore_options_from_hardware_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> backAndVerify() async {
|
||||
await commonTestCases.goBack();
|
||||
await isRestoreOptionsPage();
|
||||
}
|
||||
}
|
366
integration_test/robots/send_page_robot.dart
Normal file
366
integration_test/robots/send_page_robot.dart
Normal file
|
@ -0,0 +1,366 @@
|
|||
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/view_model/send/send_view_model_state.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
import '../components/common_test_constants.dart';
|
||||
import 'auth_page_robot.dart';
|
||||
|
||||
class SendPageRobot {
|
||||
SendPageRobot({required this.tester})
|
||||
: commonTestCases = CommonTestCases(tester),
|
||||
authPageRobot = AuthPageRobot(tester);
|
||||
|
||||
WidgetTester tester;
|
||||
CommonTestCases commonTestCases;
|
||||
AuthPageRobot authPageRobot;
|
||||
|
||||
Future<void> isSendPage() async {
|
||||
await commonTestCases.isSpecificPage<SendPage>();
|
||||
}
|
||||
|
||||
void hasTitle() {
|
||||
commonTestCases.hasText(S.current.send);
|
||||
}
|
||||
|
||||
void confirmViewComponentsDisplayProperly() {
|
||||
SendPage sendPage = tester.widget(find.byType(SendPage));
|
||||
final sendViewModel = sendPage.sendViewModel;
|
||||
|
||||
commonTestCases.hasValueKey('send_page_address_textfield_key');
|
||||
commonTestCases.hasValueKey('send_page_note_textfield_key');
|
||||
commonTestCases.hasValueKey('send_page_amount_textfield_key');
|
||||
commonTestCases.hasValueKey('send_page_add_template_button_key');
|
||||
|
||||
if (sendViewModel.hasMultipleTokens) {
|
||||
commonTestCases.hasValueKey('send_page_currency_picker_button_key');
|
||||
}
|
||||
|
||||
if (!sendViewModel.isBatchSending) {
|
||||
commonTestCases.hasValueKey('send_page_send_all_button_key');
|
||||
}
|
||||
|
||||
if (!sendViewModel.isFiatDisabled) {
|
||||
commonTestCases.hasValueKey('send_page_fiat_amount_textfield_key');
|
||||
}
|
||||
|
||||
if (sendViewModel.hasFees) {
|
||||
commonTestCases.hasValueKey('send_page_select_fee_priority_button_key');
|
||||
}
|
||||
|
||||
if (sendViewModel.hasCoinControl) {
|
||||
commonTestCases.hasValueKey('send_page_unspent_coin_button_key');
|
||||
}
|
||||
|
||||
if (sendViewModel.hasCurrecyChanger) {
|
||||
commonTestCases.hasValueKey('send_page_change_asset_button_key');
|
||||
}
|
||||
|
||||
if (sendViewModel.sendTemplateViewModel.hasMultiRecipient) {
|
||||
commonTestCases.hasValueKey('send_page_add_receiver_button_key');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> selectReceiveCurrency(CryptoCurrency receiveCurrency) async {
|
||||
final currencyPickerKey = 'send_page_currency_picker_button_key';
|
||||
final currencyPickerDialogKey = 'send_page_currency_picker_dialog_button_key';
|
||||
|
||||
await commonTestCases.tapItemByKey(currencyPickerKey);
|
||||
commonTestCases.hasValueKey(currencyPickerDialogKey);
|
||||
|
||||
SendPage sendPage = tester.widget(find.byType(SendPage));
|
||||
final sendViewModel = sendPage.sendViewModel;
|
||||
|
||||
if (receiveCurrency == sendViewModel.selectedCryptoCurrency) {
|
||||
await commonTestCases
|
||||
.tapItemByKey('picker_items_index_${receiveCurrency.name}_selected_item_button_key');
|
||||
return;
|
||||
}
|
||||
|
||||
await commonTestCases.scrollUntilVisible(
|
||||
'picker_items_index_${receiveCurrency.name}_button_key',
|
||||
'picker_scrollbar_key',
|
||||
);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.name}_button_key');
|
||||
}
|
||||
|
||||
Future<void> enterReceiveAddress(String receiveAddress) async {
|
||||
await commonTestCases.enterText(receiveAddress, 'send_page_address_textfield_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> enterAmount(String amount) async {
|
||||
await commonTestCases.enterText(amount, 'send_page_amount_textfield_key');
|
||||
}
|
||||
|
||||
Future<void> selectTransactionPriority({TransactionPriority? priority}) async {
|
||||
SendPage sendPage = tester.widget(find.byType(SendPage));
|
||||
final sendViewModel = sendPage.sendViewModel;
|
||||
|
||||
if (!sendViewModel.hasFees || priority == null) return;
|
||||
|
||||
final transactionPriorityPickerKey = 'send_page_select_fee_priority_button_key';
|
||||
await commonTestCases.tapItemByKey(transactionPriorityPickerKey);
|
||||
|
||||
if (priority == sendViewModel.transactionPriority) {
|
||||
await commonTestCases
|
||||
.tapItemByKey('picker_items_index_${priority.title}_selected_item_button_key');
|
||||
return;
|
||||
}
|
||||
|
||||
await commonTestCases.scrollUntilVisible(
|
||||
'picker_items_index_${priority.title}_button_key',
|
||||
'picker_scrollbar_key',
|
||||
);
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await commonTestCases.tapItemByKey('picker_items_index_${priority.title}_button_key');
|
||||
}
|
||||
|
||||
Future<void> onSendButtonPressed() async {
|
||||
tester.printToConsole('Pressing send');
|
||||
|
||||
await commonTestCases.tapItemByKey(
|
||||
'send_page_send_button_key',
|
||||
shouldPumpAndSettle: false,
|
||||
);
|
||||
|
||||
await _waitForSendTransactionCompletion();
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> _waitForSendTransactionCompletion() async {
|
||||
await tester.pump();
|
||||
final Completer<void> completer = Completer<void>();
|
||||
|
||||
// Loop to wait for the async operation to complete
|
||||
while (true) {
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
tester.printToConsole('Before _handleAuth');
|
||||
|
||||
await _handleAuthPage();
|
||||
|
||||
tester.printToConsole('After _handleAuth');
|
||||
|
||||
await tester.pump();
|
||||
|
||||
final sendPage = tester.widget<SendPage>(find.byType(SendPage));
|
||||
final state = sendPage.sendViewModel.state;
|
||||
|
||||
await tester.pump();
|
||||
|
||||
bool isDone = state is ExecutedSuccessfullyState;
|
||||
bool isFailed = state is FailureState;
|
||||
|
||||
tester.printToConsole('isDone: $isDone');
|
||||
tester.printToConsole('isFailed: $isFailed');
|
||||
|
||||
if (isDone || isFailed) {
|
||||
tester.printToConsole(
|
||||
isDone ? 'Completer is done' : 'Completer is done though operation failed',
|
||||
);
|
||||
completer.complete();
|
||||
await tester.pump();
|
||||
break;
|
||||
} else {
|
||||
tester.printToConsole('Completer is not done');
|
||||
await tester.pump();
|
||||
}
|
||||
}
|
||||
|
||||
await expectLater(completer.future, completes);
|
||||
|
||||
tester.printToConsole('Done confirming sending operation');
|
||||
}
|
||||
|
||||
Future<void> _handleAuthPage() async {
|
||||
tester.printToConsole('Inside _handleAuth');
|
||||
await tester.pump();
|
||||
tester.printToConsole('starting auth checks');
|
||||
|
||||
final authPage = authPageRobot.onAuthPage();
|
||||
|
||||
tester.printToConsole('hasAuth:$authPage');
|
||||
|
||||
if (authPage) {
|
||||
await tester.pump();
|
||||
tester.printToConsole('Starting inner _handleAuth loop checks');
|
||||
|
||||
try {
|
||||
await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
tester.printToConsole('Auth done');
|
||||
|
||||
await tester.pump();
|
||||
|
||||
tester.printToConsole('Auth pump done');
|
||||
} catch (e) {
|
||||
tester.printToConsole('Auth failed, retrying');
|
||||
await tester.pump();
|
||||
_handleAuthPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleSendResult() async {
|
||||
tester.printToConsole('Inside handle function');
|
||||
|
||||
bool hasError = false;
|
||||
|
||||
hasError = await hasErrorWhileSending();
|
||||
|
||||
tester.printToConsole('Has an Error in the handle: $hasError');
|
||||
|
||||
int maxRetries = 20;
|
||||
int retries = 0;
|
||||
|
||||
while (hasError && retries < maxRetries) {
|
||||
tester.printToConsole('hasErrorInLoop: $hasError');
|
||||
await tester.pump();
|
||||
|
||||
await onSendFailureDialogButtonPressed();
|
||||
tester.printToConsole('Failure button tapped');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
await onSendButtonPressed();
|
||||
tester.printToConsole('Send button tapped');
|
||||
|
||||
hasError = await hasErrorWhileSending();
|
||||
|
||||
retries++;
|
||||
}
|
||||
|
||||
if (!hasError) {
|
||||
tester.printToConsole('No error, proceeding with flow');
|
||||
await tester.pump();
|
||||
}
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
//* ------ On Sending Failure ------------
|
||||
Future<bool> hasErrorWhileSending() async {
|
||||
await tester.pump();
|
||||
|
||||
tester.printToConsole('Checking if there is an error');
|
||||
|
||||
final errorDialog = find.byKey(ValueKey('send_page_send_failure_dialog_button_key'));
|
||||
|
||||
bool hasError = errorDialog.tryEvaluate();
|
||||
|
||||
tester.printToConsole('Has error: $hasError');
|
||||
|
||||
return hasError;
|
||||
}
|
||||
|
||||
Future<void> onSendFailureDialogButtonPressed() async {
|
||||
await commonTestCases.defaultSleepTime();
|
||||
|
||||
tester.printToConsole('Send Button Failure Dialog Triggered');
|
||||
|
||||
await commonTestCases.tapItemByKey('send_page_send_failure_dialog_button_key');
|
||||
}
|
||||
|
||||
//* ------ On Sending Success ------------
|
||||
Future<void> onSendButtonOnConfirmSendingDialogPressed() async {
|
||||
tester.printToConsole('Inside confirm sending dialog: For sending');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
await tester.pump();
|
||||
|
||||
final sendText = find.text(S.current.send).last;
|
||||
bool hasText = sendText.tryEvaluate();
|
||||
tester.printToConsole('Has Text: $hasText');
|
||||
|
||||
if (hasText) {
|
||||
await commonTestCases.tapItemByFinder(sendText, shouldPumpAndSettle: false);
|
||||
// Loop to wait for the operation to commit transaction
|
||||
await _waitForCommitTransactionCompletion();
|
||||
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
} else {
|
||||
await commonTestCases.defaultSleepTime();
|
||||
await tester.pump();
|
||||
onSendButtonOnConfirmSendingDialogPressed();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _waitForCommitTransactionCompletion() async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
|
||||
while (true) {
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
final sendPage = tester.widget<SendPage>(find.byType(SendPage));
|
||||
final state = sendPage.sendViewModel.state;
|
||||
|
||||
bool isDone = state is TransactionCommitted;
|
||||
bool isFailed = state is FailureState;
|
||||
|
||||
tester.printToConsole('isDone: $isDone');
|
||||
tester.printToConsole('isFailed: $isFailed');
|
||||
|
||||
if (isDone || isFailed) {
|
||||
tester.printToConsole(
|
||||
isDone ? 'Completer is done' : 'Completer is done though operation failed',
|
||||
);
|
||||
completer.complete();
|
||||
await tester.pump();
|
||||
break;
|
||||
} else {
|
||||
tester.printToConsole('Completer is not done');
|
||||
await tester.pump();
|
||||
}
|
||||
}
|
||||
|
||||
await expectLater(completer.future, completes);
|
||||
|
||||
tester.printToConsole('Done Committing Transaction');
|
||||
}
|
||||
|
||||
Future<void> onCancelButtonOnConfirmSendingDialogPressed() async {
|
||||
tester.printToConsole('Inside confirm sending dialog: For canceling');
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
|
||||
final cancelText = find.text(S.current.cancel);
|
||||
bool hasText = cancelText.tryEvaluate();
|
||||
|
||||
if (hasText) {
|
||||
await commonTestCases.tapItemByFinder(cancelText);
|
||||
|
||||
await commonTestCases.defaultSleepTime(seconds: 4);
|
||||
}
|
||||
}
|
||||
|
||||
//* ---- Add Contact Dialog On Send Successful Dialog -----
|
||||
Future<void> onSentDialogPopUp() async {
|
||||
SendPage sendPage = tester.widget(find.byType(SendPage));
|
||||
final sendViewModel = sendPage.sendViewModel;
|
||||
|
||||
final newContactAddress = sendPage.newContactAddress ?? sendViewModel.newContactAddress();
|
||||
if (newContactAddress != null) {
|
||||
await _onAddContactButtonOnSentDialogPressed();
|
||||
}
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> _onAddContactButtonOnSentDialogPressed() async {
|
||||
await commonTestCases.tapItemByKey('send_page_sent_dialog_add_contact_button_key');
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Future<void> _onIgnoreButtonOnSentDialogPressed() async {
|
||||
await commonTestCases.tapItemByKey('send_page_sent_dialog_ignore_button_key');
|
||||
}
|
||||
}
|
28
integration_test/robots/setup_pin_code_robot.dart
Normal file
28
integration_test/robots/setup_pin_code_robot.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
import 'pin_code_widget_robot.dart';
|
||||
|
||||
class SetupPinCodeRobot extends PinCodeWidgetRobot {
|
||||
SetupPinCodeRobot(this.tester)
|
||||
: commonTestCases = CommonTestCases(tester),
|
||||
super(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isSetupPinCodePage() async {
|
||||
await commonTestCases.isSpecificPage<SetupPinCodePage>();
|
||||
}
|
||||
|
||||
void hasTitle() {
|
||||
commonTestCases.hasText(S.current.setup_pin);
|
||||
}
|
||||
|
||||
Future<void> tapSuccessButton() async {
|
||||
await commonTestCases.tapItemByKey('setup_pin_code_success_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
40
integration_test/robots/welcome_page_robot.dart
Normal file
40
integration_test/robots/welcome_page_robot.dart
Normal file
|
@ -0,0 +1,40 @@
|
|||
import 'package:cake_wallet/src/screens/welcome/welcome_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class WelcomePageRobot {
|
||||
WelcomePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
||||
final WidgetTester tester;
|
||||
late CommonTestCases commonTestCases;
|
||||
|
||||
Future<void> isWelcomePage() async {
|
||||
await commonTestCases.isSpecificPage<WelcomePage>();
|
||||
}
|
||||
|
||||
void confirmActionButtonsDisplay() {
|
||||
final createNewWalletButton = find.byKey(ValueKey('welcome_page_create_new_wallet_button_key'));
|
||||
|
||||
final restoreWalletButton = find.byKey(ValueKey('welcome_page_restore_wallet_button_key'));
|
||||
|
||||
expect(createNewWalletButton, findsOneWidget);
|
||||
expect(restoreWalletButton, findsOneWidget);
|
||||
}
|
||||
|
||||
Future<void> navigateToCreateNewWalletPage() async {
|
||||
await commonTestCases.tapItemByKey('welcome_page_create_new_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreWalletPage() async {
|
||||
await commonTestCases.tapItemByKey('welcome_page_restore_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> backAndVerify() async {
|
||||
await commonTestCases.goBack();
|
||||
await isWelcomePage();
|
||||
}
|
||||
}
|
59
integration_test/test_suites/exchange_flow_test.dart
Normal file
59
integration_test/test_suites/exchange_flow_test.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../components/common_test_constants.dart';
|
||||
import '../components/common_test_flows.dart';
|
||||
import '../robots/auth_page_robot.dart';
|
||||
import '../robots/dashboard_page_robot.dart';
|
||||
import '../robots/exchange_confirm_page_robot.dart';
|
||||
import '../robots/exchange_page_robot.dart';
|
||||
import '../robots/exchange_trade_page_robot.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
AuthPageRobot authPageRobot;
|
||||
CommonTestFlows commonTestFlows;
|
||||
ExchangePageRobot exchangePageRobot;
|
||||
DashboardPageRobot dashboardPageRobot;
|
||||
ExchangeTradePageRobot exchangeTradePageRobot;
|
||||
ExchangeConfirmPageRobot exchangeConfirmPageRobot;
|
||||
|
||||
group('Exchange Flow Tests', () {
|
||||
testWidgets('Exchange flow', (tester) async {
|
||||
authPageRobot = AuthPageRobot(tester);
|
||||
commonTestFlows = CommonTestFlows(tester);
|
||||
exchangePageRobot = ExchangePageRobot(tester);
|
||||
dashboardPageRobot = DashboardPageRobot(tester);
|
||||
exchangeTradePageRobot = ExchangeTradePageRobot(tester);
|
||||
exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
|
||||
|
||||
await commonTestFlows.startAppFlow(ValueKey('exchange_app_test_key'));
|
||||
await commonTestFlows.restoreWalletThroughSeedsFlow();
|
||||
await dashboardPageRobot.navigateToExchangePage();
|
||||
|
||||
// ----------- Exchange Page -------------
|
||||
await exchangePageRobot.selectDepositCurrency(CommonTestConstants.testDepositCurrency);
|
||||
await exchangePageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
|
||||
|
||||
await exchangePageRobot.enterDepositAmount(CommonTestConstants.exchangeTestAmount);
|
||||
await exchangePageRobot.enterDepositRefundAddress(
|
||||
depositAddress: CommonTestConstants.testWalletAddress,
|
||||
);
|
||||
await exchangePageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
|
||||
|
||||
await exchangePageRobot.onExchangeButtonPressed();
|
||||
|
||||
await exchangePageRobot.handleErrors(CommonTestConstants.exchangeTestAmount);
|
||||
|
||||
final onAuthPage = authPageRobot.onAuthPage();
|
||||
if (onAuthPage) {
|
||||
await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
}
|
||||
|
||||
await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed();
|
||||
await exchangeTradePageRobot.onGotItButtonPressed();
|
||||
});
|
||||
});
|
||||
}
|
41
integration_test/test_suites/send_flow_test.dart
Normal file
41
integration_test/test_suites/send_flow_test.dart
Normal file
|
@ -0,0 +1,41 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../components/common_test_constants.dart';
|
||||
import '../components/common_test_flows.dart';
|
||||
import '../robots/dashboard_page_robot.dart';
|
||||
import '../robots/send_page_robot.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
SendPageRobot sendPageRobot;
|
||||
CommonTestFlows commonTestFlows;
|
||||
DashboardPageRobot dashboardPageRobot;
|
||||
|
||||
group('Send Flow Tests', () {
|
||||
testWidgets('Send flow', (tester) async {
|
||||
commonTestFlows = CommonTestFlows(tester);
|
||||
sendPageRobot = SendPageRobot(tester: tester);
|
||||
dashboardPageRobot = DashboardPageRobot(tester);
|
||||
|
||||
await commonTestFlows.startAppFlow(ValueKey('send_test_app_key'));
|
||||
await commonTestFlows.restoreWalletThroughSeedsFlow();
|
||||
await dashboardPageRobot.navigateToSendPage();
|
||||
|
||||
await sendPageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
|
||||
await sendPageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
|
||||
await sendPageRobot.enterAmount(CommonTestConstants.sendTestAmount);
|
||||
await sendPageRobot.selectTransactionPriority();
|
||||
|
||||
await sendPageRobot.onSendButtonPressed();
|
||||
|
||||
await sendPageRobot.handleSendResult();
|
||||
|
||||
await sendPageRobot.onSendButtonOnConfirmSendingDialogPressed();
|
||||
|
||||
await sendPageRobot.onSentDialogPopUp();
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue