Skip to content

Commit

Permalink
test: E2E to reveal SRP on error boundary screen (#12805)
Browse files Browse the repository at this point in the history
<!--
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**

To catch any regressions in the crash screen’s reveal SRP flow, we
should add an end-to-end (e2e) test. Since revealing the Secret Recovery
Phrase is the user’s last chance to view and securely save it, this test
will check that each step in the flow works smoothly: from entering your
password to viewing your SRP.


```
Scenario: A user can reveal their SRP while on the crash screen
Given I encounter the crash screen
When I tap linked text to reveal my SRP
And I enter an invalid password
Then I should see the appropriate error
When I enter the correct password
Then I can see my SRP
```



## **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.
  • Loading branch information
cortisiko authored Dec 20, 2024
1 parent 4b09d48 commit 9e11cf6
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 4 deletions.
11 changes: 9 additions & 2 deletions app/components/Views/ErrorBoundary/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
} from '../../../components/hooks/useMetrics';
import AppConstants from '../../../core/AppConstants';
import { useSelector } from 'react-redux';

import { isTest } from '../../../util/test/utils';
// eslint-disable-next-line import/no-commonjs
const WarningIcon = require('./warning-icon.png');

Expand Down Expand Up @@ -246,7 +246,6 @@ export const Fallback = (props) => {
captureSentryFeedback({ sentryId: props.sentryId, comments: feedback });
Alert.alert(strings('error_screen.bug_report_thanks'));
};

