Testing with Mnemonic Wallet

The Mnemonic wallet provider enables automated testing of dApps by allowing direct entry of account mnemonics. While this removes the security features of traditional wallets that require explicit user interaction, it provides a way to automate end-to-end testing of your application.

Overview

Most supported wallets are designed for production use and require manual user interaction for security. The Mnemonic provider removes these security constraints, making it ideal for:

  • End-to-end (E2E) testing

  • CI/CD pipelines

  • Test automation

Configuration

Add the Mnemonic provider to your WalletManager configuration:

import { WalletManager, WalletId } from '@txnlab/use-wallet'

const manager = new WalletManager({
  wallets: [
    // Production wallets...
    WalletId.PERA,
    WalletId.DEFLY,
    
    // Test wallet
    {
      id: WalletId.MNEMONIC,
      options: {
        // Optional: persist mnemonic to localStorage
        persistToStorage: false
      }
    }
  ],
  defaultNetwork: 'testnet'
})

Session Persistence

By default, the Mnemonic provider does not persist sessions to localStorage. This means:

  • The mnemonic must be re-entered after page reloads

  • The wallet disconnects when closing/reloading the page

  • Sessions cannot be resumed automatically

To match the behavior of production wallets in tests, enable persistence:

{
  id: WalletId.MNEMONIC,
  options: {
    persistToStorage: true
  }
}

End-to-End Testing

The Mnemonic provider enables automated E2E testing with frameworks like Playwright, Cypress, or Selenium. It enables automated wallet connections and transaction signing without requiring manual user interaction.

Example Test

Here's a basic example using Playwright that demonstrates connecting to the wallet and verifying the connection:

import { test, expect } from '@playwright/test'

test('wallet connection flow', async ({ page }) => {
  // Navigate to app
  await page.goto('/')
  
  // Mock Algod responses
  await mockAlgodResponses(page)
  
  // Handle mnemonic prompt
  page.on('dialog', (dialog) => dialog.accept(
    // !! WARNING !!
    // THIS ACCOUNT IS COMPROMISED
    // Use for testing only!
    // !! WARNING !!
    'sugar bronze century excuse animal jacket what rail biology symbol want craft annual soul increase question army win execute slim girl chief exhaust abstract wink'
  ))
  
  // Verify Mnemonic wallet is available
  await expect(page.getByRole('heading', { name: 'Mnemonic' })).toBeVisible()
  
  // Connect to wallet
  await page
    .locator('.wallet-group', {
      has: page.locator('h4', { hasText: 'Mnemonic' })
    })
    .getByRole('button', { name: 'Connect' })
    .click()
    
  // Verify connection succeeded
  await expect(page.getByRole('heading', { name: 'Mnemonic [active]' })).toBeVisible()
  
  // Verify correct account is connected
  await expect(page.getByRole('combobox')).toHaveValue(
    '3F3FPW6ZQQYD6JDC7FKKQHNGVVUIBIZOUI5WPSJEHBRABZDRN6LOTBMFEY'
  )
})

Mocking Node Responses

To create reliable and predictable tests, it's recommended to mock responses from the Algorand node. This prevents tests from failing due to network issues or rate limits, and allows testing specific scenarios:

async function mockAlgodResponses(page: Page) {
  // Mock transaction parameters
  await page.route('**/v2/transactions/params', (route) => {
    route.fulfill({
      status: 200,
      body: JSON.stringify({
        'last-round': 1000,
        'consensus-version': 'test-1.0',
        'min-fee': 1000,
        'genesis-hash': 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=',
        'genesis-id': 'testnet-v1.0'
      })
    })
  })

  // Mock transaction submission
  await page.route('**/v2/transactions', (route) => {
    route.fulfill({
      status: 200,
      body: JSON.stringify({ txId: 'TEST_TX_ID' })
    })
  })
}

Best Practices

When using the Mnemonic provider for testing:

  • Test Account Security: Generate dedicated test accounts that will never be used in production. Consider these accounts compromised as their mnemonics are stored in test files.

  • Mock API Responses: Mock responses from the Algorand node to:

    • Prevent overwhelming API providers with test requests

    • Create predictable test scenarios

    • Test error handling

    • Speed up test execution

  • Test Organization: Structure tests to cover different wallet operations:

    • Connection/disconnection flows

    • Account switching

    • Transaction signing

    • Error handling

    • Network switching

  • CI/CD Integration: The Mnemonic provider works well in CI/CD pipelines since it doesn't require user interaction. Consider:

    • Storing test mnemonics securely (e.g., in CI environment variables)

    • Running tests against LocalNet (sandbox) or a private network

    • Including wallet tests in your automated test suite

For complete testing examples, including mocking strategies and common test scenarios, see the E2E test examples in the repository.

Last updated