From 397157001c098a0dc105ec51b0b91f3819252a04 Mon Sep 17 00:00:00 2001 From: Michalina Date: Thu, 2 Nov 2023 17:48:50 +0100 Subject: [PATCH 1/7] Update name of the collection The name of the NFT collection was changed from `Notable Crypto Punks` to `Notable Punks`. We're updating e2e tests to reflect that. --- e2e-tests/regular/nfts.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/regular/nfts.spec.ts b/e2e-tests/regular/nfts.spec.ts index 0fee95ad2..9d5ff3572 100644 --- a/e2e-tests/regular/nfts.spec.ts +++ b/e2e-tests/regular/nfts.spec.ts @@ -180,7 +180,7 @@ test.describe("NFTs", () => { const nftCollection = page .getByTestId("nft_list_item") .filter({ has: page.getByTestId("nft_list_item_collection") }) - .filter({ hasText: "Notable Crypto Punks" }) + .filter({ hasText: "Notable Punks" }) .first() await nftCollection.hover() From 905f495268f5ffabc4651bcbfd66e91b7d597d1c Mon Sep 17 00:00:00 2001 From: Michalina Date: Thu, 2 Nov 2023 19:49:25 +0100 Subject: [PATCH 2/7] Verify that the seed phrase words are displayed before reading them Previously when constructing an array of the seed words, we didn't verify that the words are already loaded, which could result in returning an empty array. Now we make sure all 24 words are present before creating the array with seed phrase words. --- e2e-tests/regular/onboarding.spec.ts | 8 +++++++- e2e-tests/utils/onboarding.ts | 14 ++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/e2e-tests/regular/onboarding.spec.ts b/e2e-tests/regular/onboarding.spec.ts index 0cd5454d3..4ef5565b7 100644 --- a/e2e-tests/regular/onboarding.spec.ts +++ b/e2e-tests/regular/onboarding.spec.ts @@ -72,7 +72,11 @@ test.describe("Onboarding", () => { await page.getByRole("button", { name: "Begin the hunt" }).click() await page.getByRole("button", { name: "Create recovery phrase" }).click() - // Verify seed + // Wait for the seed phrase to load. + const seedPhraseWord = await page.locator(".seed_phrase .word") + await expect(seedPhraseWord).toHaveCount(24) + + // Extract seed into an array of words with no spaces or dashes. const seedWords = ( await page.locator(".seed_phrase .word").allTextContents() ).map((word) => word.replace(/-|\s/, "")) @@ -83,6 +87,8 @@ test.describe("Onboarding", () => { "verify_seed_word_placeholder", ) + // Extract the ids of the seed phrase words that need to be verified and + // store them as an array of numbers. const wordsToVerify = (await seedWordPlaceholders.allTextContents()).map( (word) => Number((word.match(/\d+/) ?? ["0"])[0]), ) diff --git a/e2e-tests/utils/onboarding.ts b/e2e-tests/utils/onboarding.ts index 0a42b463b..61ee6a075 100644 --- a/e2e-tests/utils/onboarding.ts +++ b/e2e-tests/utils/onboarding.ts @@ -183,10 +183,14 @@ export default class OnboardingHelper { await page.getByRole("button", { name: "Begin the hunt" }).click() await page.getByRole("button", { name: "Create recovery phrase" }).click() - // Verify seed - const seedWords = ( - await page.locator(".seed_phrase .word").allTextContents() - ).map((word) => word.replace(/-|\s/, "")) + // Wait for the seed phrase to load. + const seedPhraseWord = await page.locator(".seed_phrase .word") + await expect(seedPhraseWord).toHaveCount(24) + + // Extract seed into an array of words with no spaces or dashes. + const seedWords = (await seedPhraseWord.allTextContents()).map((word) => + word.replace(/-|\s/, ""), + ) await page.getByRole("button", { name: "I wrote it down" }).click() @@ -194,6 +198,8 @@ export default class OnboardingHelper { "verify_seed_word_placeholder", ) + // Extract the ids of the seed phrase words that need to be verified and + // store them as an array of numbers. const wordsToVerify = (await seedWordPlaceholders.allTextContents()).map( (word) => Number((word.match(/\d+/) ?? ["0"])[0]), ) From 8630714827afc41618fa9b91f847ae7666764c59 Mon Sep 17 00:00:00 2001 From: Michalina Date: Thu, 2 Nov 2023 20:08:49 +0100 Subject: [PATCH 3/7] Upgrade Playwright to the latest stable version (`1.39.0`) Thanks to the upgrade we're able to access new functionalities, e.g. UI Mode. --- package.json | 2 +- yarn.lock | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index f4c6cc831..166daad2d 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "@babel/preset-react": "^7.22.5", "@babel/preset-typescript": "^7.22.11", "@babel/register": "^7.22.5", - "@playwright/test": "^1.31", + "@playwright/test": "^1.39", "@redux-devtools/cli": "^2.0.0", "@thesis-co/eslint-config": "^0.6.1", "@types/archiver": "^5.1.0", diff --git a/yarn.lock b/yarn.lock index 5b582093c..dacad0c3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3425,15 +3425,12 @@ picocolors "^1.0.0" tslib "^2.6.0" -"@playwright/test@^1.31": - version "1.31.0" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.31.0.tgz#bde42ca06804164be54893525110adda946248d6" - integrity sha512-Ys5s/06Dg9g3zAIdCIb/UOBYim3U7Zjb3DvC6XBtnRmnglH5O47iwYzmtxXu9fhSyzI2Jn28apkXIOD81GgCdw== +"@playwright/test@^1.39": + version "1.39.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.39.0.tgz#d10ba8e38e44104499e25001945f07faa9fa91cd" + integrity sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ== dependencies: - "@types/node" "*" - playwright-core "1.31.0" - optionalDependencies: - fsevents "2.3.2" + playwright "1.39.0" "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -13018,10 +13015,19 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.31.0: - version "1.31.0" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.31.0.tgz#dbd184771535e76c6743ef5c082def5564f07e85" - integrity sha512-/KquBjS5DcASCh8cGeNVHuC0kyb7c9plKTwaKxgOGtxT7+DZO2fjmFvPDBSXslEIK5CeOO/2kk5rOCktFXKEdA== +playwright-core@1.39.0: + version "1.39.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.39.0.tgz#efeaea754af4fb170d11845b8da30b2323287c63" + integrity sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw== + +playwright@1.39.0: + version "1.39.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.39.0.tgz#184c81cd6478f8da28bcd9e60e94fcebf566e077" + integrity sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw== + dependencies: + playwright-core "1.39.0" + optionalDependencies: + fsevents "2.3.2" portfinder@^1.0.17: version "1.0.28" From 735a98e3971540a42b45bf5042ff2a6417b4b66f Mon Sep 17 00:00:00 2001 From: Michalina Date: Fri, 3 Nov 2023 11:06:17 +0100 Subject: [PATCH 4/7] Modify locator identifying `Select token` buttons It looks that after upgrading to the latest version of Playwright something has changed in the way how some locators work. The `.getByRole("button", { name: "Select token", exact: true })` locator no longer identified the button we wanted to click on the Swap screen. In this commit we're changing the location method. --- e2e-tests/regular/token-trust.spec.ts | 50 ++++++--------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/e2e-tests/regular/token-trust.spec.ts b/e2e-tests/regular/token-trust.spec.ts index 8b8b479c5..52ded3376 100644 --- a/e2e-tests/regular/token-trust.spec.ts +++ b/e2e-tests/regular/token-trust.spec.ts @@ -135,16 +135,10 @@ test.describe("Token Trust", () => { * Verify there are no unverified assets on the Swap screen. */ await popup.getByLabel("Swap", { exact: true }).click() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .first() - .click() + await popup.getByLabel("Swap from:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(untrustedAssets) await assetsHelper.closeSelectTokenPopup() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .nth(1) - .click() + await popup.getByLabel("Swap to:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(untrustedAssets) await assetsHelper.closeSelectTokenPopup() }) @@ -265,16 +259,10 @@ test.describe("Token Trust", () => { * Verify there are no unverified assets on the Swap screen. */ await popup.getByLabel("Swap", { exact: true }).click() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .first() - .click() + await popup.getByLabel("Swap from:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(untrustedAssets) await assetsHelper.closeSelectTokenPopup() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .nth(1) - .click() + await popup.getByLabel("Swap to:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(untrustedAssets) await assetsHelper.closeSelectTokenPopup() }) @@ -345,16 +333,10 @@ test.describe("Token Trust", () => { * Verify there is no "pAAVE" asset on the Swap screen. */ await popup.getByLabel("Swap", { exact: true }).click() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .first() - .click() + await popup.getByLabel("Swap from:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(["pAAVE"]) await assetsHelper.closeSelectTokenPopup() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .nth(1) - .click() + await popup.getByLabel("Swap to:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(["pAAVE"]) await assetsHelper.closeSelectTokenPopup() }) @@ -423,16 +405,10 @@ test.describe("Token Trust", () => { * Verify recently trusted asset is available on the Swap screen. */ await popup.getByLabel("Swap", { exact: true }).click() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .first() - .click() + await popup.getByLabel("Swap from:").click() await assetsHelper.assertAssetsPresentOnAssetsList(["BANANA"]) await assetsHelper.closeSelectTokenPopup() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .nth(1) - .click() + await popup.getByLabel("Swap to:").click() await assetsHelper.assertAssetsPresentOnAssetsList(["BANANA"]) await assetsHelper.closeSelectTokenPopup() }) @@ -500,16 +476,10 @@ test.describe("Token Trust", () => { * Verify there is no "BANANA" asset on the Swap screen. */ await popup.getByLabel("Swap", { exact: true }).click() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .first() - .click() + await popup.getByLabel("Swap from:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(["BANANA"]) await assetsHelper.closeSelectTokenPopup() - await popup - .getByRole("button", { name: "Select token", exact: true }) - .nth(1) - .click() + await popup.getByLabel("Swap to:").click() await assetsHelper.assertAssetsNotPresentOnAssetsList(["BANANA"]) await assetsHelper.closeSelectTokenPopup() }) From e36558a40db948f64f832650e7866d996d9d9fe3 Mon Sep 17 00:00:00 2001 From: Michalina Date: Fri, 10 Nov 2023 13:19:08 +0100 Subject: [PATCH 5/7] Update regex after change of `U+202F` to `U+0020` space char in date Previously a space character before the 'AM'/'PM' in the date was a character with `U+202F` unicode (narrow no-break space). Now the space character is coded as `U+0020` (regular space). We'e updating the e2e tests to reflect this change. --- e2e-tests/utils/transactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/utils/transactions.ts b/e2e-tests/utils/transactions.ts index af2d89837..86e73c94b 100644 --- a/e2e-tests/utils/transactions.ts +++ b/e2e-tests/utils/transactions.ts @@ -271,7 +271,7 @@ export default class TransactionsHelper { timestampRow .locator(".right") // eslint-disable-next-line no-irregular-whitespace - .getByText(/^\d{1,2}\/\d{1,2}\/\d{4}, \d{1,2}:\d{2}:\d{2}( AM| PM)*$/), + .getByText(/^\d{1,2}\/\d{1,2}\/\d{4}, \d{1,2}:\d{2}:\d{2}( AM| PM)*$/), ).toBeVisible() } From 938b65da57dcceb47c0dcdc7973652696de50f3b Mon Sep 17 00:00:00 2001 From: Michalina Date: Sun, 12 Nov 2023 13:07:16 +0100 Subject: [PATCH 6/7] Expect the SIWE test to fail, due to bug on login.xyz Recently the signing in with Ethereum on login.xyz started to misbehave. The old behavior was that there was a `Vote for your favorite emoji` poll visible on the website after confirming SIWE in the wallet. Now the website shows the same state as before the signing. In website console there's a `Cannot read properties of undefined (reading 'vote')` error. The issue got reported on https://discord.com/channels/862419652286218251/886997073650655232/1173226370776694794. We've been using login.xyz in our automated tests when checking SIWE. Until the issue is fixed, we're marking the test as expected to fail. That means that the test will be marked in logs as passed when there's no `Vote for your favorite emoji` on the page after signing. If the string will be found, Playwright will log a failure and will print `Expected to fail, but passed.`. Placing the `test.fail()` expression just before the failing step makes sure that failures on earlier stages will not be considered as expected and will still be flagged. --- e2e-tests/regular/signing.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e-tests/regular/signing.spec.ts b/e2e-tests/regular/signing.spec.ts index c433b31fc..b785bb7be 100644 --- a/e2e-tests/regular/signing.spec.ts +++ b/e2e-tests/regular/signing.spec.ts @@ -26,8 +26,11 @@ test.describe("Signing", () => { await signDataPromptOpens.then(async (prompt) => { await prompt.getByRole("button", { name: "Sign" }).click() }) - - // If we see this then it means we were able to sign in + // There's a bug on login.xyz that makes the test fail + // (https://discord.com/channels/862419652286218251/886997073650655232/1173226370776694794). + // We're adding the expectation of failure. Playwright will throw `Expected + // to fail, but passed.` when bug is fixed. + test.fail() await expect(siwe.getByText("Vote for your favorite emoji")).toBeVisible() }) From f0441b13e01e76cf95c5480db7ec1d2cad1ce3ad Mon Sep 17 00:00:00 2001 From: Michalina Date: Thu, 16 Nov 2023 16:05:47 +0100 Subject: [PATCH 7/7] Use soft assertions when expecting snackbar There is a bug in the wallet which manifests with the snackbar with the action's status not displaying after that action. This happens sporadically and does not mean that the action wasn't successful. We want to be notified when the bug occurs, but we don't want it to block execution of the subsequent steps. That's why we use the soft assertions. --- e2e-tests/fork-based/transactions.spec.ts | 12 ++++++------ e2e-tests/regular/token-trust.spec.ts | 20 +++++++++++--------- e2e-tests/regular/transactions.spec.ts | 6 +++--- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/e2e-tests/fork-based/transactions.spec.ts b/e2e-tests/fork-based/transactions.spec.ts index ec58d801f..78986e21a 100644 --- a/e2e-tests/fork-based/transactions.spec.ts +++ b/e2e-tests/fork-based/transactions.spec.ts @@ -105,9 +105,9 @@ test.describe("Transactions", () => { * 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 + .soft(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) @@ -478,9 +478,9 @@ test.describe("Transactions", () => { * 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 + .soft(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) diff --git a/e2e-tests/regular/token-trust.spec.ts b/e2e-tests/regular/token-trust.spec.ts index 52ded3376..549dccc2e 100644 --- a/e2e-tests/regular/token-trust.spec.ts +++ b/e2e-tests/regular/token-trust.spec.ts @@ -293,9 +293,9 @@ test.describe("Token Trust", () => { /** * Confirm there is `Asset removed from list` snackbar visible. */ - await expect( - popup.getByText("Asset removed from list").first(), - ).toBeVisible({ timeout: 5000 }) + await expect + .soft(popup.getByText("Asset removed from list").first()) + .toBeVisible({ timeout: 5000 }) /** * Make sure `Wallet` page is opened and there are unverified assets @@ -367,9 +367,11 @@ test.describe("Token Trust", () => { /** * Confirm there is `Asset added to list` snackbar visible. */ - await expect(popup.getByText("Asset added to list").first()).toBeVisible({ - timeout: 5000, - }) + await expect + .soft(popup.getByText("Asset added to list").first()) + .toBeVisible({ + timeout: 5000, + }) /** * Confirm asset's details are opened. Ensure there are fields related to @@ -436,9 +438,9 @@ test.describe("Token Trust", () => { /** * Confirm there is `Asset removed from list` snackbar visible. */ - await expect( - popup.getByText("Asset removed from list").first(), - ).toBeVisible({ timeout: 5000 }) + await expect + .soft(popup.getByText("Asset removed from list").first()) + .toBeVisible({ timeout: 5000 }) /** * Make sure `Wallet` page is opened and there are unverified assets diff --git a/e2e-tests/regular/transactions.spec.ts b/e2e-tests/regular/transactions.spec.ts index bb0a1df01..2d5718fa0 100644 --- a/e2e-tests/regular/transactions.spec.ts +++ b/e2e-tests/regular/transactions.spec.ts @@ -136,9 +136,9 @@ test.describe("Transactions", () => { * 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 + .soft(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)