> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synpress.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide - v3 to v4

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.

<Warning>
  This guide is specifically for users migrating Cypress tests.  If you are using Playwright, refer to the [Playwright setup guide](./setup-playwright).
</Warning>

## 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+.

```bash theme={null}
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.

```typescript theme={null}
// 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`.

```typescript theme={null}
// 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.

```diff theme={null}
// 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:

```json theme={null}
// 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:**

  ```typescript theme={null}
  // 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.

  ```typescript theme={null}
  // 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:

```bash theme={null}
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):

```bash theme={null}
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.

```bash theme={null}
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 Command                        | v4 Command                                       | Notes                                                                   |
| --------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------- |
| `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 equivalent*                           | Use `cy.addNewAccount` instead.                                         |
| `cy.getMetamaskWalletAddress()`   | `cy.getAccountAddress()`                         |                                                                         |
| `cy.switchMetamaskAccount()`      | `cy.switchAccount()`                             |                                                                         |
| `cy.getMetamaskBalance()`         | *No direct equivalent*                           |                                                                         |
|                                   | `cy.importWalletFromPrivateKey`                  | Use for importing from private key.                                     |
| *Not Available in v3*             | `cy.emptyAnvilNode()`                            | Empties the Anvil node.                                                 |
| *Not Available in v3*             | `cy.approveNewNetwork()`                         | Approves a new network in MetaMask.                                     |
| *Not Available in v3*             | `cy.approveSwitchNetwork()`                      | Approves switching to a different network in MetaMask.                  |
| *Not Available in v3*             | `cy.rejectNewNetwork()`                          | Rejects a new network in MetaMask.                                      |
| *Not Available in v3*             | `cy.rejectSwitchNetwork()`                       | Rejects switching to a different network in MetaMask.                   |
| *Not Available in v3*             | `cy.deployToken()`                               | Deploys a new token contract.                                           |
| *Not Available in v3*             | `cy.addNewToken()`                               | Adds a new token to MetaMask.                                           |
| *Not Available in v3*             | `cy.approveTokenPermission()`                    | Approves token spending permission in MetaMask.                         |
| *Not Available in v3*             | `cy.rejectTokenPermission()`                     | Rejects token spending permission in MetaMask.                          |
| *Not Available in v3*             | `cy.toggleShowTestNetworks()`                    | Toggles the display of test networks in MetaMask.                       |
| *Not Available in v3*             | `cy.toggleDismissSecretRecoveryPhraseReminder()` | Toggles the dismissal of the secret recovery phrase reminder.           |
| *Not Available in v3*             | `cy.providePublicEncryptionKey()`                | Provides a public encryption key.                                       |
| *Not Available in v3*             | `cy.decrypt()`                                   | Decrypts a message.                                                     |
| *Not Available in v3*             | `cy.confirmSignature()`                          | Confirms a signature request in MetaMask.                               |
| *Not Available in v3*             | `cy.rejectSignature()`                           | Rejects a signature request in MetaMask.                                |
| *Not Available in v3*             | `cy.confirmTransactionAndWaitForMining()`        | Confirms a transaction and waits for it to be mined.                    |
| *Not Available in v3*             | `cy.openTransactionDetails()`                    | Opens transaction details in MetaMask.                                  |
| *Not Available in v3*             | `cy.closeTransactionDetails()`                   | Closes transaction details in MetaMask.                                 |
| *Not Available in v3*             | `cy.goBackToHomePage()`                          | Goes back to MetaMask homepage.                                         |
| *Not Available in v3*             | `cy.openSettings()`                              | Opens MetaMask settings page.                                           |
| *Not Available in v3*             | `cy.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.
