Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use JSON onboarding in e2e tests of transactions #3559

Merged
merged 12 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 16 additions & 22 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,14 @@ jobs:
|| contains(github.head_ref, 'e2e')
|| needs.detect-if-flag-changed.outputs.path-filter == 'true'
run: xvfb-run npx playwright test --grep @expensive
# Upload of Playwright artifacts commented out until we change the method
# of account import in the tests from seed to JSON (we don't want to leak
# the seed phrase in logs/recordings from tests).
# - uses: actions/upload-artifact@v3
# if: failure()
# with:
# name: debug-output
# path: |
# test-results/
# #videos/
# retention-days: 30
- uses: actions/upload-artifact@v3
if: failure()
with:
name: debug-output
path: |
test-results/
#videos/
retention-days: 30
e2e-tests-fork:
if: |
github.ref == 'refs/heads/main'
Expand Down Expand Up @@ -247,14 +244,11 @@ jobs:
RECOVERY_PHRASE: ${{ secrets.TEST_WALLET_RECOVERY_PHRASE }}
USE_MAINNET_FORK: true
run: xvfb-run npx playwright test
# Upload of Playwright artifacts commented out until we change the method
# of account import in the tests from seed to JSON (we don't want to leak
# the seed phrase in logs/recordings from tests).
# - uses: actions/upload-artifact@v3
# if: failure()
# with:
# name: fork-debug-output
# path: |
# test-results/
# #videos/
# retention-days: 30
- uses: actions/upload-artifact@v3
if: failure()
with:
name: fork-debug-output
path: |
test-results/
#videos/
retention-days: 30
56 changes: 41 additions & 15 deletions e2e-tests/fork-based/transactions.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
import fs from "fs"
import { test, expect } from "../utils"

