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

Create E2E tests for verified/unverified tokens #3472

Merged
merged 37 commits into from
Aug 16, 2023
Merged

Conversation

michalinacienciala
Copy link
Contributor

@michalinacienciala michalinacienciala commented Jun 13, 2023

This commit introduces E2E test that checks the functiolality of verified/unverified tokens. Following general steps are executed:

  1. Import account
  2. Enable Show unverified assets
  3. Hide asset
  4. Trust asset
  5. Hide trusted asset
    A number of checks is performed during each step.

The commit also introduces helper functions and adds data-testid attribute to a couple of DOM elements.

TODO:

Latest build: extension-builds-3472 (as of Wed, 16 Aug 2023 01:05:46 GMT).

This commit introduces E2E test that checks the functiolality of
verified/unverified tokens. Following general steps are executed:
1. Import account
2. Enable `Show unverified assets`
3. Hide asset
4. Trust asset
5. Hide trusted asset
A number of checks is performed during each step.

The commit also introduces helper functions and adds `data-testid` attribute to
a couple of DOM elements.

As some of the code is similar or identical as in the
#3418 PR which is yet not merged to
`main`, some conflicts may arise and will need to be resolved before this change
lands on `main`.

Also some changes will need to be made once
#3195 gets merged to `main`, as this
PR solves a bug causing failures in the tests (the failing part of the test was
temporarily commented out).
@michalinacienciala
Copy link
Contributor Author

The tests were passing locally, but we have a failing check in CI. I'll investigate the failures.

