-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
1 parent
32e119e
commit 4adb81c
Showing
67 changed files
with
2,381 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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(); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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{} |
Oops, something went wrong.