test.describe("Transactions", () => {
test.beforeAll(async () => {
/**
* Create a JSON file with an encoded private key based on the file
* content passed from an environment variable. The further steps of
* the tests assume that the file encodes the pk of the `testertesting.eth`
* account. The JSON file can be generated using a script
* `scripts/key-generation/export-key-as-json.js`.
*/
const jsonBody = process.env.JSON_BODY
if (jsonBody) {
fs.writeFileSync("./e2e-tests/utils/JSON.json", jsonBody)
} else {
throw new Error("JSON_BODY environment variable is not defined.")
}
})

test("User can send base asset", async ({
page: popup,
walletPageHelper,
transactionsHelper,
}) => {
await test.step("Import account", async () => {
/**
* Onboard using walletPageHelper
* Onboard using JSON file.
*/
const recoveryPhrase = process.env.RECOVERY_PHRASE
if (recoveryPhrase) {
await walletPageHelper.onboardWithSeedPhrase(recoveryPhrase)
const jsonPassword = process.env.JSON_PASSWORD
if (jsonPassword) {
await walletPageHelper.onboardWithJSON(
"./e2e-tests/utils/JSON.json",
jsonPassword
)
} else {
throw new Error("RECOVERY_PHRASE environment variable is not defined.")
throw new Error("JSON_PASSWORD environment variable is not defined.")
}

/**
Expand Down Expand Up @@ -185,13 +205,16 @@ test.describe("Transactions", () => {
}) => {
await test.step("Import account", async () => {
/**
* Onboard using walletPageHelper
* Onboard using JSON file.
*/
const recoveryPhrase = process.env.RECOVERY_PHRASE
if (recoveryPhrase) {
await walletPageHelper.onboardWithSeedPhrase(recoveryPhrase)
const jsonPassword = process.env.JSON_PASSWORD
if (jsonPassword) {
await walletPageHelper.onboardWithJSON(
"./e2e-tests/utils/JSON.json",
jsonPassword
)
} else {
throw new Error("RECOVERY_PHRASE environment variable is not defined.")
throw new Error("JSON_PASSWORD environment variable is not defined.")
}

/**
Expand Down Expand Up @@ -327,13 +350,16 @@ test.describe("Transactions", () => {
}) => {
await test.step("Import account", async () => {
/**
* Onboard using walletPageHelper
* Onboard using JSON file.
*/
const recoveryPhrase = process.env.RECOVERY_PHRASE
if (recoveryPhrase) {
await walletPageHelper.onboardWithSeedPhrase(recoveryPhrase)
const jsonPassword = process.env.JSON_PASSWORD
if (jsonPassword) {
await walletPageHelper.onboardWithJSON(
"./e2e-tests/utils/JSON.json",
jsonPassword
)
} else {
throw new Error("RECOVERY_PHRASE environment variable is not defined.")
throw new Error("JSON_PASSWORD environment variable is not defined.")
}

/**
Expand Down
84 changes: 51 additions & 33 deletions e2e-tests/regular/transactions.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from "fs"
import { test, expect } from "../utils"

test.describe("Transactions", () => {
Expand All @@ -8,13 +9,30 @@ test.describe("Transactions", () => {
}) => {
await test.step("Import account", async () => {
/**
* Onboard using walletPageHelper
* Create a JSON file with an encoded private key based on the file
* content passed from an environment variable. The further steps of
* the test assume that the file encodes the pk of the `testertesting.eth`
* account. The JSON file can be generated using a script
* `scripts/key-generation/export-key-as-json.js`.
*/
const recoveryPhrase = process.env.RECOVERY_PHRASE
if (recoveryPhrase) {
await walletPageHelper.onboardWithSeedPhrase(recoveryPhrase)
const jsonBody = process.env.JSON_BODY
if (jsonBody) {
fs.writeFileSync("./e2e-tests/utils/JSON.json", jsonBody)
} else {
throw new Error("RECOVERY_PHRASE environment variable is not defined.")
throw new Error("JSON_BODY environment variable is not defined.")
}

/**
* Onboard using JSON file.
*/
const jsonPassword = process.env.JSON_PASSWORD
if (jsonPassword) {
await walletPageHelper.onboardWithJSON(
"./e2e-tests/utils/JSON.json",
jsonPassword
)
} else {
throw new Error("JSON_PASSWORD environment variable is not defined.")
}

/**
Expand Down Expand Up @@ -113,36 +131,36 @@ test.describe("Transactions", () => {
await popup.getByRole("button", { name: "Continue", exact: true }).click()
})

await test.step("Send transaction", async () => {
/**
* Check if "Transfer" has opened and verify elements on the page.
*/
await transactionsHelper.verifyTransferScreen(
"Goerli",
"testertesting\\.eth",
"0x47745a7252e119431ccf973c0ebd4279638875a6",
"0x4774…875a6",
"0",
"ETH",
true
)
// await test.step("Send transaction", async () => {
// /**
// * Check if "Transfer" has opened and verify elements on the page.
// */
// await transactionsHelper.verifyTransferScreen(
// "Goerli",
// "testertesting\\.eth",
// "0x47745a7252e119431ccf973c0ebd4279638875a6",
// "0x4774…875a6",
// "0",
// "ETH",
// true
// )

/**
* Sign.
*/
await popup.getByRole("button", { name: "Sign" }).click()
// /**
// * Sign.
// */
// await popup.getByRole("button", { name: "Sign" }).click()

/**
* Confirm there is "Transaction signed, broadcasting..." snackbar visible
* and there is no "Transaction failed to broadcast" snackbar visible.
*/
await expect(
popup.getByText("Transaction signed, broadcasting...").first()
).toBeVisible() // we need to use `.first()` because sometimes Playwright catches 2 elements matching that copy
await expect(
popup.getByText("Transaction failed to broadcast.")
).toHaveCount(0)
})
// /**
// * Confirm there is "Transaction signed, broadcasting..." snackbar visible
// * and there is no "Transaction failed to broadcast" snackbar visible.
// */
// await expect(
// popup.getByText("Transaction signed, broadcasting...").first()
// ).toBeVisible() // we need to use `.first()` because sometimes Playwright catches 2 elements matching that copy
// await expect(
// popup.getByText("Transaction failed to broadcast.")
// ).toHaveCount(0)
// })

await test.step(
"Verify asset activity screen and latest transaction status",
Expand Down
62 changes: 61 additions & 1 deletion e2e-tests/utils/onboarding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BrowserContext, test as base, expect, Page } from "@playwright/test"
import * as path from "path"

export const getOnboardingPage = async (
context: BrowserContext
Expand Down Expand Up @@ -60,7 +61,7 @@ export default class OnboardingHelper {
}): Promise<void> {
const page = onboardingPage || (await getOnboardingPage(this.context))

await base.step("Onboard readonly address", async () => {
await base.step("Onboard using seed", async () => {
await page.getByRole("button", { name: "Use existing wallet" }).click()
await page.getByRole("button", { name: "Import recovery phrase" }).click()

Expand All @@ -86,6 +87,65 @@ export default class OnboardingHelper {
})
}

async addAccountFromJSON({
file,
filePassword,
onboardingPage,
}: {
file: string
filePassword: string
onboardingPage?: Page
}): Promise<void> {
const page = onboardingPage || (await getOnboardingPage(this.context))

await base.step("Onboard using JSON with private key", async () => {
await page.getByRole("button", { name: "Use existing wallet" }).click()
await page.getByRole("button", { name: "Import private key" }).click()

const passwordInput = page.locator('input[name="password"]')

if (await passwordInput.isVisible()) {
await page.locator('input[name="password"]').fill(DEFAULT_PASSWORD)
await page
.locator('input[name="confirm_password"]')
.fill(DEFAULT_PASSWORD)
}

await page.getByRole("button", { name: "Begin the hunt" }).click()

await page.getByTestId("panel_switcher").getByText("JSON").click()
// await page.getByText("Browse files").click()

// Start waiting for file chooser before clicking. Note no await.
const fileChooserPromise = page.waitForEvent("filechooser")
await page.getByText("Browse files").click({ force: true })
const fileChooser = await fileChooserPromise
await fileChooser.setFiles(file)

await expect(
page.getByTestId("file_status").getByText(path.basename(file))
).toBeVisible()
await expect(
page.getByText("Wrong file, only JSON accepted")
).toHaveCount(0)

await page.getByPlaceholder(" ").fill(filePassword)
await page.getByRole("button", { name: "Decrypt file" }).click()

await expect(page.getByTestId("loading_doggo")).toBeVisible()
await expect(page.getByText("Decrypting file...")).toBeVisible()
await expect(page.getByText("this may take up to 1 minute")).toBeVisible()

await expect(page.getByText("Completed!")).toBeVisible({ timeout: 60000 })

await page.getByRole("button", { name: "Finalize" }).click()

await expect(
page.getByRole("heading", { name: "Welcome to Taho" })
).toBeVisible()
})
}

async addNewWallet(onboardingPage?: Page): Promise<void> {
const page = onboardingPage || (await getOnboardingPage(this.context))

Expand Down
16 changes: 15 additions & 1 deletion e2e-tests/utils/walletPageHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class WalletPageHelper {
}

/**
* Onboard using walletPageHelper
* Onboard using seed phrase.
*/
async onboardWithSeedPhrase(recoveryPhrase: string): Promise<void> {
const onboardingPage = await getOnboardingPage(this.context)
Expand All @@ -50,6 +50,20 @@ export default class WalletPageHelper {
await this.goToStartPage()
}

/**
* Onboard using JSON with password-encrypted private key
*/
async onboardWithJSON(file: string, filePassword: string): Promise<void> {
const onboardingPage = await getOnboardingPage(this.context)
await this.onboarding.addAccountFromJSON({
file,
filePassword,
onboardingPage,
})
await this.setViewportSize()
await this.goToStartPage()
}

async verifyTopWrap(network: RegExp, accountLabel: RegExp): Promise<void> {
// TODO: maybe we could also verify graphical elements (network icon, profile picture, etc)?

Expand Down
Loading
Loading