The steps were temporarily commented out because there was a bug that caused the
step to fail. Now that the bug got fixed, we can uncomment.
@michalinacienciala michalinacienciala linked an issue Jun 30, 2023 that may be closed by this pull request
We want to have a control over the account we use in test, as change in the
state of the assets may break the tests. We'll use the account with the address
0x6f1b1f1feb01235e15a7962f16c389c7f8218ed6` (`e2e.testertesting.eth`).

We also fix some flakiness and improve the locators used in tests.
@michalinacienciala michalinacienciala force-pushed the trust-tokens-e2e branch 2 times, most recently from 97bcb56 to 8d1b96a Compare July 21, 2023 11:09
We're removing some code that became unnecessary after the merge from `main`.
We're also switching from onboarding using seed phrase to onboarding using JSON
file with encrypted private key.
Previous implementation wasn't properly handling cases when the assertion was
not met. In such cases it was silently ending the tests, without reporting any
failures (the failure was visible only in the Playwright report, which wasn't
opened by default).
We had a bug in the code that was resulting in price of some assets not being
displayed. We've temporarily commented out the assertions that verify this. Now
that the bug is fixed, we can uncomment.
The `assertAssetDetailsPage` function was a more robust version of the
`verifyAssetActivityScreen` function. When `verifyAssetActivityScreen` was
created we didn't yet have the `AssetsHelper` so we kept the function checking
the activity detais in the `TransactionsHelper`. Now that we have a specific
helper for assets, we can merge both functions into one.
Comment suggested that we could move some of the functions from `AssetsHelper`
to `TransactionsHelper`. After thinking it through, I think it makes sense to
leave the functions where they are, especially that they're used not only during
filling of the Transaction form but also during filling of the Swap form.
We're adding a timeout, as switching to the Polygon network too fast after
importing wallet was causing some of the price info missing for the ERC-20
assets. It's quite unlikely for the real users to switch the network this fast
anyway, so the timeout does not contradict the real user behaviour.
We changed this for production fork builds to differentiate from the release
builds, and we updated e2e tests to look for the suffix, but on non release
branches the fork builds were not getting the suffix, leading to test failures.
The previously used 1s wait sometimes wasn't sufficient.
The checks are no longer failing. What fixed them is not known, but maybe it has
something to do with the wait period added before switching to Polygon.
As we have functionality of verifying assets in the wallet, we recently started
to use `assert` nomenclature in the names of the new functions and methods
checking certain areas of the wallet. This was done to avoid confusion in the
naming. Now we update the older function using the `verify...` prefix, to make
the naming consistent across all our test-related files.
Copy link
Contributor

@jagodarybacka jagodarybacka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bunch of possible improvements 🏗️

/^Ethereum$/,
/^testertesting\.eth$/,
account2Name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use a variable for testertesting.eth string as well? Also other strings like Ethereum etc - so we can avoid typos or other easy bugs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use a variable for testertesting.eth string as well?

Did you mean this comment for line 115 (and other similar)? If so, I've applied that in 95db29f.

Also other strings like Ethereum etc - so we can avoid typos or other easy bugs

and

Network's strings should be reusable variables, same with most common assets like /^MATIC$/, /^WMATIC$/ etc

I feel a bit torn about this...

The good side of moving commonly used labels to some external place is what you said and also possibility to apply changes to the labels quickly, without having to modify them in many places.

But there are also some cons, mainly in cases where we also have the same labels abstracted in the app's code (as this is the case for network names and base assets labels stored in network.ts). What I mean is that having similar implementation in tests and in tested code may lead to introducing same bug in both places and not catching it by the tests.

Another issue is that in tests we sometimes want to use RegExp, sometimes string, sometimes value with all letters capitalized, sometimes only with the first letter captalized etc, depending on the context. We'll either need a separate variable for each different version of the label we use or we'll need to use some method that modifies given variable into the formatting we need.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not saying definitely NO to this idea though. The pros may outweigh the cons...
What would be the best way to approach this? Having all the constant values used by the E2E tests stored in one helper file? Or storing them in files they are related to (something like what we have currently, where names of testing accounts are in the onboarding helper)? The first solution seems more universal to me, but I'm curious if there some good practice I should follow here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that having similar implementation in tests and in tested code may lead to introducing same bug in both places and not catching it by the tests

Another issue is that in tests we sometimes want to use RegExp, sometimes string, sometimes value with all letters capitalized, sometimes only with the first letter captalized etc, depending on the context. We'll either need a separate variable for each different version of the label we use or we'll need to use some method that modifies given variable into the formatting we need.

Both are great points, I'm not entirely onboard with abstracting simple names as it reduces readability on written test cases, which should remain as simple as possible and, are also unlikely to change unless there are changes in the implementation.

Still, I don't think there's much harm if it's a simple string that's repeated multiple times and it's a simple change. Considering that does not seem to be the case here given the multiple variants, I'd keep the hardcoded strings.

@@ -663,7 +663,7 @@
}
},
"unverifiedAssets": {
"tooltip": "Discover assets that you own but are not on our asset list. Some spam/scam assets will show up, so tread carefully.<br/><br/>These will show up on the bottom of the asset page until you verify them."
"tooltip": "Discover assets that you own but are not on our asset list. Some spam/scam assets may show up, so treat them with caution.<br/><br/>They will show up on the bottom of the asset page until you verify them."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬 thanks for fixing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem :)

Comment on lines 25 to 47
const jsonBody = process.env.E2E_TEST_ONLY_WALLET_JSON_BODY
if (jsonBody) {
fs.writeFileSync("./e2e-tests/utils/JSON.json", jsonBody)
} else {
throw new Error(
"E2E_TEST_ONLY_WALLET_JSON_BODY environment variable is not defined."
)
}

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this part should be encapsulated in a method or a util as we most likely will be using this JSON wallet often

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, but will that make much difference? When calling the method, we will still need to provide the environment variables as arguments. And this means that we'll still need to have the if/else conditions present in the token-trust.spec.ts, right? Or maybe there's something I'm missing here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move these to a helper we can reduce duplication. Since we're doing very similar things with TEST_WALLET_JSON_BODY and E2E_TEST_ONLY_WALLET_JSON_BODY, we could put both of these with the corresponding env variables inside a function (if not onboardWithJSON)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is something like this what you had in mind: 5f45f7f?

* Switch to the Polygon network.
*/
await popup.waitForTimeout(3000) // without this timeout the prices of ERC-20 assets are not loaded
await walletPageHelper.switchNetwork(/^Polygon$/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Network's strings should be reusable variables, same with most common assets like /^MATIC$/, /^WMATIC$/ etc

// have a positive balance of at least one of the listed assets. At the
// moment of writing the test, the wallet had positive balance for all
// those assets.
const untrustedAssets = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be declared outside of this test so we don't have to repeat it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 89019b4.

await expect(this.popup.locator(".spinner")).toHaveCount(0, {
timeout: timeout ?? 120000,
})
// await expect(this.popup.locator(".token_icon_fallback")).toHaveCount(0, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we delete it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in e9d7951.

hasText: accountLabel,
})
.getByRole("button")
await this.popup.getByTestId("wallet_title").click({ trial: true }) // TODO: why trial?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, this step and a couple of others nearby were not supposed to land in the final code. Removed in 4e740df.

Comment on lines 268 to 272
const accountsPopup = await this.popup.$(".slide_up_menu:not(.closed)")
if (accountsPopup) {
const closeButton = await accountsPopup.$(
'button[aria-label="Close menu"]'
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we want to add proper test ids?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't do it simpler than this (maybe there's something I didn't think of?).

The problem is that the slide_up_menu DOM element for Accounts contains a bunch of identical slide_up_menu child elements, all containing their own Close button. All Close buttons except of one are not visible for users. On the DOM side, the difference is that those invisible buttons are wrapped with the div element of slide_up_menu closed class, whereas the visible button is wrapped by slide_up_menu with_overflow div.
Adding a test id to the button or the div element does not solve the issue - the id is added to all the elements and we still have the problem with identifying the one we want to click.

As a workaround we use ElementHandle to locate the right item to click, by specifying that the element shouldn't be wrapped by the DOM item of the closed class (I couldn't do that using classic Locator syntax).

And now, going back to your suggestion - switching to use of the test ids everywhere in the function would not work from the above mentioned reasons. And sticking with use of the ElemenHandle to locate the right slide_up_menu and using the test id to locate the Close menu would also not work, because the getByTestId cannot be called on the ElementHandle objects.

We could add a data-testid="slide_up_menu_close" line after this one and then try to do

this.popup.getByTestId("slide_up_menu_close").click()

in the closeAccountsPopup() function, but this does not work. It finds multiple identical matching DOM elements. The only significant difference between the matched elements is that the parent element of the one we want to click has class slide_up_menu with_overflow

Anyway, as all of this is not straightforward, I've added a comment to the closeAccountsPopup() function, that explains why we use ElementHandle there: b4a61d2.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add a test id here like accounts_list_slide_up_menu

<SharedSlideUpMenu
isOpen={isNotificationsOpen}
allowOverflow
close={() => {
setIsNotificationsOpen(false)
}}
>

Then use playwright assertions so we don't have to throw up errors if the locator doesn't return anything

const accountsSlideUp = this.popup.getByTestId(
      "accounts_list_slide_up_menu"
    )

    await expect(accountsSlideUp).toBeVisible()

This slide up is indeed trickier because there are nested slide ups so to get the right close button we can just ask playwright to return the first one it finds, we'll get the right one because we start looking from the right slide up menu.

    await accountsSlideUp
      .getByRole("button", { name: "Close menu" })
      .first()
      .click()

This way playwright throws if it can't find the element to click so we can skip the manual if check as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me that this the test id set in this place does not get reflected in the final DOM. I've set this in the extension/ui/components/TopMenu/TopMenu.tsx:

      <SharedSlideUpMenu
        isOpen={isNotificationsOpen}
        allowOverflow
        close={() => {
          setIsNotificationsOpen(false)
        }}
        data-testid="accounts_list_slide_up_menu"
      >

Then I rebuilt the code and run a test that does this:

      await popup.getByTestId("top_menu_profile_button").last().click()
      await walletPageHelper.closeAccountsSlideUp()

where closeAccountsSlideUp() looks like this:

  async closeAccountsSlideUp(): Promise<void> {
    const accountsSlideUp = await this.popup.getByTestId(
      "accounts_list_slide_up_menu"
    )
    await expect(accountsSlideUp).toBeVisible()
    await accountsSlideUp
      .getByRole("button", { name: "Close menu" })
      .first()
      .click()

I've got a failure of the await expect(accountsSlideUp).toBeVisible() assertion. I checked the DOM of the app and there was no element with the accounts_list_slide_up_menu test id. The Accounts slide up had the slide_up_menu test id, which is set in

testid = "slide_up_menu",
.
Maybe we can't overwrite one test id with another?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works:

  async closeAccountsSlideUp(): Promise<void> {
    const accountsSlideUp = await this.popup.getByTestId("slide_up_menu").nth(2)
    await expect(accountsSlideUp).toBeVisible()
    await accountsSlideUp
      .getByRole("button", { name: "Close menu" })
      .first()
      .click()
  }

However I'm not a fan of using .nth(2) to locate the right slide up menu.
Playing a bit more with this, I was able to simplify the code by using filtering:

  async closeAccountsSlideUp(): Promise<void> {
    const accountsSlideUp = await this.popup
      .getByTestId("slide_up_menu")
      .filter({ hasText: "Accounts" })
    await expect(accountsSlideUp).toBeVisible()
    await accountsSlideUp
      .getByRole("button", { name: "Close menu" })
      .first()
      .click()
  }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me that this the test id set in this place does not get reflected in the final DOM. I've set this in the extension/ui/components/TopMenu/TopMenu.tsx:

      <SharedSlideUpMenu
        isOpen={isNotificationsOpen}
        allowOverflow
        close={() => {
          setIsNotificationsOpen(false)
        }}
        data-testid="accounts_list_slide_up_menu"
      >

On this code, it seems we passed a data-testid prop instead of testid to SharedSlideUpMenu. If that's the case, it would explain why the test id was not set correctly on the element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in c562952.


if (assetType === "base" || assetType === "knownERC20") {
await expect(
activityLeftContainer.getByText(/^\$(\d|,)+\.\d{2}$/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These regex should be named variables

Comment on lines +313 to +325
// Below assertions fail, as `Verify asset` and `Asset not verified`
// elements are present in DOM even when unverified assets are collapsed.
// There's no easy way to assert that those elements are not visible to a
// human eye.
// await expect(
// this.popup.getByRole("button", { name: "Verify asset" }).first()
// ).toBeHidden()
// await expect(this.popup.getByText("Asset not verified")).not.toBeVisible()
// await expect(
// this.popup.getByText(
// "Be aware of scam and spam assets, only interact with assets you trust."
// )
// ).not.toBeVisible()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some html attribute or check it by CSS class to make it easier to test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to Playwright documentation

Element is considered visible when it has non-empty bounding box and does not have visibility:hidden computed style. Note that elements of zero size or with display:none are not considered visible.

One thing that we could do is to do something to make the elements' style be computed to visibility:hidden. I'm not sure though how easily can we do this...

Another approach would be to use ElemenHandle syntax to check that elements we want to make sure are invisible are children of the div element with the hidden_assets class, but no visible class. But this seems to me unnecessarily complex, given that checking

await expect(
      this.popup.getByTestId("hidden_assets_container")
    ).not.toBeVisible()

already tells us that the section with unverified assets does not have the visible class.

/**
* Function adding new address to an already imported account
*/
async addAddressToAccount(accountLabel: string): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, due to the fact that during work on this PR I switched from importing the tests account via recovery phrase to import via JSON, I no longer use this function (and closeAccountsPopup as well). However, those function may come handy some day. What is the best practice here? Leave it as it is or maybe comment out or remove completely?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one looks useful and generic enough that we could benefit from keeping it but I'd suggest that we move here the code from closeAccountsPopup and separate it later if we need the logic somewhere else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 1cf604e.

Copy link
Contributor

@hyphenized hyphenized left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall 💪! Left a few comments

this.popup
.getByTestId("hidden_assets_container")
.filter({ has: asset.getByText(assetSymbol) })
).not.toBeVisible()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this won't work if we have some spam asset with the same name as the one we just verified

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored the assertVerifiedAssetOnWalletPage() method to handle such case. See 1265763.

Comment on lines 29 to 30
await this.popup.waitForTimeout(2000) // We need to wait for the background elements to disappear
await expect(asset.getByText(assetSymbol)).toBeVisible()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can set the timeout on the assertion itself too (unless for some reason it does not work)

Suggested change
await this.popup.waitForTimeout(2000) // We need to wait for the background elements to disappear
await expect(asset.getByText(assetSymbol)).toBeVisible()
await this.popup.waitForTimeout(2000) // We need to wait for the background elements to disappear
await expect(asset.getByText(assetSymbol)).toBeVisible({ timeout: 2000 })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that some of the recent changes made the timeout completely obsolete. I removed it in c21299e.

Comment on lines 268 to 272
const accountsPopup = await this.popup.$(".slide_up_menu:not(.closed)")
if (accountsPopup) {
const closeButton = await accountsPopup.$(
'button[aria-label="Close menu"]'
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add a test id here like accounts_list_slide_up_menu

<SharedSlideUpMenu
isOpen={isNotificationsOpen}
allowOverflow
close={() => {
setIsNotificationsOpen(false)
}}
>

Then use playwright assertions so we don't have to throw up errors if the locator doesn't return anything

const accountsSlideUp = this.popup.getByTestId(
      "accounts_list_slide_up_menu"
    )

    await expect(accountsSlideUp).toBeVisible()

This slide up is indeed trickier because there are nested slide ups so to get the right close button we can just ask playwright to return the first one it finds, we'll get the right one because we start looking from the right slide up menu.

    await accountsSlideUp
      .getByRole("button", { name: "Close menu" })
      .first()
      .click()

This way playwright throws if it can't find the element to click so we can skip the manual if check as well.

/**
* Function adding new address to an already imported account
*/
async addAddressToAccount(accountLabel: string): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one looks useful and generic enough that we could benefit from keeping it but I'd suggest that we move here the code from closeAccountsPopup and separate it later if we need the logic somewhere else.

@Shadowfiend
Copy link
Contributor

@hyphenized do you consider any of your notes above blockers?

@hyphenized
Copy link
Contributor

@hyphenized do you consider any of your notes above blockers?

I don't consider these as blockers for merging, but I do see these as concerns regarding code quality and potential future technical debt.

@Shadowfiend
Copy link
Contributor

Cool, since Michalina is back on Monday we'll keep this fellow open for visibility and merge after she's had a look.

As after opening the Accounts list, there were multiple `slide_up_menu`
elements in the wallet's DOM, and only one was not of a `closed` class, we were
using the `ElementHandle` syntax to find the one which is not closed (the one
we wanted to click). This then influenced the way how we can locate the `Close
menu` button, making the code quite complicated.
In this PR we are simplifying the code, by filtering the slide up menus by the
`Accounts` text. Then we are able to point to the right `Close menu` element by
using `.first()` locator.
Both functions are currently not used by the e2e tests, but we want to keep
them in case they're needed in the future. We're moving the steps closing the
Accounts slide up to the `addAddressToAccount()` functions for now. They may be
separated on the future, if there will be a need for this.
There may be a situation where we have a spam asset named the same as the
asset we verified and are checking in the `assertVerifiedAssetOnWalletPage`
function. The previous implementation of the function wasn't supporting such
case. Now the function should handle it.
We've pulled some of the code relating to JSON onboarding reused in several
tests to a `WalletPageHelper`'s `onboardWithJSON` method. Now the onboarding
with JSON in e2e tests requires just one command:
`await walletPageHelper.onboardWithJSON(<account>)`,
where `account` can be either `account1`, `account2`, or `custom`.
The `account1`'s and `account2`'s JSON data (body & password) is accessed via
the `onboarding.ts` file. The `custom` option allows for onboarding wit a custom
account and requires providing the `customJsonBody` and `customFilePassword`
parameters.
So far we've been storing each piece of the account-specific data in a separate
variable. We are now reorganizing the data into objects adhering to a common
interface structure.
Copy link
Contributor

@hyphenized hyphenized left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments addressed

@hyphenized hyphenized merged commit 3fdd9dc into main Aug 16, 2023
@hyphenized hyphenized deleted the trust-tokens-e2e branch August 16, 2023 00:54
@Shadowfiend Shadowfiend mentioned this pull request Aug 31, 2023
Shadowfiend added a commit that referenced this pull request Sep 2, 2023
## What's Changed
* Create E2E tests for verified/unverified tokens by @michalinacienciala
in #3472
* v0.47.0 by @Shadowfiend in
#3601
* Versions that go bump in the night: Bump versions across a few
different core dependencies by @Shadowfiend in
#3415


**Full Changelog**:
v0.47.0...v0.48.0

Latest build:
[extension-builds-3610](https://github.com/tahowallet/extension/suites/15695499704/artifacts/896067135)
(as of Thu, 31 Aug 2023 16:31:16 GMT).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add E2E tests for trust tokens
4 participants