Skip to content

Commit 832a4f9

Browse files
authored
test: Add Stake e2e automation (#13180)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** These are the Stake flows this PR will automate: - Stake - Unstake - Stake more - Claim - Making sure staking balance, banners, and actions are hidden for ETH assets that aren't on mainnet or holesky To run them locally follow these steps: - Build the app locally and make sure you set the following ENV variables: `export MM_MULTICHAIN_V1_ENABLED="true"` `export MM_CHAIN_PERMISSIONS="true"` `export MM_PERMISSIONS_SETTINGS_V1_ENABLED="false"` `export PORTFOLIO_VIEW="true"` `export MM_SECURITY_ALERTS_API_ENABLED="true"` `export MM_NETWORK_UI_REDESIGN_ENABLED= "false"` and run `yarn test:e2e:android:debug:build` - Run the following command ` yarn test:e2e:android:debug:run e2e/specs/stake/stake-action-smoke.spec.js` ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
1 parent 1937f9a commit 832a4f9

File tree

23 files changed

+519
-50
lines changed

23 files changed

+519
-50
lines changed

app/components/Base/StatusText.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { StyleSheet } from 'react-native';
55
import { FIAT_ORDER_STATES } from '../../constants/on-ramp';
66
import { strings } from '../../../locales/i18n';
77
import { useTheme } from '../../util/theme';
8-
import { CommonSelectorsIDs } from '../../../e2e/selectors/Common.selectors';
98

109
const styles = StyleSheet.create({
1110
status: {
@@ -15,43 +14,55 @@ const styles = StyleSheet.create({
1514
},
1615
});
1716

18-
export const ConfirmedText = (props) => (
17+
export const ConfirmedText = ({testID, ...props}) => (
1918
<Text
20-
testID={CommonSelectorsIDs.TRANSACTION_STATUS}
19+
testID={testID}
2120
bold
2221
green
2322
style={styles.status}
2423
{...props}
2524
/>
2625
);
27-
export const PendingText = (props) => {
26+
ConfirmedText.propTypes = {
27+
testID: PropTypes.string,
28+
};
29+
30+
export const PendingText = ({testID, ...props}) => {
2831
const { colors } = useTheme();
2932
return (
3033
<Text
34+
testID={testID}
3135
bold
3236
style={[styles.status, { color: colors.warning.default }]}
3337
{...props}
3438
/>
3539
);
3640
};
37-
export const FailedText = (props) => {
41+
PendingText.propTypes = {
42+
testID: PropTypes.string,
43+
};
44+
45+
export const FailedText = ({testID, ...props} ) => {
3846
const { colors } = useTheme();
3947
return (
4048
<Text
41-
testID={CommonSelectorsIDs.TRANSACTION_STATUS}
49+
testID={testID}
4250
bold
4351
style={[styles.status, { color: colors.error.default }]}
4452
{...props}
4553
/>
4654
);
4755
};
56+
FailedText.propTypes = {
57+
testID: PropTypes.string,
58+
};
4859

49-
function StatusText({ status, context, ...props }) {
60+
function StatusText({ status, context, testID, ...props }) {
5061
switch (status) {
5162
case 'Confirmed':
5263
case 'confirmed':
5364
return (
54-
<ConfirmedText {...props}>
65+
<ConfirmedText testID={testID} {...props}>
5566
{strings(`${context}.${status}`)}
5667
</ConfirmedText>
5768
);
@@ -60,14 +71,14 @@ function StatusText({ status, context, ...props }) {
6071
case 'Submitted':
6172
case 'submitted':
6273
return (
63-
<PendingText {...props}>{strings(`${context}.${status}`)}</PendingText>
74+
<PendingText testID={testID} {...props}>{strings(`${context}.${status}`)}</PendingText>
6475
);
6576
case 'Failed':
6677
case 'Cancelled':
6778
case 'failed':
6879
case 'cancelled':
6980
return (
70-
<FailedText {...props}>{strings(`${context}.${status}`)}</FailedText>
81+
<FailedText testID={testID} {...props}>{strings(`${context}.${status}`)}</FailedText>
7182
);
7283

7384
case FIAT_ORDER_STATES.COMPLETED:
@@ -103,6 +114,7 @@ StatusText.defaultProps = {
103114
StatusText.propTypes = {
104115
status: PropTypes.string.isRequired,
105116
context: PropTypes.string,
117+
testID: PropTypes.string,
106118
};
107119

108120
export default StatusText;

app/components/UI/Stake/components/StakingBalance/StakingBalance.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ const StakingBalanceContent = ({ asset }: StakingBalanceProps) => {
236236
<NetworkMainAssetLogo style={styles.ethLogo} />
237237
)}
238238
</BadgeWrapper>
239-
<Text style={styles.balances} variant={TextVariant.BodyLGMedium}>
239+
<Text style={styles.balances} variant={TextVariant.BodyLGMedium} testID="staked-ethereum-label">
240240
{strings('stake.staked_ethereum')}
241241
</Text>
242242
</AssetElement>

app/components/UI/Stake/components/StakingBalance/StakingBanners/UnstakeBanner/UnstakeBanner.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ const UnstakingBanner = ({
2626
variant={BannerVariant.Alert}
2727
style={style}
2828
description={
29-
<Text>{renderUnstakingTimeRemaining(timeRemaining, amountEth)}</Text>
29+
<Text testID="unstaking-banner">
30+
{renderUnstakingTimeRemaining(timeRemaining, amountEth)}
31+
</Text>
3032
}
3133
/>
3234
);

app/components/UI/Stake/components/StakingBalance/StakingButtons/StakingButtons.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ const StakingButtons = ({
7474
<View style={[styles.balanceButtonsContainer, style]}>
7575
{hasEthToUnstake && (
7676
<Button
77+
testID={'unstake-button'}
7778
style={styles.balanceActionButton}
7879
variant={ButtonVariants.Secondary}
7980
label={strings('stake.unstake')}
8081
onPress={onUnstakePress}
8182
/>
8283
)}
8384
<Button
85+
testID={'stake-more-button'}
8486
style={styles.balanceActionButton}
8587
variant={ButtonVariants.Secondary}
8688
label={

app/components/UI/Stake/components/StakingBalance/__snapshots__/StakingBalance.test.tsx.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ exports[`StakingBalance render matches snapshot 1`] = `
188188
"marginLeft": 20,
189189
}
190190
}
191+
testID="staked-ethereum-label"
191192
>
192193
Staked Ethereum
193194
</Text>
@@ -263,6 +264,7 @@ exports[`StakingBalance render matches snapshot 1`] = `
263264
"lineHeight": 22,
264265
}
265266
}
267+
testID="unstaking-banner"
266268
>
267269
Unstaking 0.0010 ETH in progress. Come back in a few days to claim it.
268270
</Text>
@@ -404,6 +406,7 @@ exports[`StakingBalance render matches snapshot 1`] = `
404406
"paddingHorizontal": 16,
405407
}
406408
}
409+
testID="unstake-button"
407410
>
408411
<Text
409412
accessibilityRole="text"
@@ -443,6 +446,7 @@ exports[`StakingBalance render matches snapshot 1`] = `
443446
"paddingHorizontal": 16,
444447
}
445448
}
449+
testID="stake-more-button"
446450
>
447451
<Text
448452
accessibilityRole="text"
@@ -653,6 +657,7 @@ exports[`StakingBalance should match the snapshot when portfolio view is enabled
653657
"marginLeft": 20,
654658
}
655659
}
660+
testID="staked-ethereum-label"
656661
>
657662
Staked Ethereum
658663
</Text>
@@ -728,6 +733,7 @@ exports[`StakingBalance should match the snapshot when portfolio view is enabled
728733
"lineHeight": 22,
729734
}
730735
}
736+
testID="unstaking-banner"
731737
>
732738
Unstaking 0.0010 ETH in progress. Come back in a few days to claim it.
733739
</Text>
@@ -869,6 +875,7 @@ exports[`StakingBalance should match the snapshot when portfolio view is enabled
869875
"paddingHorizontal": 16,
870876
}
871877
}
878+
testID="unstake-button"
872879
>
873880
<Text
874881
accessibilityRole="text"
@@ -908,6 +915,7 @@ exports[`StakingBalance should match the snapshot when portfolio view is enabled
908915
"paddingHorizontal": 16,
909916
}
910917
}
918+
testID="stake-more-button"
911919
>
912920
<Text
913921
accessibilityRole="text"

app/components/UI/TransactionElement/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ class TransactionElement extends PureComponent {
316316
chainId,
317317
isQRHardwareAccount,
318318
isLedgerAccount,
319+
i,
319320
tx: { time, status, isSmartTransaction },
320321
} = this.props;
321322
const { colors, typography } = this.context || mockTheme;
@@ -344,7 +345,7 @@ class TransactionElement extends PureComponent {
344345
<ListItem.Title numberOfLines={1} style={styles.listItemTitle}>
345346
{actionKey}
346347
</ListItem.Title>
347-
<StatusText status={status} style={styles.listItemStatus} />
348+
<StatusText testID={`transaction-status-${i}`} status={status} style={styles.listItemStatus} />
348349
</ListItem.Body>
349350
{Boolean(value) && (
350351
<ListItem.Amounts>

bitrise.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ stages:
164164
- run_tag_smoke_ramps_android: {}
165165
- run_tag_smoke_swaps_ios: {}
166166
- run_tag_smoke_swaps_android: {}
167+
- run_tag_smoke_stake_ios: {}
168+
- run_tag_smoke_stake_android: {}
167169
- run_tag_smoke_core_ios: {}
168170
- run_tag_smoke_core_android: {}
169171
- run_tag_multichain_permissions_ios: {}
@@ -674,6 +676,22 @@ workflows:
674676
- TEST_SUITE_TAG: '.*SmokeSwaps.*'
675677
after_run:
676678
- android_e2e_test
679+
run_tag_smoke_stake_ios:
680+
envs:
681+
- TEST_SUITE_FOLDER: './e2e/specs/stake/*'
682+
- TEST_SUITE_TAG: '.*SmokeStake.*'
683+
after_run:
684+
- ios_e2e_test
685+
run_tag_smoke_stake_android:
686+
meta:
687+
bitrise.io:
688+
stack: linux-docker-android-22.04
689+
machine_type_id: elite-xl
690+
envs:
691+
- TEST_SUITE_FOLDER: './e2e/specs/stake/*'
692+
- TEST_SUITE_TAG: '.*SmokeStake.*'
693+
after_run:
694+
- android_e2e_test
677695
run_ios_api_specs:
678696
after_run:
679697
- ios_api_specs

e2e/pages/Stake/StakeConfirmView.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Gestures from '../../utils/Gestures.js';
2+
import Matchers from '../../utils/Matchers.js';
3+
import { StakeConfirmViewSelectors } from '../../selectors/Stake/StakeConfirmView.selectors.js';
4+
5+
class StakeConfirmationView {
6+
get confirmButton() {
7+
return Matchers.getElementByText(StakeConfirmViewSelectors.CONFIRM);
8+
}
9+
10+
async tapConfirmButton() {
11+
await Gestures.waitAndTap(this.confirmButton);
12+
}
13+
}
14+
15+
export default new StakeConfirmationView();

e2e/pages/Stake/StakeView.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { StakeViewSelectors } from '../../selectors/Stake/StakeView.selectors.js';
2+
3+
import Matchers from '../../utils/Matchers';
4+
import Gestures from '../../utils/Gestures';
5+
6+
class StakeView {
7+
get stakeContainer() {
8+
return Matchers.getElementByText(StakeViewSelectors.STAKE_CONTAINER);
9+
}
10+
11+
get unstakeContainer() {
12+
return Matchers.getElementByText(StakeViewSelectors.UNSTAKE_CONTAINER);
13+
}
14+
15+
get reviewButton() {
16+
return Matchers.getElementByText(StakeViewSelectors.REVIEW_BUTTON);
17+
}
18+
19+
get continueButton() {
20+
return Matchers.getElementByText(StakeViewSelectors.CONTINUE);
21+
}
22+
23+
async selectAmount(amount) {
24+
const amountButton = await Matchers.getElementByText(amount);
25+
await Gestures.waitAndTap(amountButton);
26+
}
27+
28+
async enterAmount(amount) {
29+
for (let idx = 0; idx < amount.length; idx++) {
30+
const element = Matchers.getElementByText(amount[idx]);
31+
await Gestures.waitAndTap(element);
32+
}
33+
}
34+
35+
async tapReview() {
36+
await Gestures.waitAndTap(this.reviewButton);
37+
}
38+
39+
async tapContinue() {
40+
await Gestures.waitAndTap(this.continueButton);
41+
}
42+
43+
}
44+
45+
export default new StakeView();

e2e/pages/Transactions/ActivitiesView.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import {
44
} from '../../selectors/Transactions/ActivitiesView.selectors';
55
import Matchers from '../../utils/Matchers';
66
import Gestures from '../../utils/Gestures';
7-
import { CommonSelectorsIDs } from '../../selectors/Common.selectors';
87

98
class ActivitiesView {
10-
static FIRST_ROW = 0;
11-
static SECOND_ROW = 1;
129

1310
get title() {
1411
return Matchers.getElementByText(ActivitiesViewSelectorsText.TITLE);
@@ -22,18 +19,25 @@ class ActivitiesView {
2219
return Matchers.getElementByText(ActivitiesViewSelectorsText.CONFIRM_TEXT);
2320
}
2421

25-
get firstTransactionStatus() {
26-
return Matchers.getElementByID(
27-
CommonSelectorsIDs.TRANSACTION_STATUS,
28-
ActivitiesView.FIRST_ROW,
29-
);
22+
get stakeDepositedLabel() {
23+
return Matchers.getElementByText(ActivitiesViewSelectorsText.STAKE_DEPOSIT);
3024
}
3125

32-
get secondTransactionStatus() {
33-
return Matchers.getElementByID(
34-
CommonSelectorsIDs.TRANSACTION_STATUS,
35-
ActivitiesView.SECOND_ROW,
36-
);
26+
get stakeMoreDepositedLabel() {
27+
return Matchers.getElementByText(ActivitiesViewSelectorsText.STAKE_DEPOSIT, 0);
28+
}
29+
30+
get unstakeLabel() {
31+
return Matchers.getElementByText(ActivitiesViewSelectorsText.UNSTAKE);
32+
}
33+
34+
get stackingClaimLabel() {
35+
return Matchers.getElementByText(ActivitiesViewSelectorsText.STAKING_CLAIM);
36+
}
37+
38+
39+
transactionStatus(row) {
40+
return Matchers.getElementByID(`transaction-status-${row}`);
3741
}
3842

3943
generateSwapActivityLabel(sourceToken, destinationToken) {

0 commit comments

Comments
 (0)