Skip to content

Commit c3b271a

Browse files
test: add file download E2E tests with local HTML fixtures (#28634)
## **Description** Migrates the two file download E2E tests from the quarantined `browser-tests.failing.ts` into a new `browser-download.spec.ts` file. Replaces live external URL navigation (`tyschenko.github.io`) with local HTML fixtures served by DappServer, eliminating external network dependencies and improving test reliability. Part of the effort to increase API mocking coverage for E2E tests ([MMQA-1368](https://consensyssoftware.atlassian.net/browse/MMQA-1368)). ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [MMQA-1705](https://consensyssoftware.atlassian.net/browse/MMQA-1705) ## **Manual testing steps** ```gherkin Feature: Browser File Download Scenario: user downloads a blob file from a local fixture page Given the app is launched and user is logged in And the browser view is open When user navigates to the local blob download fixture page And user taps the Download button And user confirms the download in the tapjacking dialog Then the download success state is displayed Scenario: user downloads a base64 file from a local fixture page Given the app is launched and user is logged in And the browser view is open When user navigates to the local base64 download fixture page And user taps the Download button And user confirms the download in the tapjacking dialog Then the download success state is displayed ``` ## **Screenshots/Recordings** ### **Before** N/A — tests were quarantined in `browser-tests.failing.ts` due to reliance on external URLs. ### **After** Both tests passing locally on iOS simulator: ``` PASS tests/smoke/wallet/browser/browser-download.spec.ts (222.23 s) SmokeWalletPlatform: Browser File Download ✓ downloads a blob file (121368 ms) ✓ downloads a base64 file (92885 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total ``` ## **Pre-merge author checklist** - [x] 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). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] 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. [MMQA-1368]: https://consensyssoftware.atlassian.net/browse/MMQA-1368?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [MMQA-1705]: https://consensyssoftware.atlassian.net/browse/MMQA-1705?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk because changes are limited to E2E smoke tests and static HTML/text fixtures, with no production code paths affected. > > **Overview** > Adds a new smoke spec `browser-download.spec.ts` that exercises in-app browser file downloads for both *blob* and *base64 data URL* flows. > > Replaces reliance on external download pages by introducing local DappServer-served fixtures (`tests/fixtures/download/*`) that fetch a bundled `File.txt` and trigger downloads via `URL.createObjectURL` or `FileReader.readAsDataURL`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9ca245f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 49357e1 commit c3b271a

4 files changed

Lines changed: 122 additions & 0 deletions

File tree

tests/fixtures/download/File.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a test file for download E2E tests.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Download Base64 File</title>
7+
</head>
8+
<body>
9+
<h1>Download File document</h1>
10+
<button id="download_button">Download</button>
11+
<a id="hidden_download_link" style="display:none;"></a>
12+
13+
<script>
14+
document.getElementById("download_button").addEventListener("click", async () => {
15+
try {
16+
const response = await fetch("File.txt");
17+
const blob = await response.blob();
18+
const reader = new FileReader();
19+
reader.onloadend = () => {
20+
const base64DataUrl = reader.result;
21+
const link = document.getElementById("hidden_download_link");
22+
link.href = base64DataUrl;
23+
link.download = "file.txt";
24+
link.click();
25+
};
26+
reader.readAsDataURL(blob);
27+
} catch (error) {
28+
console.error("Download failed:", error);
29+
alert("Failed to download file.");
30+
}
31+
});
32+
</script>
33+
</body>
34+
</html>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Download Blob file</title>
7+
</head>
8+
<body>
9+
<h1>Download File document</h1>
10+
<button id="download_button">Download</button>
11+
12+
<script>
13+
document.getElementById("download_button").addEventListener("click", async () => {
14+
try {
15+
const response = await fetch("File.txt");
16+
const blob = await response.blob();
17+
const url = URL.createObjectURL(blob);
18+
const a = document.createElement("a");
19+
a.href = url;
20+
a.download = "file.txt";
21+
document.body.appendChild(a);
22+
a.click();
23+
document.body.removeChild(a);
24+
URL.revokeObjectURL(url);
25+
} catch (error) {
26+
console.error("Download failed:", error);
27+
alert("Failed to download file.");
28+
}
29+
});
30+
</script>
31+
</body>
32+
</html>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// eslint-disable-next-line import-x/no-nodejs-modules
2+
import path from 'path';
3+
import { SmokeWalletPlatform } from '../../../tags.js';
4+
import { loginToApp } from '../../../flows/wallet.flow';
5+
import { navigateToBrowserView } from '../../../flows/browser.flow';
6+
import FixtureBuilder from '../../../framework/fixtures/FixtureBuilder';
7+
import { withFixtures } from '../../../framework/fixtures/FixtureHelper';
8+
import { getDappUrl } from '../../../framework/fixtures/FixtureUtils';
9+
import { DappVariants } from '../../../framework/Constants';
10+
import Browser from '../../../page-objects/Browser/BrowserView';
11+
import DownloadFileWebsite from '../../../page-objects/Browser/ExternalWebsites/DownloadFileWebsite';
12+
import DownloadFile from '../../../page-objects/Browser/DownloadFile';
13+
14+
const DOWNLOAD_FIXTURES_PATH = path.resolve(
15+
__dirname,
16+
'../../../fixtures/download',
17+
);
18+
19+
async function testDownloadFile(filename: string) {
20+
await withFixtures(
21+
{
22+
dapps: [
23+
{
24+
dappVariant: DappVariants.TEST_DAPP,
25+
dappPath: DOWNLOAD_FIXTURES_PATH,
26+
},
27+
],
28+
fixture: new FixtureBuilder().build(),
29+
restartDevice: true,
30+
},
31+
async () => {
32+
await loginToApp();
33+
await navigateToBrowserView();
34+
await Browser.tapUrlInputBox();
35+
await Browser.navigateToURL(`${getDappUrl(0)}/${filename}`);
36+
await DownloadFileWebsite.tapDownloadFileButton();
37+
await DownloadFile.verifyTapjackingAndClickDownloadButton();
38+
await DownloadFile.verifySuccessStateVisible();
39+
},
40+
);
41+
}
42+
43+
describe(SmokeWalletPlatform('Browser File Download'), () => {
44+
beforeEach(() => {
45+
jest.setTimeout(150000);
46+
});
47+
48+
it('downloads a blob file', async () => {
49+
await testDownloadFile('download_blob_file.html');
50+
});
51+
52+
it('downloads a base64 file', async () => {
53+
await testDownloadFile('download_base64_file.html');
54+
});
55+
});

0 commit comments

Comments
 (0)