Synpress v4 represents a significant architectural shift, introducing major improvements in performance, stability, and developer experience. This guide focuses on migrating your existing Cypress tests from Synpress v3 to v4.

This guide is specifically for users migrating Cypress tests. If you are using Playwright, refer to the Playwright setup guide.

Key Changes and Improvements

v4’s core change is the browser caching mechanism. Instead of setting up MetaMask for each test, v4 pre-configures a browser instance and reuses it, leading to drastically faster test runs. This also enables full support for Playwright.

Here’s a summary of the most important changes:

  1. Installation: The package name remains the same: @synthetixio/synpress.

  2. Configuration (cypress.config.ts): The setup within your Cypress configuration file has changed. You now use configureSynpressForMetaMask (or configureSynpressForEthereumWalletMock) to integrate Synpress.

  3. Support Files (support/e2e.ts): You now import specific command sets (synpressCommandsForMetaMask or synpressCommandsForEthereumWalletMock) instead of a global import.

  4. Test Structure: The automatic page visit in before() hook, which was a recommended approach, is now replaced with test isolation set to false.

  5. API Changes: Several Cypress commands have been renamed or removed for clarity and consistency. A detailed mapping is provided below.

  6. Test Execution: You use the standard cypress run command, but headed mode is currently required on CI.

  7. Wallet Setup Files: Synpress v4 introduces “wallet setup files” (*.setup.{ts,js,mjs}) to define how the wallet should be pre-configured (importing a seed phrase, adding networks, etc.).

Migration Steps

1. Update Dependencies

Update both cypress and @synthetixio/synpress to their latest versions. Synpress v4 requires Cypress v13+.

pnpm update cypress @synthetixio/synpress --latest
# OR
npm update cypress @synthetixio/synpress --latest
# OR
yarn upgrade cypress @synthetixio/synpress --latest

2. Update cypress.config.ts

Replace the old Synpress/Cypress configuration with the new configureSynpressForMetaMask function. If you were using the Ethereum Wallet Mock, use configureSynpressForEthereumWalletMock instead.

// cypress.config.ts
import { defineConfig } from 'cypress';
import { configureSynpressForMetaMask } from '@synthetixio/synpress/cypress';

export default defineConfig({
  chromeWebSecurity: false, // Keep this if you had it before
  e2e: {
    baseUrl: 'http://localhost:9999', // Adjust if your base URL is different
    specPattern: 'test/cypress/**/*.cy.{js,jsx,ts,tsx}', // Adjust if your spec pattern is different
    supportFile: 'src/cypress/support/e2e.{js,jsx,ts,tsx}', // Adjust if needed
    testIsolation: false, // Important for reusing the cached browser context
    setupNodeEvents(on, config) {
      return configureSynpressForMetaMask(on, config);
    },
  },
});

3. Update Support File (src/cypress/support/e2e.ts)

Import synpressCommandsForMetaMask and remove any previous global imports of Synpress commands. Remove cy.visit('/'), because it’s not needed, thanks to test isolation being set to false.

// src/cypress/support/e2e.ts
import { synpressCommandsForMetaMask } from '@synthetixio/synpress/cypress/support';

// Optional: If you had custom error handling, keep it.
Cypress.on('uncaught:exception', () => {
  return false;
});

synpressCommandsForMetaMask();

// REMOVE the before() hook with cy.visit('/');

If you use the Ethereum Wallet Mock, import the mockEthereum function and call it.

// src/cypress/support/e2e.ts
- import { synpressCommandsForMetaMask } from '@synthetixio/synpress/cypress/support';
+ import { synpressCommandsForEthereumWalletMock, mockEthereum } from '@synthetixio/synpress/cypress/support'

// Optional: If you had custom error handling, keep it.
Cypress.on('uncaught:exception', () => {
  return false;
});

- synpressCommandsForMetaMask();
+ synpressCommandsForEthereumWalletMock();
+ mockEthereum()

4. Update TypeScript Configuration (tsconfig.json)

Ensure your tsconfig.json is configured for Cypress and includes the necessary files:

// tsconfig.json
{
  "compilerOptions": {
    "types": ["cypress"],
    "esModuleInterop": true // Important for compatibility
  },
  "include": ["cypress.config.ts", "test", "src"],
  "files": ["environment.d.ts"]
}

Make sure "strict": true is set in the compilerOptions.

5. Update Test Files

  • Update Commands: Replace v3 commands with their v4 equivalents. See the “Detailed API Changes” section below for a comprehensive mapping.

  • Example:

    // Old v3 test
    describe('My Test Suite', () => {
      before(() => {
        cy.visit('/');
      });
    
      it('should connect to MetaMask', () => {
        cy.acceptMetamaskAccess(); // v3
        cy.get('#someElement').should('be.visible');
      });
    });
    
    // New v4 test
    describe('My Test Suite', () => {
      before(() => {
        cy.visit('/');
      });
    
      it('should connect to MetaMask', () => {
        cy.connectToDapp(); // v4
        cy.get('#someElement').should('be.visible');
      });
    });
    

6. Create Wallet Setup Files (New in v4)

