diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3892a56806..b112e7e1e8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -115,7 +115,7 @@ jobs:
- name: Run e2e (Chrome)
uses: nick-fields/retry@v2
with:
- timeout_minutes: 16
+ timeout_minutes: 18
max_attempts: 3
command: |
export BROWSER=chrome
@@ -173,7 +173,7 @@ jobs:
# - name: Run e2e (Brave)
# uses: nick-fields/retry@v2
# with:
- # timeout_minutes: 16
+ # timeout_minutes: 18
# max_attempts: 3
# command: |
# export BROWSER=brave
diff --git a/e2e/helpers.ts b/e2e/helpers.ts
index 4787655b06..e8c12dcea9 100644
--- a/e2e/helpers.ts
+++ b/e2e/helpers.ts
@@ -66,6 +66,28 @@ export async function getExtensionIdByName(driver, extensionName) {
`);
}
+export function shortenAddress(address) {
+ // if address is 42 in length and starts with 0x, then shorten it
+ // otherwise return the base value. this is so it doesn't break incase an ens, etc is input
+ return address.substring(0, 2) === '0x' && address.length === 42
+ ? `${address.substring(0, 6)}...${address.substring(38, 42)}`
+ : address;
+}
+
+export async function switchWallet(address, rootURL, driver) {
+ // find shortened address, go to popup, find header, click, find wallet you want to switch to and click
+ const shortenedAddress = shortenAddress(address);
+
+ await goToPopup(driver, rootURL, '#/home');
+ await findElementByIdAndClick({
+ id: 'header-account-name-shuffle',
+ driver,
+ });
+
+ await findElementByTextAndClick(driver, shortenedAddress);
+ await delayTime('short');
+}
+
export async function getOnchainBalance(addy, contract) {
const provider = ethers.getDefaultProvider('http://127.0.0.1:8545');
const testContract = new ethers.Contract(contract, erc20ABI, provider);
@@ -94,6 +116,13 @@ export async function findElementByText(driver, text) {
return driver.findElement(By.xpath("//*[contains(text(),'" + text + "')]"));
}
+export async function findElementByTextAndClick(driver, text) {
+ const element = await driver.findElement(
+ By.xpath("//*[contains(text(),'" + text + "')]"),
+ );
+ await waitAndClick(element, driver);
+}
+
export async function waitAndClick(element, driver) {
await delay(200);
await driver.wait(until.elementIsVisible(element), waitUntilTime);
@@ -130,6 +159,12 @@ export async function findElementByTestIdAndClick({ id, driver }) {
await waitAndClick(element, driver);
}
+export async function findElementByIdAndClick({ id, driver }) {
+ await delay(200);
+ const element = await findElementById({ id, driver });
+ await waitAndClick(element, driver);
+}
+
export async function typeOnTextInput({ id, text, driver }) {
const element = await findElementByTestId({ id, driver });
await element.sendKeys(text);
diff --git a/e2e/parallel/importWalletFlow.test.ts b/e2e/parallel/importWalletFlow.test.ts
index e717637f25..11ce691298 100644
--- a/e2e/parallel/importWalletFlow.test.ts
+++ b/e2e/parallel/importWalletFlow.test.ts
@@ -8,12 +8,12 @@ import {
findElementByTestIdAndClick,
findElementByText,
getExtensionIdByName,
+ getTextFromText,
goToPopup,
goToWelcome,
initDriverWithOptions,
- querySelector,
+ shortenAddress,
typeOnTextInput,
- waitAndClick,
} from '../helpers';
let rootURL = 'chrome-extension://';
@@ -21,6 +21,7 @@ let driver: WebDriver;
const browser = process.env.BROWSER || 'chrome';
const os = process.env.OS || 'mac';
+const wallet = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
describe('Import wallet flow', () => {
beforeAll(async () => {
@@ -71,31 +72,10 @@ describe('Import wallet flow', () => {
await findElementByTestIdAndClick({ id: 'set-password-button', driver });
await delayTime('long');
await findElementByText(driver, 'Your wallets ready');
- });
-
- it('should be able to test the sandbox for the popup', async () => {
- await goToPopup(driver, rootURL, '#/home');
- await findElementByTestIdAndClick({ id: 'home-page-header-right', driver });
- await findElementByTestIdAndClick({ id: 'settings-link', driver });
- const btn = await querySelector(
- driver,
- '[data-testid="test-sandbox-popup"]',
- );
- await waitAndClick(btn, driver);
- const text = await driver.switchTo().alert().getText();
- expect(text).toBe('Popup sandboxed!');
- await driver.switchTo().alert().accept();
- });
- it('should be able to test the sandbox for the background', async () => {
- const btn = await querySelector(
- driver,
- '[data-testid="test-sandbox-background"]',
- );
- await waitAndClick(btn, driver);
- await delayTime('long');
- const text = await driver.switchTo().alert().getText();
- expect(text).toBe('Background sandboxed!');
- await driver.switchTo().alert().accept();
+ goToPopup(driver, rootURL);
+ await delayTime('short');
+ const account = await getTextFromText({ id: 'account-name', driver });
+ expect(account).toBe(await shortenAddress(wallet));
});
});
diff --git a/e2e/parallel/importWalletFlowPkey.test.ts b/e2e/parallel/importWalletFlowPkey.test.ts
new file mode 100644
index 0000000000..a4d2217af4
--- /dev/null
+++ b/e2e/parallel/importWalletFlowPkey.test.ts
@@ -0,0 +1,78 @@
+import 'chromedriver';
+import 'geckodriver';
+import { WebDriver } from 'selenium-webdriver';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+
+import {
+ delayTime,
+ findElementByTestIdAndClick,
+ findElementByText,
+ getExtensionIdByName,
+ getTextFromText,
+ goToPopup,
+ goToWelcome,
+ initDriverWithOptions,
+ shortenAddress,
+ typeOnTextInput,
+} from '../helpers';
+
+let rootURL = 'chrome-extension://';
+let driver: WebDriver;
+
+const browser = process.env.BROWSER || 'chrome';
+const os = process.env.OS || 'mac';
+const wallet = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
+
+describe('Import wallet flow', () => {
+ beforeAll(async () => {
+ driver = await initDriverWithOptions({
+ browser,
+ os,
+ });
+ const extensionId = await getExtensionIdByName(driver, 'Rainbow');
+ if (!extensionId) throw new Error('Extension not found');
+ rootURL += extensionId;
+ });
+
+ afterAll(async () => driver.quit());
+
+ // Import a wallet
+ it('should be able import a wallet via pkey', async () => {
+ // Start from welcome screen
+ await goToWelcome(driver, rootURL);
+ await findElementByTestIdAndClick({
+ id: 'import-wallet-button',
+ driver,
+ });
+ await findElementByTestIdAndClick({
+ id: 'import-wallet-option',
+ driver,
+ });
+
+ await typeOnTextInput({
+ id: 'secret-textarea',
+ driver,
+ text: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
+ });
+
+ await findElementByTestIdAndClick({
+ id: 'import-wallets-button',
+ driver,
+ });
+
+ await typeOnTextInput({ id: 'password-input', driver, text: 'test1234' });
+ await typeOnTextInput({
+ id: 'confirm-password-input',
+ driver,
+ text: 'test1234',
+ });
+ await findElementByTestIdAndClick({ id: 'set-password-button', driver });
+ await delayTime('long');
+ await findElementByText(driver, 'Your wallets ready');
+
+ goToPopup(driver, rootURL);
+ await delayTime('short');
+ const account = await getTextFromText({ id: 'account-name', driver });
+ expect(account).toBe(await shortenAddress(wallet));
+ });
+});
diff --git a/e2e/parallel/newWalletFlow.test.ts b/e2e/parallel/newWalletFlow.test.ts
index fa43e7bf51..ab3db11e6e 100644
--- a/e2e/parallel/newWalletFlow.test.ts
+++ b/e2e/parallel/newWalletFlow.test.ts
@@ -14,6 +14,7 @@ import {
initDriverWithOptions,
querySelector,
typeOnTextInput,
+ waitAndClick,
} from '../helpers';
let rootURL = 'chrome-extension://';
@@ -96,4 +97,44 @@ describe('New wallet flow', () => {
const actual = await label.getText();
expect(actual.substr(0, 2) === '0x' && actual.length === 13).toEqual(true);
});
+
+ it('should be able to lock and unlock the extension', async () => {
+ await goToPopup(driver, rootURL, '#/home');
+ // Lock
+ await findElementByTestIdAndClick({
+ id: 'home-page-header-right',
+ driver,
+ });
+ await findElementByTestIdAndClick({ id: 'lock', driver });
+
+ // Unlock
+ await typeOnTextInput({ id: 'password-input', driver, text: 'test1234' });
+ await findElementByTestIdAndClick({ id: 'unlock-button', driver });
+ });
+
+ it('should be able to test the sandbox for the popup', async () => {
+ await goToPopup(driver, rootURL, '#/home');
+ await findElementByTestIdAndClick({ id: 'home-page-header-right', driver });
+ await findElementByTestIdAndClick({ id: 'settings-link', driver });
+ const btn = await querySelector(
+ driver,
+ '[data-testid="test-sandbox-popup"]',
+ );
+ await waitAndClick(btn, driver);
+ const text = await driver.switchTo().alert().getText();
+ expect(text).toBe('Popup sandboxed!');
+ await driver.switchTo().alert().accept();
+ });
+
+ it('should be able to test the sandbox for the background', async () => {
+ const btn = await querySelector(
+ driver,
+ '[data-testid="test-sandbox-background"]',
+ );
+ await waitAndClick(btn, driver);
+ await delayTime('long');
+ const text = await driver.switchTo().alert().getText();
+ expect(text).toBe('Background sandboxed!');
+ await driver.switchTo().alert().accept();
+ });
});
diff --git a/e2e/parallel/vitest.config.ts b/e2e/parallel/vitest.config.ts
new file mode 100644
index 0000000000..fa6db1a695
--- /dev/null
+++ b/e2e/parallel/vitest.config.ts
@@ -0,0 +1,13 @@
+import { mergeConfig } from 'vite';
+import { defineConfig } from 'vitest/config';
+
+import viteConfig from '../vitest.config';
+
+export default mergeConfig(
+ viteConfig,
+ defineConfig({
+ test: {
+ threads: false,
+ },
+ }),
+);
diff --git a/e2e/parallel/watchWalletFlow.test.ts b/e2e/parallel/watchWalletFlow.test.ts
index 2f6872a220..39437060e4 100644
--- a/e2e/parallel/watchWalletFlow.test.ts
+++ b/e2e/parallel/watchWalletFlow.test.ts
@@ -5,13 +5,17 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import {
delayTime,
+ findElementByIdAndClick,
findElementByTestIdAndClick,
findElementByText,
getExtensionIdByName,
+ getTextFromText,
goToPopup,
goToWelcome,
initDriverWithOptions,
querySelector,
+ shortenAddress,
+ switchWallet,
typeOnTextInput,
} from '../helpers';
@@ -20,8 +24,14 @@ let driver: WebDriver;
const browser = process.env.BROWSER || 'chrome';
const os = process.env.OS || 'mac';
+const watchedWallet = 'djweth.eth';
+const watchedWalletTwo = 'brdy.eth';
+const seedWallet = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
+const pkWallet = '0x38eDa688Cd8DFC6FeE8016c85803a584A0564dDC';
+const privateKey =
+ '0xaeb5635a53c33d3c0d92c32881d7613ee9fe18be77772054f5e025bc4fa8c851';
-describe('Watch wallet flow', () => {
+describe('Watch wallet then add more and switch between them', () => {
beforeAll(async () => {
driver = await initDriverWithOptions({
browser,
@@ -50,7 +60,7 @@ describe('Watch wallet flow', () => {
await typeOnTextInput({
id: 'secret-textarea',
driver,
- text: 'djweth.eth',
+ text: watchedWallet,
});
await findElementByTestIdAndClick({
@@ -68,7 +78,7 @@ describe('Watch wallet flow', () => {
await findElementByText(driver, 'Your wallets ready');
});
- it('should display account name', async () => {
+ it('should display watched account name', async () => {
await goToPopup(driver, rootURL);
const label = await querySelector(
driver,
@@ -76,20 +86,132 @@ describe('Watch wallet flow', () => {
);
const actual = await label.getText();
- const expected = ['0x70c1...43C4', 'djweth.eth'];
+ const expected = ['0x70c1...43C4', watchedWallet];
expect(expected.includes(actual)).toEqual(true);
});
- it('should be able to lock and unlock the extension', async () => {
- // Lock
+ it('should be able to add a new wallet via pkey', async () => {
+ await goToPopup(driver, rootURL, '#/home');
+ await findElementByIdAndClick({
+ id: 'header-account-name-shuffle',
+ driver,
+ });
+ await findElementByTestIdAndClick({ id: 'add-wallet-button', driver });
await findElementByTestIdAndClick({
- id: 'home-page-header-right',
+ id: 'import-wallets-button',
driver,
});
- await findElementByTestIdAndClick({ id: 'lock', driver });
- // Unlock
- await typeOnTextInput({ id: 'password-input', driver, text: 'test1234' });
- await findElementByTestIdAndClick({ id: 'unlock-button', driver });
+ await typeOnTextInput({
+ id: 'secret-textarea',
+ driver,
+ text: privateKey,
+ });
+
+ await findElementByTestIdAndClick({
+ id: 'import-wallets-button',
+ driver,
+ });
+ await delayTime('medium');
+
+ it('should display pk account wallet name', async () => {
+ const account = await getTextFromText({ id: 'account-name', driver });
+ expect(account).toBe(await shortenAddress(pkWallet));
+ });
+ });
+
+ it('should be able to add a new wallet via watch', async () => {
+ await goToPopup(driver, rootURL, '#/home');
+ await findElementByIdAndClick({
+ id: 'header-account-name-shuffle',
+ driver,
+ });
+ await findElementByTestIdAndClick({ id: 'add-wallet-button', driver });
+ await findElementByTestIdAndClick({
+ id: 'watch-wallets-button',
+ driver,
+ });
+
+ await typeOnTextInput({
+ id: 'secret-textarea',
+ driver,
+ text: watchedWalletTwo,
+ });
+
+ await findElementByTestIdAndClick({
+ id: 'watch-wallets-button',
+ driver,
+ });
+ await delayTime('medium');
+
+ it('should display watched account name', async () => {
+ await goToPopup(driver, rootURL);
+ const label = await querySelector(
+ driver,
+ '[data-testid="header"] [data-testid="account-name"]',
+ );
+
+ const actual = await label.getText();
+ const expected = ['0x089b...be9E', watchedWalletTwo];
+ expect(expected.includes(actual)).toEqual(true);
+ });
+ });
+
+ it('should be able to add a new wallet via seed', async () => {
+ await goToPopup(driver, rootURL, '#/home');
+ await findElementByIdAndClick({
+ id: 'header-account-name-shuffle',
+ driver,
+ });
+ await findElementByTestIdAndClick({ id: 'add-wallet-button', driver });
+ await findElementByTestIdAndClick({
+ id: 'import-wallets-button',
+ driver,
+ });
+
+ await typeOnTextInput({
+ id: 'secret-textarea',
+ driver,
+ text: 'test test test test test test test test test test test junk',
+ });
+
+ await findElementByTestIdAndClick({
+ id: 'import-wallets-button',
+ driver,
+ });
+ await findElementByTestIdAndClick({
+ id: 'add-wallets-button',
+ driver,
+ });
+ await delayTime('medium');
+
+ it('should display seed account name', async () => {
+ const account = await getTextFromText({ id: 'account-name', driver });
+ expect(account).toBe(await shortenAddress(pkWallet));
+ });
+ });
+
+ it('should be able to switch to the watched wallet', async () => {
+ await switchWallet(watchedWallet, rootURL, driver);
+ const wallet = await getTextFromText({ id: 'account-name', driver });
+ expect(wallet).toBe(await shortenAddress(watchedWallet));
+ });
+
+ it('should be able to switch to the pk wallet', async () => {
+ await switchWallet(pkWallet, rootURL, driver);
+ const wallet = await getTextFromText({ id: 'account-name', driver });
+ expect(wallet).toBe(await shortenAddress(pkWallet));
+ });
+
+ it('should be able to switch to the seed wallet', async () => {
+ await switchWallet(seedWallet, rootURL, driver);
+ const wallet = await getTextFromText({ id: 'account-name', driver });
+ expect(wallet).toBe(await shortenAddress(seedWallet));
+ });
+
+ it('should be able to switch to the second watched wallet', async () => {
+ await switchWallet(watchedWalletTwo, rootURL, driver);
+ const wallet = await getTextFromText({ id: 'account-name', driver });
+ expect(wallet).toBe(await shortenAddress(watchedWalletTwo));
});
});
diff --git a/e2e/serial/5_dappInteractionFlow.test.ts b/e2e/serial/5_dappInteractionFlow.test.ts
index e8f007893f..b76adc376b 100644
--- a/e2e/serial/5_dappInteractionFlow.test.ts
+++ b/e2e/serial/5_dappInteractionFlow.test.ts
@@ -9,6 +9,7 @@ import {
findElementByTestId,
findElementByTestIdAndClick,
findElementByText,
+ findElementByTextAndClick,
getAllWindowHandles,
getExtensionIdByName,
getOnchainBalance,
@@ -17,6 +18,7 @@ import {
goToPopup,
goToWelcome,
initDriverWithOptions,
+ shortenAddress,
transactionStatus,
typeOnTextInput,
waitAndClick,
@@ -30,7 +32,7 @@ const os = process.env.OS || 'mac';
const walletAddress = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
const recipientWalletAddress = '0x2f318C334780961FB129D2a6c30D0763d9a5C970';
// eslint-disable-next-line prettier/prettier
-const shortenedAddress = `${walletAddress.substring(0, 6)}...${walletAddress.substring(38, 42)}`;
+const shortenedAddress = await shortenAddress(walletAddress);
describe('App interactions flow', () => {
beforeAll(async () => {
@@ -253,11 +255,7 @@ describe('App interactions flow', () => {
driver,
});
- const connection = await findElementByText(
- driver,
- 'bx-e2e-dapp.vercel.app',
- );
- await waitAndClick(connection, driver);
+ await findElementByTextAndClick(driver, 'bx-e2e-dapp.vercel.app');
await findElementByTestIdAndClick({ id: 'switch-network-item-5', driver });
await driver.get('https://bx-e2e-dapp.vercel.app/');
diff --git a/src/entries/popup/pages/walletSwitcher/addWallet.tsx b/src/entries/popup/pages/walletSwitcher/addWallet.tsx
index 27637681ff..1bf4e5cf8f 100644
--- a/src/entries/popup/pages/walletSwitcher/addWallet.tsx
+++ b/src/entries/popup/pages/walletSwitcher/addWallet.tsx
@@ -51,6 +51,7 @@ const AddWallet = () => {
subtitle={i18n.t('add_wallet.create_wallet_description')}
symbolColor="pink"
symbol="plus.circle"
+ testId={'create-wallets-button'}
/>
{
subtitle={i18n.t('add_wallet.import_wallet_description')}
symbolColor="purple"
symbol="lock.rotation"
+ testId={'import-wallets-button'}
/>
{
subtitle={i18n.t('add_wallet.hardware_wallet_description')}
symbolColor="blue"
symbol="doc.text.magnifyingglass"
+ testId={'hardware-wallets-button'}
/>
{
subtitle={i18n.t('add_wallet.watch_address_description')}
symbolColor="green"
symbol="magnifyingglass.circle"
+ testId={'watch-wallets-button'}
/>
diff --git a/src/entries/popup/pages/walletSwitcher/index.tsx b/src/entries/popup/pages/walletSwitcher/index.tsx
index 7638885991..2666d563ce 100644
--- a/src/entries/popup/pages/walletSwitcher/index.tsx
+++ b/src/entries/popup/pages/walletSwitcher/index.tsx
@@ -426,6 +426,7 @@ export function WalletSwitcher() {
height="32px"
width="full"
borderRadius="9px"
+ testId={'add-wallet-button'}
>
{i18n.t('wallet_switcher.add_another_wallet')}
diff --git a/src/entries/popup/pages/wallets/index.tsx b/src/entries/popup/pages/wallets/index.tsx
index b0d03e9da8..308f0cae66 100644
--- a/src/entries/popup/pages/wallets/index.tsx
+++ b/src/entries/popup/pages/wallets/index.tsx
@@ -575,6 +575,7 @@ export function Wallets() {
gap="24px"
padding="20px"
style={{ overflow: 'auto' }}
+ testId={'wallet-address-or-ens'}
>
{isUnlocked ? (