return (
<View style={styles.container}>
<View style={styles.header}>
Expand All @@ -270,6 +269,14 @@ export const Fallback = (props) => {
</Text>
}
/>

{isTest && (
<Text style={styles.text}>
<Text onPress={props.showExportSeedphrase} style={styles.link}>
{strings('error_screen.save_seedphrase_2')}
</Text>
</Text>
)}
<View style={styles.errorContentWrapper}>
<Text style={styles.errorBoxTitle}>
{strings('error_screen.error_message')}
Expand Down
22 changes: 22 additions & 0 deletions app/components/Views/Login/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,28 @@ exports[`Login should render correctly 1`] = `
</Text>
</View>
</View>
<Text
style={
{
"color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 14,
"fontWeight": "400",
"lineHeight": 20,
}
}
>
<Text
onPress={[Function]}
style={
{
"color": "#0376c9",
}
}
>
save your Secret Recovery Phrase
</Text>
</Text>
<View
style={
{
Expand Down
10 changes: 9 additions & 1 deletion e2e/pages/Browser/TestDApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ class TestDApp {
TestDappSelectorsWebIDs.APPROVE_ERC_20_TOKENS_BUTTON_ID,
);
}
get invalidSignature() {
return Matchers.getElementByWebID(
BrowserViewSelectorsIDs.BROWSER_WEBVIEW_ID,
'signInvalidType',
);
}

get ApproveERC721TokenButton() {
return Matchers.getElementByWebID(
Expand Down Expand Up @@ -144,7 +150,9 @@ class TestDApp {
async tapApproveERC721TokenButton() {
await this.tapButton(this.ApproveERC721TokenButton);
}

async tapInvalidSigButton() {
await this.tapButton(this.invalidSignature);
}
async tapIncreaseAllowanceButton() {
await this.tapButton(this.increaseAllowanceButton);
}
Expand Down
21 changes: 21 additions & 0 deletions e2e/pages/ErrorBoundaryView/ErrorBoundaryView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Matchers from '../../utils/Matchers';
import Gestures from '../../utils/Gestures';
import { ErrorBoundarySelectorsText } from '../../selectors/ErrorBoundary/ErrorBoundaryView.selectors';

class ErrorBoundaryView {
get title() {
return Matchers.getElementByText(ErrorBoundarySelectorsText.TITLE);
}

get srpLinkText() {
return Matchers.getElementByText(
ErrorBoundarySelectorsText.SAVE_YOUR_SRP_TEXT,
);
}

async tapSRPLinkText() {
await Gestures.waitAndTap(this.srpLinkText);
}
}

export default new ErrorBoundaryView();
12 changes: 11 additions & 1 deletion e2e/pages/Network/NetworkApprovalBottomSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@ import Gestures from '../../utils/Gestures';

class NetworkApprovalBottomSheet {
get container() {
return Matchers.getElementByID(NetworkApprovalBottomSheetSelectorsIDs.CONTAINER);
return Matchers.getElementByID(
NetworkApprovalBottomSheetSelectorsIDs.CONTAINER,
);
}

get approvedButton() {
return Matchers.getElementByID(
NetworkApprovalBottomSheetSelectorsIDs.APPROVE_BUTTON,
);
}
get cancelButton() {
return Matchers.getElementByID(
NetworkApprovalBottomSheetSelectorsIDs.CANCEL_BUTTON,
);
}

get displayName() {
return Matchers.getElementByID(
Expand All @@ -22,6 +29,9 @@ class NetworkApprovalBottomSheet {
async tapApproveButton() {
await Gestures.tap(this.approvedButton);
}
async tapCancelButton() {
await Gestures.tap(this.cancelButton);
}
}

export default new NetworkApprovalBottomSheet();
9 changes: 9 additions & 0 deletions e2e/selectors/ErrorBoundary/ErrorBoundaryView.selectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import enContent from '../../../locales/languages/en.json';

export const ErrorBoundarySelectorsIDs = {
CONTAINER: 'error-boundary-container-id',
};
export const ErrorBoundarySelectorsText = {
SAVE_YOUR_SRP_TEXT: enContent.error_screen.save_seedphrase_2,
TITLE: enContent.error_screen.title,
};
56 changes: 56 additions & 0 deletions e2e/specs/accounts/error-boundary-srp-backup.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';
import Browser from '../../pages/Browser/BrowserView';
import TabBarComponent from '../../pages/wallet/TabBarComponent';
import { loginToApp } from '../../viewHelper';
import TestDApp from '../../pages/Browser/TestDApp';
import FixtureBuilder from '../../fixtures/fixture-builder';
import {
withFixtures,
defaultGanacheOptions,
} from '../../fixtures/fixture-helper';
import { SmokeAccounts } from '../../tags';
import TestHelpers from '../../helpers';
import Assertions from '../../utils/Assertions';
import RevealSecretRecoveryPhrase from '../../pages/Settings/SecurityAndPrivacy/RevealSecretRecoveryPhrase';
import ErrorBoundaryView from '../../pages/ErrorBoundaryView/ErrorBoundaryView';
const PASSWORD = '123123123';

describe(SmokeAccounts('Error Boundary Screen'), () => {
beforeAll(async () => {
jest.setTimeout(2500000);
await TestHelpers.reverseServerPort();
});

it('should trigger error boundary screen to reveal SRP', async () => {
await withFixtures(
{
dapp: true,
fixture: new FixtureBuilder()
.withGanacheNetwork()
.withPermissionControllerConnectedToTestDapp()
.build(),
restartDevice: true,
ganacheOptions: defaultGanacheOptions,
},
async () => {
await loginToApp();

await TabBarComponent.tapBrowser();
await Browser.navigateToTestDApp();

await TestDApp.tapInvalidSigButton();
await Assertions.checkIfVisible(ErrorBoundaryView.title);
await ErrorBoundaryView.tapSRPLinkText();

await RevealSecretRecoveryPhrase.enterPasswordToRevealSecretCredential(
PASSWORD,
);
// If the following step fails, ensure you are using a test build with tap and hold to reveal animation disabled
await RevealSecretRecoveryPhrase.tapToReveal();
await Assertions.checkIfVisible(RevealSecretRecoveryPhrase.container);

await Assertions.checkIfTextIsDisplayed(defaultGanacheOptions.mnemonic);
},
);
});
});

0 comments on commit 9e11cf6

Please sign in to comment.