mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 17:27:37 +00:00
test: Test for Send flow scenario and minor restructuring for test folders and files
This commit is contained in:
parent
9dc96d7d22
commit
989ecbb2de
38 changed files with 787 additions and 366 deletions
|
@ -1,3 +1,4 @@
|
|||
# Commenting out for now, will bring back after I get the CI flow for Automated Testing stable
|
||||
name: Automated Integration Test
|
||||
|
||||
on:
|
||||
|
@ -215,7 +216,7 @@ jobs:
|
|||
script: |
|
||||
cd /opt/android/cake_wallet
|
||||
flutter pub get
|
||||
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart
|
||||
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Tests failed"
|
||||
exit 1
|
||||
|
|
|
@ -305,18 +305,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: ffigen
|
||||
sha256: d3e76c2ad48a4e7f93a29a162006f00eba46ce7c08194a77bb5c5e97d1b5ff0a
|
||||
sha256: "3e12e80ccb6539bb3917217bb6f32709220efb737de0d0fa8736da0b7cb507da"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.2"
|
||||
version: "12.0.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -793,8 +793,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "sp_v2.0.0"
|
||||
resolved-ref: "62c152b9086cd968019128845371072f7e1168de"
|
||||
ref: "sp_v2.1.0"
|
||||
resolved-ref: b4b8fbd8d832198d3cee853feb427c4ec482dd7d
|
||||
url: "https://github.com/cake-tech/sp_scanner"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
|
|
|
@ -205,10 +205,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -212,10 +212,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -254,10 +254,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -514,14 +514,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -707,10 +699,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0+3"
|
||||
version: "1.0.4"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -212,10 +212,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -254,10 +254,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -555,14 +555,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -748,10 +740,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0+3"
|
||||
version: "1.0.4"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -252,10 +252,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -212,10 +212,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -254,10 +254,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -555,14 +555,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -748,10 +740,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0+3"
|
||||
version: "1.0.4"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
import 'package:cake_wallet/main.dart' as app;
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'robots/auth_page_robot.dart';
|
||||
import 'robots/dashboard_page_robot.dart';
|
||||
import 'robots/disclaimer_page_robot.dart';
|
||||
import 'robots/exchange_confirm_page_robot.dart';
|
||||
import 'robots/exchange_page_robot.dart';
|
||||
import 'robots/exchange_trade_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 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
DisclaimerPageRobot disclaimerPageRobot;
|
||||
WelcomePageRobot welcomePageRobot;
|
||||
SetupPinCodeRobot setupPinCodeRobot;
|
||||
RestoreOptionsPageRobot restoreOptionsPageRobot;
|
||||
NewWalletTypePageRobot newWalletTypePageRobot;
|
||||
RestoreFromSeedOrKeysPageRobot restoreFromSeedOrKeysPageRobot;
|
||||
DashboardPageRobot dashboardPageRobot;
|
||||
ExchangePageRobot exchangePageRobot;
|
||||
ExchangeConfirmPageRobot exchangeConfirmPageRobot;
|
||||
AuthPageRobot authPageRobot;
|
||||
ExchangeTradePageRobot exchangeTradePageRobot;
|
||||
|
||||
group('Startup Test', () {
|
||||
testWidgets(
|
||||
'Test for Exchange flow using Restore Wallet, -Up to the point where the sending is to be triggered',
|
||||
(tester) async {
|
||||
authPageRobot = AuthPageRobot(tester);
|
||||
welcomePageRobot = WelcomePageRobot(tester);
|
||||
exchangePageRobot = ExchangePageRobot(tester);
|
||||
setupPinCodeRobot = SetupPinCodeRobot(tester);
|
||||
dashboardPageRobot = DashboardPageRobot(tester);
|
||||
disclaimerPageRobot = DisclaimerPageRobot(tester);
|
||||
exchangeTradePageRobot = ExchangeTradePageRobot(tester);
|
||||
newWalletTypePageRobot = NewWalletTypePageRobot(tester);
|
||||
restoreOptionsPageRobot = RestoreOptionsPageRobot(tester);
|
||||
exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
|
||||
restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(tester);
|
||||
|
||||
final pin = [0, 8, 0, 1];
|
||||
|
||||
// String testAmount = '0.08';
|
||||
String testAmount = '8';
|
||||
CryptoCurrency testReceiveCurrency = CryptoCurrency.sol;
|
||||
CryptoCurrency testDepositCurrency = CryptoCurrency.usdtSol;
|
||||
|
||||
WalletType testWalletType = WalletType.solana;
|
||||
String testWalletName = 'Integrated Testing Wallet';
|
||||
String testWalletAddress = 'An2Y2fsUYKfYvN1zF89GAqR1e6GUMBg3qA83Y5ZWDf8L';
|
||||
|
||||
await app.main();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// --------- Disclaimer Page ------------
|
||||
// Tap checkbox to accept disclaimer
|
||||
await disclaimerPageRobot.tapDisclaimerCheckbox();
|
||||
|
||||
// Tap accept button
|
||||
await disclaimerPageRobot.tapAcceptButton();
|
||||
|
||||
// --------- 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(pin, true);
|
||||
await setupPinCodeRobot.enterPinCode(pin, false);
|
||||
await setupPinCodeRobot.tapSuccessButton();
|
||||
|
||||
// ----------- NewWalletType Page -------------
|
||||
// Confirm scroll behaviour works properly
|
||||
await newWalletTypePageRobot.findParticularWalletTypeInScrollableList(WalletType.solana);
|
||||
|
||||
// Select a wallet and route to next page
|
||||
await newWalletTypePageRobot.selectWalletType(testWalletType);
|
||||
await newWalletTypePageRobot.onNextButtonPressed();
|
||||
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await restoreFromSeedOrKeysPageRobot.enterWalletNameText(testWalletName);
|
||||
await restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore(secrets.seeds);
|
||||
await restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await dashboardPageRobot.navigateToExchangePage();
|
||||
|
||||
// ----------- Exchange Page -------------
|
||||
await exchangePageRobot.isExchangePage();
|
||||
exchangePageRobot.hasResetButton();
|
||||
await exchangePageRobot.displayBothExchangeCards();
|
||||
exchangePageRobot.confirmRightComponentsDisplayOnDepositExchangeCards();
|
||||
exchangePageRobot.confirmRightComponentsDisplayOnReceiveExchangeCards();
|
||||
|
||||
await exchangePageRobot.selectDepositCurrency(testDepositCurrency);
|
||||
await exchangePageRobot.selectReceiveCurrency(testReceiveCurrency);
|
||||
|
||||
await exchangePageRobot.enterDepositAmount(testAmount);
|
||||
await exchangePageRobot.enterDepositRefundAddress(depositAddress: testWalletAddress);
|
||||
|
||||
await exchangePageRobot.enterReceiveAddress(testWalletAddress);
|
||||
|
||||
await exchangePageRobot.onExchangeButtonPressed();
|
||||
|
||||
await exchangePageRobot.handleErrors(testAmount);
|
||||
|
||||
final onAuthPage = authPageRobot.onAuthPage();
|
||||
if (onAuthPage) {
|
||||
await authPageRobot.enterPinCode(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();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -10,15 +10,15 @@ class CommonTestCases {
|
|||
hasType<T>();
|
||||
}
|
||||
|
||||
Future<void> tapItemByKey(String key) async {
|
||||
Future<void> tapItemByKey(String key, {bool shouldPumpAndSettle = true}) async {
|
||||
final widget = find.byKey(ValueKey(key));
|
||||
await tester.tap(widget);
|
||||
await tester.pumpAndSettle();
|
||||
shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
|
||||
}
|
||||
|
||||
Future<void> tapItemByFinder(Finder finder) async {
|
||||
Future<void> tapItemByFinder(Finder finder, {bool shouldPumpAndSettle = true}) async {
|
||||
await tester.tap(finder);
|
||||
await tester.pumpAndSettle();
|
||||
shouldPumpAndSettle ? await tester.pumpAndSettle() : await tester.pump();
|
||||
}
|
||||
|
||||
void hasText(String text, {bool hasWidget = true}) {
|
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.seeds);
|
||||
await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
}
|
||||
|
||||
Future<void> _restoreFromKeys() async {
|
||||
await _commonTestCases.swipePage();
|
||||
await _commonTestCases.defaultSleepTime();
|
||||
|
||||
await _restoreFromSeedOrKeysPageRobot.enterWalletNameText(CommonTestConstants.testWalletName);
|
||||
|
||||
await _restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore('');
|
||||
await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
}
|
||||
}
|
|
@ -1,100 +1,38 @@
|
|||
import 'package:cake_wallet/main.dart' as app;
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
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/disclaimer_page_robot.dart';
|
||||
import 'robots/exchange_confirm_page_robot.dart';
|
||||
import 'robots/exchange_page_robot.dart';
|
||||
import 'robots/exchange_trade_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 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
DisclaimerPageRobot disclaimerPageRobot;
|
||||
WelcomePageRobot welcomePageRobot;
|
||||
SetupPinCodeRobot setupPinCodeRobot;
|
||||
RestoreOptionsPageRobot restoreOptionsPageRobot;
|
||||
NewWalletTypePageRobot newWalletTypePageRobot;
|
||||
RestoreFromSeedOrKeysPageRobot restoreFromSeedOrKeysPageRobot;
|
||||
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);
|
||||
welcomePageRobot = WelcomePageRobot(tester);
|
||||
exchangePageRobot = ExchangePageRobot(tester);
|
||||
setupPinCodeRobot = SetupPinCodeRobot(tester);
|
||||
dashboardPageRobot = DashboardPageRobot(tester);
|
||||
disclaimerPageRobot = DisclaimerPageRobot(tester);
|
||||
exchangeTradePageRobot = ExchangeTradePageRobot(tester);
|
||||
newWalletTypePageRobot = NewWalletTypePageRobot(tester);
|
||||
restoreOptionsPageRobot = RestoreOptionsPageRobot(tester);
|
||||
exchangeConfirmPageRobot = ExchangeConfirmPageRobot(tester);
|
||||
restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(tester);
|
||||
commonTestFlows = CommonTestFlows(tester);
|
||||
|
||||
final pin = [0, 8, 0, 1];
|
||||
await commonTestFlows.startAppFlow(ValueKey('funds_exchange_test_app_key'));
|
||||
|
||||
// String testAmount = '0.08';
|
||||
String testAmount = '8';
|
||||
CryptoCurrency testReceiveCurrency = CryptoCurrency.sol;
|
||||
CryptoCurrency testDepositCurrency = CryptoCurrency.usdtSol;
|
||||
|
||||
WalletType testWalletType = WalletType.solana;
|
||||
String testWalletName = 'Integrated Testing Wallet';
|
||||
String testWalletAddress = 'An2Y2fsUYKfYvN1zF89GAqR1e6GUMBg3qA83Y5ZWDf8L';
|
||||
|
||||
await app.main();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// --------- Disclaimer Page ------------
|
||||
// Tap checkbox to accept disclaimer
|
||||
await disclaimerPageRobot.tapDisclaimerCheckbox();
|
||||
|
||||
// Tap accept button
|
||||
await disclaimerPageRobot.tapAcceptButton();
|
||||
|
||||
// --------- 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(pin, true);
|
||||
await setupPinCodeRobot.enterPinCode(pin, false);
|
||||
await setupPinCodeRobot.tapSuccessButton();
|
||||
|
||||
// ----------- NewWalletType Page -------------
|
||||
// Confirm scroll behaviour works properly
|
||||
await newWalletTypePageRobot.findParticularWalletTypeInScrollableList(WalletType.solana);
|
||||
|
||||
// Select a wallet and route to next page
|
||||
await newWalletTypePageRobot.selectWalletType(testWalletType);
|
||||
await newWalletTypePageRobot.onNextButtonPressed();
|
||||
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await restoreFromSeedOrKeysPageRobot.enterWalletNameText(testWalletName);
|
||||
await restoreFromSeedOrKeysPageRobot.enterSeedPhraseForWalletRestore(secrets.seeds);
|
||||
await restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed();
|
||||
await commonTestFlows.restoreWalletThroughSeedsFlow();
|
||||
|
||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||
await dashboardPageRobot.navigateToExchangePage();
|
||||
|
@ -106,21 +44,22 @@ void main() {
|
|||
exchangePageRobot.confirmRightComponentsDisplayOnDepositExchangeCards();
|
||||
exchangePageRobot.confirmRightComponentsDisplayOnReceiveExchangeCards();
|
||||
|
||||
await exchangePageRobot.selectDepositCurrency(testDepositCurrency);
|
||||
await exchangePageRobot.selectReceiveCurrency(testReceiveCurrency);
|
||||
await exchangePageRobot.selectDepositCurrency(CommonTestConstants.testDepositCurrency);
|
||||
await exchangePageRobot.selectReceiveCurrency(CommonTestConstants.testReceiveCurrency);
|
||||
|
||||
await exchangePageRobot.enterDepositAmount(testAmount);
|
||||
await exchangePageRobot.enterDepositRefundAddress(depositAddress: testWalletAddress);
|
||||
await exchangePageRobot.enterDepositAmount(CommonTestConstants.exchangeTestAmount);
|
||||
await exchangePageRobot.enterDepositRefundAddress(
|
||||
depositAddress: CommonTestConstants.testWalletAddress);
|
||||
|
||||
await exchangePageRobot.enterReceiveAddress(testWalletAddress);
|
||||
await exchangePageRobot.enterReceiveAddress(CommonTestConstants.testWalletAddress);
|
||||
|
||||
await exchangePageRobot.onExchangeButtonPressed();
|
||||
|
||||
await exchangePageRobot.handleErrors(testAmount);
|
||||
await exchangePageRobot.handleErrors(CommonTestConstants.exchangeTestAmount);
|
||||
|
||||
final onAuthPage = authPageRobot.onAuthPage();
|
||||
if (onAuthPage) {
|
||||
await authPageRobot.enterPinCode(pin, false);
|
||||
await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
}
|
||||
|
||||
// ----------- Exchange Confirm Page -------------
|
||||
|
@ -137,7 +76,7 @@ void main() {
|
|||
|
||||
await exchangeTradePageRobot.onConfirmSendingButtonPressed();
|
||||
|
||||
await exchangeTradePageRobot.handleSendSuccessOrFailure();
|
||||
await exchangeTradePageRobot.handleConfirmSendResult();
|
||||
|
||||
await exchangeTradePageRobot.onSendButtonOnConfirmSendingDialogPressed();
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
import 'pin_code_widget_robot.dart';
|
||||
|
||||
class AuthPageRobot extends PinCodeWidgetRobot {
|
||||
|
|
|
@ -3,7 +3,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class DashboardPageRobot {
|
||||
DashboardPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -58,7 +58,7 @@ class DashboardPageRobot {
|
|||
}
|
||||
|
||||
Future<void> navigateToSendPage() async {
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.buy}_action_button_key');
|
||||
await commonTestCases.tapItemByKey('dashboard_page_${S.current.send}_action_button_key');
|
||||
}
|
||||
|
||||
Future<void> navigateToSellPage() async {
|
||||
|
|
|
@ -2,7 +2,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class DisclaimerPageRobot {
|
||||
DisclaimerPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -26,15 +26,14 @@ class DisclaimerPageRobot {
|
|||
}
|
||||
|
||||
Future<void> tapDisclaimerCheckbox() async {
|
||||
final checkBox = find.byKey(ValueKey('disclaimer_check_key'));
|
||||
await tester.tap(checkBox);
|
||||
await tester.pumpAndSettle();
|
||||
await commonTestCases.tapItemByKey('disclaimer_check_key');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> tapAcceptButton() async {
|
||||
final checkBox = find.byKey(ValueKey('disclaimer_accept_button_key'));
|
||||
await tester.tap(checkBox);
|
||||
await tester.pumpAndSettle();
|
||||
await commonTestCases.tapItemByKey('disclaimer_accept_button_key');
|
||||
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dar
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangeConfirmPageRobot {
|
||||
ExchangeConfirmPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -38,6 +38,8 @@ class ExchangeConfirmPageRobot {
|
|||
}
|
||||
|
||||
Future<void> onSavedTradeIdButtonPressed() async {
|
||||
await tester.pumpAndSettle();
|
||||
await commonTestCases.defaultSleepTime();
|
||||
await commonTestCases.tapItemByKey('exchange_confirm_page_saved_id_button_key');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:cw_core/crypto_currency.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangePageRobot {
|
||||
ExchangePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -317,6 +317,8 @@ class ExchangePageRobot {
|
|||
}
|
||||
|
||||
Future<void> handleErrors(String initialAmount) async {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await _handleMinLimitError(initialAmount);
|
||||
|
||||
await _handleMaxLimitError(initialAmount);
|
||||
|
|
|
@ -6,7 +6,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class ExchangeTradePageRobot {
|
||||
ExchangeTradePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -30,9 +30,10 @@ class ExchangeTradePageRobot {
|
|||
Future<void> onConfirmSendingButtonPressed() async {
|
||||
tester.printToConsole('Now confirming sending');
|
||||
|
||||
final widget = find.byKey(ValueKey('exchange_trade_page_confirm_sending_button_key'));
|
||||
await tester.tap(widget);
|
||||
await tester.pump();
|
||||
await commonTestCases.tapItemByKey(
|
||||
'exchange_trade_page_confirm_sending_button_key',
|
||||
shouldPumpAndSettle: false,
|
||||
);
|
||||
|
||||
final Completer<void> completer = Completer<void>();
|
||||
|
||||
|
@ -116,7 +117,7 @@ class ExchangeTradePageRobot {
|
|||
return hasError;
|
||||
}
|
||||
|
||||
Future<void> handleSendSuccessOrFailure() async {
|
||||
Future<void> handleConfirmSendResult() async {
|
||||
bool hasError = false;
|
||||
|
||||
hasError = await hasErrorWhileSending();
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:cw_core/wallet_type.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class NewWalletTypePageRobot {
|
||||
NewWalletTypePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class PinCodeWidgetRobot {
|
||||
PinCodeWidgetRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -29,7 +29,6 @@ class PinCodeWidgetRobot {
|
|||
}
|
||||
|
||||
Future<void> enterPinCode(List<int> pinCode, bool isFirstEntry) async {
|
||||
|
||||
for (int pin in pinCode) {
|
||||
await pushPinButton(pin);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class RestoreFromSeedOrKeysPageRobot {
|
||||
RestoreFromSeedOrKeysPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -49,13 +49,17 @@ class RestoreFromSeedOrKeysPageRobot {
|
|||
commonTestCases.hasValueKey('wallet_restore_advanced_settings_button_key');
|
||||
}
|
||||
|
||||
Future<void> enterWalletNameText(String walletName) async {
|
||||
Future<void> enterWalletNameText(String walletName, {bool isSeedFormEntry = true}) async {
|
||||
await commonTestCases.enterText(
|
||||
walletName, 'wallet_restore_from_seed_wallet_name_textfield_key');
|
||||
walletName,
|
||||
'wallet_restore_from_${isSeedFormEntry ? 'seed' : 'keys'}_wallet_name_textfield_key',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> selectWalletNameFromAvailableOptions() async {
|
||||
await commonTestCases.tapItemByKey('wallet_restore_from_seed_wallet_name_refresh_button_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 {
|
||||
|
@ -70,6 +74,14 @@ class RestoreFromSeedOrKeysPageRobot {
|
|||
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();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:cake_wallet/src/screens/restore/restore_options_page.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../components/common_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class RestoreOptionsPageRobot {
|
||||
RestoreOptionsPageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -21,19 +21,16 @@ class RestoreOptionsPageRobot {
|
|||
}
|
||||
|
||||
Future<void> navigateToRestoreFromSeedsPage() async {
|
||||
tester.printToConsole('Routing to restore from seeds page');
|
||||
await commonTestCases.tapItemByKey('restore_options_from_seeds_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreFromBackupPage() async {
|
||||
tester.printToConsole('Routing to restore from backup page');
|
||||
await commonTestCases.tapItemByKey('restore_options_from_backup_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreFromHardwareWalletPage() async {
|
||||
tester.printToConsole('Routing to restore from hardware wallet page');
|
||||
await commonTestCases.tapItemByKey('restore_options_from_hardware_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
|
349
integration_test/robots/send_page_robot.dart
Normal file
349
integration_test/robots/send_page_robot.dart
Normal file
|
@ -0,0 +1,349 @@
|
|||
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 {
|
||||
|
||||
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 in auth');
|
||||
|
||||
await _handleAuthPage();
|
||||
|
||||
tester.printToConsole('After in auth');
|
||||
|
||||
final sendPage = tester.widget<SendPage>(find.byType(SendPage));
|
||||
final state = sendPage.sendViewModel.state;
|
||||
|
||||
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 {
|
||||
final authPage = authPageRobot.onAuthPage();
|
||||
if (authPage) {
|
||||
tester.printToConsole('Auth');
|
||||
await tester.pump();
|
||||
|
||||
await authPageRobot.enterPinCode(CommonTestConstants.pin, false);
|
||||
tester.printToConsole('Auth done');
|
||||
|
||||
await tester.pump();
|
||||
|
||||
tester.printToConsole('Auth pump done');
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
import 'pin_code_widget_robot.dart';
|
||||
|
||||
class SetupPinCodeRobot extends PinCodeWidgetRobot {
|
||||
|
|
|
@ -2,7 +2,7 @@ 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_checks.dart';
|
||||
import '../components/common_test_cases.dart';
|
||||
|
||||
class WelcomePageRobot {
|
||||
WelcomePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||
|
@ -24,13 +24,11 @@ class WelcomePageRobot {
|
|||
}
|
||||
|
||||
Future<void> navigateToCreateNewWalletPage() async {
|
||||
tester.printToConsole('Routing to create new wallet page');
|
||||
await commonTestCases.tapItemByKey('welcome_page_create_new_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
||||
Future<void> navigateToRestoreWalletPage() async {
|
||||
tester.printToConsole('Routing to restore wallet page');
|
||||
await commonTestCases.tapItemByKey('welcome_page_restore_wallet_button_key');
|
||||
await commonTestCases.defaultSleepTime();
|
||||
}
|
||||
|
|
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();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -46,7 +46,7 @@ final navigatorKey = GlobalKey<NavigatorState>();
|
|||
final rootKey = GlobalKey<RootState>();
|
||||
final RouteObserver<PageRoute<dynamic>> routeObserver = RouteObserver<PageRoute<dynamic>>();
|
||||
|
||||
Future<void> main() async {
|
||||
Future<void> main({Key? topLevelKey}) async {
|
||||
bool isAppRunning = false;
|
||||
await runZonedGuarded(() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
@ -67,7 +67,7 @@ Future<void> main() async {
|
|||
|
||||
await initializeAppConfigs();
|
||||
|
||||
runApp(App());
|
||||
runApp(App(key: topLevelKey));
|
||||
|
||||
isAppRunning = true;
|
||||
}, (error, stackTrace) async {
|
||||
|
@ -253,6 +253,9 @@ Future<void> initialSetup(
|
|||
}
|
||||
|
||||
class App extends StatefulWidget {
|
||||
App({this.key});
|
||||
|
||||
final Key? key;
|
||||
@override
|
||||
AppState createState() => AppState();
|
||||
}
|
||||
|
@ -281,7 +284,7 @@ class AppState extends State<App> with SingleTickerProviderStateMixin {
|
|||
statusBarIconBrightness: statusBarIconBrightness));
|
||||
|
||||
return Root(
|
||||
key: rootKey,
|
||||
key: widget.key ?? rootKey,
|
||||
appStore: appStore,
|
||||
authenticationStore: authenticationStore,
|
||||
navigatorKey: navigatorKey,
|
||||
|
|
|
@ -365,7 +365,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: AddressTextField(
|
||||
key: ValueKey('${_cardInstanceName}_editable_address_textfield_key'),
|
||||
addressKey: ValueKey('${_cardInstanceName}_editable_address_textfield_key'),
|
||||
focusNode: widget.addressFocusNode,
|
||||
controller: addressController,
|
||||
onURIScanned: (uri) {
|
||||
|
|
|
@ -82,10 +82,12 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
|
|||
alignment: Alignment.centerRight,
|
||||
children: [
|
||||
BaseTextFormField(
|
||||
key: ValueKey('wallet_restore_from_keys_wallet_name_textfield_key'),
|
||||
controller: nameTextEditingController,
|
||||
hintText: S.of(context).wallet_name,
|
||||
validator: WalletNameValidator(),
|
||||
suffixIcon: IconButton(
|
||||
key: ValueKey('wallet_restore_from_keys_wallet_name_refresh_button_key'),
|
||||
onPressed: () async {
|
||||
final rName = await generateName();
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
@ -132,6 +134,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
|
|||
bool nanoBased = widget.walletRestoreViewModel.type == WalletType.nano ||
|
||||
widget.walletRestoreViewModel.type == WalletType.banano;
|
||||
return AddressTextField(
|
||||
addressKey: ValueKey('wallet_restore_from_key_private_key_textfield_key'),
|
||||
controller: privateKeyController,
|
||||
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
|
||||
options: [AddressTextFieldOption.paste],
|
||||
|
|
|
@ -112,7 +112,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
controller: nameTextEditingController,
|
||||
hintText: S.of(context).wallet_name,
|
||||
suffixIcon: IconButton(
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_name_refresh_button_key'),
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_name_refresh_button_key'),
|
||||
onPressed: () async {
|
||||
final rName = await generateName();
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
@ -145,10 +145,13 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
|||
)),
|
||||
Container(height: 20),
|
||||
SeedWidget(
|
||||
key: seedWidgetStateKey,
|
||||
language: language,
|
||||
type: widget.type,
|
||||
onSeedChange: onSeedChange),
|
||||
key: seedWidgetStateKey,
|
||||
language: language,
|
||||
type: widget.type,
|
||||
onSeedChange: onSeedChange,
|
||||
seedTextFieldKey: ValueKey('wallet_restore_from_seed_wallet_seeds_textfield_key'),
|
||||
pasteButtonKey: ValueKey('wallet_restore_from_seed_wallet_seeds_paste_button_key'),
|
||||
),
|
||||
if (widget.type == WalletType.monero || widget.type == WalletType.wownero)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
|
|
|
@ -68,11 +68,11 @@ class SendPage extends BasePage {
|
|||
|
||||
@override
|
||||
Function(BuildContext)? get pushToNextWidget => (context) {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.focusedChild?.unfocus();
|
||||
}
|
||||
};
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.focusedChild?.unfocus();
|
||||
}
|
||||
};
|
||||
|
||||
@override
|
||||
Widget? leading(BuildContext context) {
|
||||
|
@ -246,6 +246,7 @@ class SendPage extends BasePage {
|
|||
return Row(
|
||||
children: <Widget>[
|
||||
AddTemplateButton(
|
||||
key: ValueKey('send_page_add_template_button_key'),
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate),
|
||||
currentTemplatesLength: templates.length,
|
||||
),
|
||||
|
@ -333,19 +334,22 @@ class SendPage extends BasePage {
|
|||
children: [
|
||||
if (sendViewModel.hasCurrecyChanger)
|
||||
Observer(
|
||||
builder: (_) => Padding(
|
||||
padding: EdgeInsets.only(bottom: 12),
|
||||
child: PrimaryButton(
|
||||
onPressed: () => presentCurrencyPicker(context),
|
||||
text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
|
||||
color: Colors.transparent,
|
||||
textColor:
|
||||
Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
|
||||
))),
|
||||
builder: (_) => Padding(
|
||||
padding: EdgeInsets.only(bottom: 12),
|
||||
child: PrimaryButton(
|
||||
key: ValueKey('send_page_change_asset_button_key'),
|
||||
onPressed: () => presentCurrencyPicker(context),
|
||||
text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
|
||||
color: Colors.transparent,
|
||||
textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 12),
|
||||
child: PrimaryButton(
|
||||
key: ValueKey('send_page_add_receiver_button_key'),
|
||||
onPressed: () {
|
||||
sendViewModel.addOutput();
|
||||
Future.delayed(const Duration(milliseconds: 250), () {
|
||||
|
@ -362,6 +366,7 @@ class SendPage extends BasePage {
|
|||
Observer(
|
||||
builder: (_) {
|
||||
return LoadingPrimaryButton(
|
||||
key: ValueKey('send_page_send_button_key'),
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
||||
if (sendViewModel.outputs.length > 1) {
|
||||
|
@ -444,6 +449,8 @@ class SendPage extends BasePage {
|
|||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
key: ValueKey('send_page_send_failure_dialog_key'),
|
||||
buttonKey: ValueKey('send_page_send_failure_dialog_button_key'),
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
|
@ -459,6 +466,7 @@ class SendPage extends BasePage {
|
|||
context: context,
|
||||
builder: (BuildContext _dialogContext) {
|
||||
return ConfirmSendingAlert(
|
||||
key: ValueKey('send_page_confirm_sending_dialog_key'),
|
||||
alertTitle: S.of(_dialogContext).confirm_sending,
|
||||
amount: S.of(_dialogContext).send_amount,
|
||||
amountValue: sendViewModel.pendingTransaction!.amountFormatted,
|
||||
|
@ -472,6 +480,10 @@ class SendPage extends BasePage {
|
|||
outputs: sendViewModel.outputs,
|
||||
rightButtonText: S.of(_dialogContext).send,
|
||||
leftButtonText: S.of(_dialogContext).cancel,
|
||||
alertRightActionButtonKey:
|
||||
ValueKey('send_page_confirm_sending_dialog_send_button_key'),
|
||||
alertLeftActionButtonKey:
|
||||
ValueKey('send_page_confirm_sending_dialog_cancel_button_key'),
|
||||
actionRightButton: () async {
|
||||
Navigator.of(_dialogContext).pop();
|
||||
sendViewModel.commitTransaction();
|
||||
|
@ -505,10 +517,15 @@ class SendPage extends BasePage {
|
|||
|
||||
if (newContactAddress != null) {
|
||||
return AlertWithTwoActions(
|
||||
alertDialogKey: ValueKey('send_page_sent_dialog_key'),
|
||||
alertTitle: '',
|
||||
alertContent: alertContent,
|
||||
rightButtonText: S.of(_dialogContext).add_contact,
|
||||
leftButtonText: S.of(_dialogContext).ignor,
|
||||
alertLeftActionButtonKey:
|
||||
ValueKey('send_page_sent_dialog_ignore_button_key'),
|
||||
alertRightActionButtonKey: ValueKey(
|
||||
'send_page_sent_dialog_add_contact_button_key'),
|
||||
actionRightButton: () {
|
||||
Navigator.of(_dialogContext).pop();
|
||||
RequestReviewHandler.requestReview();
|
||||
|
|
|
@ -157,6 +157,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
: sendViewModel.addressValidator;
|
||||
|
||||
return AddressTextField(
|
||||
addressKey: ValueKey('send_page_address_textfield_key'),
|
||||
focusNode: addressFocusNode,
|
||||
controller: addressController,
|
||||
onURIScanned: (uri) {
|
||||
|
@ -221,6 +222,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
padding: EdgeInsets.only(right: 8),
|
||||
height: 32,
|
||||
child: InkWell(
|
||||
key: ValueKey('send_page_currency_picker_button_key'),
|
||||
onTap: () => _presentPicker(context),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -298,6 +300,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
child: Stack(
|
||||
children: [
|
||||
BaseTextFormField(
|
||||
key: ValueKey('send_page_amount_textfield_key'),
|
||||
focusNode: cryptoAmountFocus,
|
||||
controller: cryptoAmountController,
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
|
@ -332,6 +335,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
width: prefixIconWidth,
|
||||
height: prefixIconHeight,
|
||||
child: InkWell(
|
||||
key: ValueKey('send_page_send_all_button_key'),
|
||||
onTap: () async {
|
||||
output.setSendAll(sendViewModel.balance);
|
||||
},
|
||||
|
@ -405,6 +409,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: BaseTextFormField(
|
||||
key: ValueKey('send_page_fiat_amount_textfield_key'),
|
||||
focusNode: fiatAmountFocus,
|
||||
controller: fiatAmountController,
|
||||
keyboardType:
|
||||
|
@ -440,6 +445,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: BaseTextFormField(
|
||||
key: ValueKey('send_page_note_textfield_key'),
|
||||
controller: noteController,
|
||||
keyboardType: TextInputType.multiline,
|
||||
maxLines: null,
|
||||
|
@ -458,6 +464,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
if (sendViewModel.hasFees)
|
||||
Observer(
|
||||
builder: (_) => GestureDetector(
|
||||
key: ValueKey('send_page_select_fee_priority_button_key'),
|
||||
onTap: sendViewModel.hasFeesPriority
|
||||
? () => pickTransactionPriority(context)
|
||||
: () {},
|
||||
|
@ -531,6 +538,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: GestureDetector(
|
||||
key: ValueKey('send_page_unspent_coin_button_key'),
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsList),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
|
@ -715,6 +723,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
|
|||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => CurrencyPicker(
|
||||
key: ValueKey('send_page_currency_picker_dialog_button_key'),
|
||||
selectedAtIndex: sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency),
|
||||
items: sendViewModel.currencies,
|
||||
hintText: S.of(context).search_currency,
|
||||
|
|
|
@ -15,24 +15,26 @@ import 'package:permission_handler/permission_handler.dart';
|
|||
enum AddressTextFieldOption { paste, qrCode, addressBook }
|
||||
|
||||
class AddressTextField extends StatelessWidget {
|
||||
AddressTextField(
|
||||
{required this.controller,
|
||||
this.isActive = true,
|
||||
this.placeholder,
|
||||
this.options = const [AddressTextFieldOption.qrCode, AddressTextFieldOption.addressBook],
|
||||
this.onURIScanned,
|
||||
this.focusNode,
|
||||
this.isBorderExist = true,
|
||||
this.buttonColor,
|
||||
this.borderColor,
|
||||
this.iconColor,
|
||||
this.textStyle,
|
||||
this.hintStyle,
|
||||
this.validator,
|
||||
this.onPushPasteButton,
|
||||
this.onPushAddressBookButton,
|
||||
this.onSelectedContact,
|
||||
this.selectedCurrency, super.key});
|
||||
AddressTextField({
|
||||
required this.controller,
|
||||
this.isActive = true,
|
||||
this.placeholder,
|
||||
this.options = const [AddressTextFieldOption.qrCode, AddressTextFieldOption.addressBook],
|
||||
this.onURIScanned,
|
||||
this.focusNode,
|
||||
this.isBorderExist = true,
|
||||
this.buttonColor,
|
||||
this.borderColor,
|
||||
this.iconColor,
|
||||
this.textStyle,
|
||||
this.hintStyle,
|
||||
this.validator,
|
||||
this.onPushPasteButton,
|
||||
this.onPushAddressBookButton,
|
||||
this.onSelectedContact,
|
||||
this.selectedCurrency,
|
||||
this.addressKey,
|
||||
});
|
||||
|
||||
static const prefixIconWidth = 34.0;
|
||||
static const prefixIconHeight = 34.0;
|
||||
|
@ -55,28 +57,27 @@ class AddressTextField extends StatelessWidget {
|
|||
final Function(BuildContext context)? onPushAddressBookButton;
|
||||
final Function(ContactBase contact)? onSelectedContact;
|
||||
final CryptoCurrency? selectedCurrency;
|
||||
final Key? addressKey;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
key: addressKey,
|
||||
enableIMEPersonalizedLearning: false,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
onFieldSubmitted: (_) => FocusScope.of(context).unfocus(),
|
||||
enabled: isActive,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
|
||||
style: textStyle ??
|
||||
TextStyle(
|
||||
fontSize: 16, color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
decoration: InputDecoration(
|
||||
|
||||
suffixIcon: SizedBox(
|
||||
width: prefixIconWidth * options.length + (spaceBetweenPrefixIcons * options.length),
|
||||
),
|
||||
|
||||
hintStyle: hintStyle ?? TextStyle(fontSize: 16, color: Theme.of(context).hintColor),
|
||||
hintText: placeholder ?? S.current.widgets_address,
|
||||
focusedBorder: isBorderExist
|
||||
|
@ -194,7 +195,7 @@ class AddressTextField extends StatelessWidget {
|
|||
|
||||
Future<void> _presentQRScanner(BuildContext context) async {
|
||||
bool isCameraPermissionGranted =
|
||||
await PermissionHandler.checkPermission(Permission.camera, context);
|
||||
await PermissionHandler.checkPermission(Permission.camera, context);
|
||||
if (!isCameraPermissionGranted) return;
|
||||
final code = await presentQRScanner();
|
||||
if (code.isEmpty) {
|
||||
|
|
|
@ -14,6 +14,9 @@ class AlertWithTwoActions extends BaseAlertDialog {
|
|||
this.isDividerExist = false,
|
||||
// this.leftActionColor,
|
||||
// this.rightActionColor,
|
||||
this.alertRightActionButtonKey,
|
||||
this.alertLeftActionButtonKey,
|
||||
this.alertDialogKey,
|
||||
});
|
||||
|
||||
final String alertTitle;
|
||||
|
@ -26,6 +29,9 @@ class AlertWithTwoActions extends BaseAlertDialog {
|
|||
// final Color leftActionColor;
|
||||
// final Color rightActionColor;
|
||||
final bool isDividerExist;
|
||||
final Key? alertRightActionButtonKey;
|
||||
final Key? alertLeftActionButtonKey;
|
||||
final Key? alertDialogKey;
|
||||
|
||||
@override
|
||||
String get titleText => alertTitle;
|
||||
|
@ -47,4 +53,13 @@ class AlertWithTwoActions extends BaseAlertDialog {
|
|||
// Color get rightButtonColor => rightActionColor;
|
||||
@override
|
||||
bool get isDividerExists => isDividerExist;
|
||||
|
||||
@override
|
||||
Key? get dialogKey => alertDialogKey;
|
||||
|
||||
@override
|
||||
Key? get leftActionButtonKey => alertLeftActionButtonKey;
|
||||
|
||||
@override
|
||||
Key? get rightActionButtonKey => alertRightActionButtonKey;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
|
||||
Key? rightActionButtonKey;
|
||||
|
||||
Key? dialogKey;
|
||||
|
||||
Widget title(BuildContext context) {
|
||||
return Text(
|
||||
titleText,
|
||||
|
@ -158,6 +160,7 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
key: key,
|
||||
onTap: () => barrierDismissible ? Navigator.of(context).pop() : null,
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:math';
|
|||
|
||||
import 'package:cake_wallet/src/widgets/search_bar_widget.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
|
||||
|
@ -303,11 +304,25 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
);
|
||||
}
|
||||
|
||||
String _getItemName(Item item) {
|
||||
String itemName;
|
||||
if (item is Currency) {
|
||||
itemName = item.name;
|
||||
} else if (item is TransactionPriority) {
|
||||
itemName = item.title;
|
||||
} else {
|
||||
itemName = '';
|
||||
}
|
||||
|
||||
return itemName;
|
||||
}
|
||||
|
||||
Widget buildItem(int index) {
|
||||
final item = widget.headerEnabled ? filteredItems[index] : items[index];
|
||||
|
||||
final tag = item is Currency ? item.tag : null;
|
||||
final currencyName = item is Currency ? item.name : '';
|
||||
final itemName = _getItemName(item);
|
||||
|
||||
final icon = _getItemIcon(item);
|
||||
|
||||
final image = images.isNotEmpty ? filteredImages[index] : icon;
|
||||
|
@ -327,7 +342,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
key: ValueKey('picker_items_index_${currencyName}_text_key'),
|
||||
key: ValueKey('picker_items_index_${itemName}_text_key'),
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
|
@ -371,7 +386,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
);
|
||||
|
||||
return GestureDetector(
|
||||
key: ValueKey('picker_items_index_${currencyName}_button_key'),
|
||||
key: ValueKey('picker_items_index_${itemName}_button_key'),
|
||||
onTap: () {
|
||||
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
||||
onItemSelected(item!);
|
||||
|
@ -397,7 +412,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
final item = items[index];
|
||||
|
||||
final tag = item is Currency ? item.tag : null;
|
||||
final currencyName = item is Currency ? item.name : '';
|
||||
final itemName = _getItemName(item);
|
||||
final icon = _getItemIcon(item);
|
||||
|
||||
final image = images.isNotEmpty ? images[index] : icon;
|
||||
|
@ -418,7 +433,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
key: ValueKey('picker_items_index_${currencyName}_selected_item_text_key'),
|
||||
key: ValueKey('picker_items_index_${itemName}_selected_item_text_key'),
|
||||
widget.displayItem?.call(item) ?? item.toString(),
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
|
@ -462,7 +477,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
);
|
||||
|
||||
return GestureDetector(
|
||||
key: ValueKey('picker_items_index_${currencyName}_selected_item_button_key'),
|
||||
key: ValueKey('picker_items_index_${itemName}_selected_item_button_key'),
|
||||
onTap: () {
|
||||
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
||||
},
|
||||
|
|
|
@ -12,9 +12,12 @@ class SeedWidget extends StatefulWidget {
|
|||
required this.language,
|
||||
required this.type,
|
||||
this.onSeedChange,
|
||||
this.pasteButtonKey,
|
||||
this.seedTextFieldKey,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final Key? seedTextFieldKey;
|
||||
final Key? pasteButtonKey;
|
||||
final String language;
|
||||
final WalletType type;
|
||||
final void Function(String)? onSeedChange;
|
||||
|
@ -79,12 +82,11 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
top: 10,
|
||||
left: 0,
|
||||
child: Text(S.of(context).enter_seed_phrase,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0, color: Theme.of(context).hintColor))),
|
||||
style: TextStyle(fontSize: 16.0, color: Theme.of(context).hintColor))),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 40, top: 10),
|
||||
child: ValidatableAnnotatedEditableText(
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_seeds_textfield_key'),
|
||||
key: widget.seedTextFieldKey,
|
||||
cursorColor: Colors.blue,
|
||||
backgroundCursorColor: Colors.blue,
|
||||
validStyle: TextStyle(
|
||||
|
@ -114,16 +116,17 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
width: 32,
|
||||
height: 32,
|
||||
child: InkWell(
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_seeds_paste_button_key'),
|
||||
key: widget.pasteButtonKey,
|
||||
onTap: () async => _pasteText(),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).hintColor,
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(6))),
|
||||
borderRadius: BorderRadius.all(Radius.circular(6))),
|
||||
child: Image.asset('assets/images/paste_ios.png',
|
||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)),
|
||||
color: Theme.of(context)
|
||||
.extension<SendPageTheme>()!
|
||||
.textFieldButtonIconColor)),
|
||||
)))
|
||||
]),
|
||||
Container(
|
||||
|
|
Loading…
Reference in a new issue