This is a crucial step in Synpress v4. You need to create one or more wallet setup files to define how MetaMask should be pre-configured.

  • Create a Directory: By default, Synpress expects these files in test/wallet-setup. You can change this using the Synpress CLI.

  • File Naming: Files must follow the pattern *.setup.{ts,js,mjs} (e.g., basic.setup.ts, connected.setup.ts).

  • File Content: Use the defineWalletSetup function to define the setup steps.

    // test/wallet-setup/basic.setup.ts
    import { defineWalletSetup } from '@synthetixio/synpress'
    import { MetaMask } from '@synthetixio/synpress/playwright'
    import 'dotenv/config';
    
    const SEED_PHRASE = process.env.SEED_PHRASE;
    const PASSWORD = process.env.WALLET_PASSWORD;
    
    export default defineWalletSetup(PASSWORD, async (context, walletPage) => {
      const extensionId = await getExtensionId(context, 'MetaMask');
      const metamask = new MetaMask(context, walletPage, PASSWORD);
    
      await metamask.importWallet(SEED_PHRASE);
    });
    
    

    This example imports a wallet using a seed phrase. You can customize this to:

    • Import from a private key.
    • Add custom networks.
    • Connect to a dapp (for a “pre-connected” state).
    • Change MetaMask settings.
    • …and anything else you can do within the MetaMask UI.

7. Build the Cache

After creating your wallet setup files, you must build the cache using the Synpress CLI:

npx synpress
# OR
pnpm run synpress # If you have a script named 'synpress' in your package.json

This command will:

  1. Find your *.setup.{ts,js,mjs} files.
  2. Generate a unique hash for each setup function.
  3. Launch a browser instance for each unique setup.
  4. Execute the setup function (installing MetaMask, importing the wallet, etc.).
  5. Save the browser context (the cache) to the .cache-synpress directory.

Important Cache Options:

  • --headless: Run the cache building process in headless mode (no browser window visible). Useful for local development to see what’s happening.
  • --force: Force a rebuild of the cache, even if a cache with the same hash already exists. Use this if you’ve made changes to your setup file or if you suspect the cache is corrupted.
  • --debug: Enables additional logging during the cache building, and preserves logs.
  • [dir]: Specify a custom directory containing the wallet setup files (defaults to test/wallet-setup).

Example (headless, forced rebuild):

npx synpress --headless --force

8. Run Your Tests

Now you can run your Cypress tests as usual. Synpress will automatically use the cached browser context.

npx cypress run --browser chrome --headed # Headed mode is required on CI

Important:

  • Headed Mode on CI: Due to a MetaMask issue, you must run tests in headed mode on CI. Use a virtual display like xvfb-run. See the “Known Issues” page in the Synpress documentation.

Detailed API Changes

This table summarizes the command changes from Synpress v3 to v4:

v3 Commandv4 CommandNotes
cy.acceptMetamaskAccess()cy.connectToDapp()
cy.confirmMetamaskTransaction()cy.confirmTransaction()Now supports optional gasSetting object for fine-grained gas control.
cy.rejectMetamaskTransaction()cy.rejectTransaction()
cy.switchMetamaskNetwork()cy.switchNetwork()
cy.addMetamaskNetwork()cy.addNetwork()
cy.importMetamaskAccount()cy.importWallet()Use for importing with a seed phrase.
cy.createMetamaskAccount()No direct equivalentUse cy.addNewAccount instead.
cy.getMetamaskWalletAddress()cy.getAccountAddress()
cy.switchMetamaskAccount()cy.switchAccount()
cy.getMetamaskBalance()No direct equivalent
cy.importWalletFromPrivateKeyUse for importing from private key.
Not Available in v3cy.emptyAnvilNode()Empties the Anvil node.
Not Available in v3cy.approveNewNetwork()Approves a new network in MetaMask.
Not Available in v3cy.approveSwitchNetwork()Approves switching to a different network in MetaMask.
Not Available in v3cy.rejectNewNetwork()Rejects a new network in MetaMask.
Not Available in v3cy.rejectSwitchNetwork()Rejects switching to a different network in MetaMask.
Not Available in v3cy.deployToken()Deploys a new token contract.
Not Available in v3cy.addNewToken()Adds a new token to MetaMask.
Not Available in v3cy.approveTokenPermission()Approves token spending permission in MetaMask.
Not Available in v3cy.rejectTokenPermission()Rejects token spending permission in MetaMask.
Not Available in v3cy.toggleShowTestNetworks()Toggles the display of test networks in MetaMask.
Not Available in v3cy.toggleDismissSecretRecoveryPhraseReminder()Toggles the dismissal of the secret recovery phrase reminder.
Not Available in v3cy.providePublicEncryptionKey()Provides a public encryption key.
Not Available in v3cy.decrypt()Decrypts a message.
Not Available in v3cy.confirmSignature()Confirms a signature request in MetaMask.
Not Available in v3cy.rejectSignature()Rejects a signature request in MetaMask.
Not Available in v3cy.confirmTransactionAndWaitForMining()Confirms a transaction and waits for it to be mined.
Not Available in v3cy.openTransactionDetails()Opens transaction details in MetaMask.
Not Available in v3cy.closeTransactionDetails()Closes transaction details in MetaMask.
Not Available in v3cy.goBackToHomePage()Goes back to MetaMask homepage.
Not Available in v3cy.openSettings()Opens MetaMask settings page.
Not Available in v3cy.openSidebarMenu()Opens a specific sidebar menu in MetaMask settings.

This migration guide should provide a solid foundation for transitioning your Cypress tests to Synpress v4. Remember to consult the official Synpress documentation and examples for the most up-to-date information and best practices.