Dappeteer vs Synpress

You asked you got it !! JK 😂 , this was in my backlog for a long time and finally had time to write something about it. This literally summarises my life:

Not many people out there talking about Blockchain Tests, maybe Oleksandr Romanov and Rhian Lewis, so I usually resource to communities (Web3Tests, Synpress…) to see what others are doing.

It is a bit shocking as there are many well-known attacks in this technology and on top of that after deploying something to the Blockchain you can’t go back (immutability feature), so how come this phase is so neglected as making sure everything is alright is so crucial ?

I am doing a quick benchmark about the End-to-End Tests Web3 Frameworks that are out there, and yes you can always mock the Web3 and then you don’t rely on third party integrations, which you would do any Web2 application already. But hey, this is one option to use when you need it !

Here it is what I got from the two major and most popular tools to test Web3 Apps (DApps):

CriteriaSynpressDappeteer
Platform & Application SupportWeb3 applications (Dapps)Web3 applications (Dapps)
Supported TechnologiesTypeScript, JavascriptTypeScript, Javascript
Wallets supportedMetaMaskMetaMask snaps, but probably is outdated.
Testing ScopeE2E TestsE2E Tests
Testing Framework IntegrationPlaywright (as a plugin)
Support for Cypress is coming soon.
Playwright (as a plugin)
Puppeteer (as a plugin)
Ease of Use & Learning CurveEasy learning curve, requires JavaScript/Typecript knowledgeRequires JavaScript/Typescript knowledge
Reporting & AnalyticsDetailed reports with dashboards and integrationsBasic reporting, may require additional tools
Ease of setupEasy to set up with Node.js, yarn and npmEasy to set up with Node.js, yarn and npm
Browsers– Chrome/Chromium (+ Edge, Opera, Brave, Chromium-based browsers)
– Firefox
– Webkit (Safari)
– Chrome/Chromium (+ Edge, Opera, Brave, Chromium-based browsers)
– Webkit (Safari)
Community & SupportLarge and active community, extensive documentation and supportSmaller community, growing resources and documentation
Cost & LicensingOpen source and free to useOpen source and free to use
Scalability & IntegrationHighly scalable, integrates with CI/CD pipelinesLess information available, may require custom integrations
AccessibilitySupports accessibility testing with pluginsInformation not available.
CustomizationHighly customizable with plugins and extensionsHighly customizable with plugins and extensions

Let me know in the comments which option you went for and how was your experience with it 😃

Implement Synpress support methods in your Web3 tests

Hello guys,

Today I am going to post a quick and easy to use snippet with Synpress MetaMask support methods in your Web3 E2E (end-to-end) Test Project.

Create a base class to get the Synpress methods and extend it to use across the project. Here are some examples of methods that you can have:

export default class MetaMaskSupport {
  getCurrentNetwork() {
    return cy.getNetwork();
  }

 isMetamaskWindowActive() {
      return cy.isMetamaskWindowActive();
  }

  getMetamaskWalletAddress() {
    return cy.fetchMetamaskWalletAddress();
  }

  acceptMetamaskAccessRequest() {
    cy.acceptMetamaskAccess();
  }
}

Then you can either extend the class:

import MetaMaskSupport from '../metaMaskSupport';

export default class HomePage extends MetaMaskSupport {
  constructor() {
    super();
  }

  visit() {
    cy.visit('/');
  }

  waitUntilLoggedIn() {
    cy.waitUntil(() => {
      const walletAddress = this.getMetamaskWalletAddress();
      return walletAddress.should('exist');
    });
  }

  getLoggedInWalletAddress() {
    const walletAddress = this.getMetamaskWalletAddress();
    return walletAddress.invoke('text');
  }
}

Or you can instantiate as an object:

import MetaMaskSupport from '../metaMaskSupport';

export default class HomePage {
  constructor() {
    super();
    this.metaMaskSupport = new MetaMaskSupport();
  }

  visit() {
    cy.visit('/');
  }

  waitUntilLoggedIn() {
    cy.waitUntil(() => {
      const walletAddress = this.metaMaskSupport.getMetamaskWalletAddress();
      return walletAddress.should('exist');
    });
  }

  getLoggedInWalletAddress() {
    const walletAddress = this.metaMaskSupport.getMetamaskWalletAddress();
    return walletAddress.invoke('text');
  }
}

Now, get yourself a drink, you deserve it 🤣