Skip to content

Latest commit

 

History

History
578 lines (436 loc) · 14 KB

File metadata and controls

578 lines (436 loc) · 14 KB

E2E Testing Guide for DApp Studio

Comprehensive guide for running end-to-end tests for the three-layer DApp architecture.

Overview

This guide covers E2E testing for:

  • L1 (Smart Contracts): MyToken with RBAC (AccessControl)
  • L2 (Backend API): Express server with JWT authentication and Web3 signature verification
  • L3 (Frontend): React application with Drizzle state management

Prerequisites

1. Install Dependencies

# Install E2E test dependencies
cd e2e
npm install
npx playwright install

2. Start Ganache (L1 Blockchain)

# Terminal 1: Start Ganache on port 7545 with chain ID 1337
ganache -p 7545 -i 1337

# Or use ganache-cli
ganache-cli -p 7545 -i 1337

Expected Output:

Ganache CLI v7.9.2 (ganache-core: 7.9.2)

Available Accounts
==================
(0) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (1000 ETH)
(1) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (1000 ETH)
...

Listening on 127.0.0.1:7545

3. Deploy Smart Contracts (L1)

# Terminal 2: Deploy contracts to Ganache
cd contracts
npx truffle migrate --network ganache --reset

Expected Output:

Deploying 'MyToken'
-------------------
> transaction hash:    0x...
> contract address:    0x...
> block number:        1
> account:             0x90F79bf6EB2c4f870365E785982E1f101E93b906

Important: Note the contract address for verification.

4. Start Backend API Server (L2)

# Terminal 3: Start backend on port 3001
cd backend
npm run dev

Expected Output:

Server running on http://localhost:3001
Database initialized successfully

Verify Backend Health:

curl http://localhost:3001/api/health
# Expected: {"status":"ok"}

5. Start Frontend Development Server (L3)

# Terminal 4: Start frontend on port 5173
cd frontend
npm run dev

Expected Output:

VITE v5.x.x ready in XXX ms

➜  Local:   http://localhost:5173/
➜  Network: use --host to expose

Running E2E Tests

Quick Start

# Run all E2E tests
cd e2e
npm test

# Or run specific test suites
npm run test:auth          # Authentication tests only
npm run test:rbac          # RBAC permission tests only
npm run test:integration   # Cross-layer integration tests only
npm run test:all           # Auth + RBAC + Integration (recommended)

Interactive Testing (Recommended for Development)

# UI Mode - Visual test runner with watch mode
npm run test:ui

# Headed Mode - See browser interactions
npm run test:headed

# Debug Mode - Step through tests
npm run test:debug

Test Suites Overview

1. Authentication Tests (auth.spec.ts)

Coverage:

  • Web3 wallet connection flow
  • Signature-based authentication (nonce challenge -> sign -> verify)
  • JWT token issuance and validation
  • Nonce replay attack prevention
  • Token expiration (24 hours)
  • Account switching detection
  • Network detection and warnings

Run:

npm run test:auth

Key Scenarios:

  • ✅ User logs in with MetaMask wallet signature
  • ✅ Invalid signature is rejected
  • ✅ Expired nonce is rejected
  • ✅ Nonce replay attack is prevented
  • ✅ User logs out and token is cleared
  • ✅ Protected API endpoint requires valid JWT

2. RBAC Permission Tests (rbac.spec.ts)

Coverage:

  • Admin role verification (DEFAULT_ADMIN_ROLE)
  • Minter role verification (MINTER_ROLE)
  • Permission enforcement on smart contract
  • Role granting by admin
  • Role revoking by admin
  • Access control violations
  • Role-based UI elements

Run:

npm run test:rbac

Key Scenarios:

  • ✅ Admin user has MINTER_ROLE on contract
  • ✅ Regular user cannot mint without MINTER_ROLE
  • ✅ Admin grants MINTER_ROLE to a user
  • ✅ Admin revokes MINTER_ROLE from a user
  • ✅ Non-admin user cannot grant roles
  • ✅ UI disables mint form for users without MINTER_ROLE

3. Cross-Layer Integration Tests (integration.spec.ts)

Coverage:

  • End-to-end token transfers with authentication
  • Real-time balance synchronization (L1 -> L3)
  • Protected API endpoints with JWT (L2)
  • Transaction tracking across all layers
  • Error handling and validation
  • Network mismatch detection
  • Concurrent user authentication

Run:

npm run test:integration

Key Scenarios:

  • ✅ End-to-end token transfer with authentication
  • ✅ Protected API endpoint requires valid JWT
  • ✅ Real-time balance synchronization (3-second polling)
  • ✅ Minting requires both JWT and MINTER_ROLE
  • ✅ Transaction tracking from pending to confirmed
  • ✅ Invalid address format is rejected
  • ✅ Self-transfer is prevented
  • ✅ Network detection and warnings
  • ✅ Multiple concurrent users can authenticate

Deployment Tests (deployment.spec.ts)

Original deployment tests are preserved:

npm run test:deployment

Test Configuration

Playwright Configuration (playwright.config.ts)

{
  testDir: './tests',
  fullyParallel: false,      // Sequential for blockchain state consistency
  workers: 1,                // Single worker to avoid race conditions
  baseURL: 'http://localhost:5173',
  webServer: {
    command: 'cd ../frontend && npm run dev',
    url: 'http://localhost:5173',
    reuseExistingServer: true,
    timeout: 120000
  }
}

Test Accounts

Pre-configured Ganache accounts (deterministic addresses):

TEST_ACCOUNTS = {
  ADMIN:   '0x90F79bf6EB2c4f870365E785982E1f101E93b906', // Account 0 - Contract deployer
  USER1:   '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', // Account 1
  USER2:   '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc', // Account 2
  MINTER:  '0x976EA74026E726554dB657fA54763abd0C3a0aa9', // Account 3
  REGULAR: '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955'  // Account 4
}

Test Helpers

Authentication Helper (auth-helper.ts)

Purpose: Handles Web3 wallet connection and JWT authentication flows.

Key Methods:

const authHelper = createAuthHelper(page);

// Get nonce challenge from backend
await authHelper.getChallenge(walletAddress);

// Sign message with wallet
await authHelper.signMessage(message, walletAddress);

// Verify signature and get JWT token
await authHelper.verifySignature(address, signature, nonce);

// Complete login flow (challenge -> sign -> verify)
await authHelper.login(walletAddress);

// UI interactions
await authHelper.connectWalletUI();
await authHelper.loginViaUI(walletAddress);
await authHelper.logoutViaUI();

// Check auth state
await authHelper.isAuthenticated();
await authHelper.getToken();

// Make authenticated API requests
await authHelper.authenticatedRequest('GET', endpoint, token);

Web3 Helper (web3-helper.ts)

Purpose: Interacts with smart contracts on Ganache.

Key Methods:

const web3 = await createWeb3Helper();

// Get contract instance
const contract = await web3.getContract('MyToken');

// Read contract state
const balance = await contract.methods.balanceOf(address).call();
const totalSupply = await contract.methods.totalSupply().call();
const hasRole = await contract.methods.hasRole(roleHash, address).call();

// Send transactions
await contract.methods.transfer(recipient, amount).send({ from, gas });
await contract.methods.mint(recipient, amount).send({ from, gas });
await contract.methods.grantRole(roleHash, address).send({ from, gas });

// Get transaction receipt
const receipt = await web3.web3.eth.getTransactionReceipt(txHash);

Mock MetaMask Provider

For testing without real MetaMask extension, we inject a mock provider:

await injectMockMetaMask(page, accountAddress);

Features:

  • Simulates window.ethereum object
  • Auto-connects specified account
  • Mocks signature requests
  • Simulates account/network switching

Limitations:

  • Not suitable for production testing
  • Does not validate actual cryptographic signatures
  • For real MetaMask testing, use Synpress or dappwright

Troubleshooting

1. Tests Timeout

Symptom: Tests fail with timeout errors.

Solutions:

# Check all services are running
curl http://localhost:7545  # Ganache
curl http://localhost:3001/api/health  # Backend
curl http://localhost:5173  # Frontend

# Increase timeout in individual tests
test('slow test', async ({ page }) => {
  test.setTimeout(60000); // 60 seconds
});

2. Contract Not Deployed

Symptom: Cannot read property 'address' of undefined

Solution:

# Redeploy contracts
cd contracts
npx truffle migrate --network ganache --reset

# Verify artifact exists
ls -la build/contracts/MyToken.json

3. Backend Not Responding

Symptom: 401/500 errors from API endpoints

Solution:

# Check backend logs
cd backend
npm run dev

# Verify database initialized
# Check for "Database initialized successfully" in logs

# Test auth endpoint directly
curl http://localhost:3001/api/auth/challenge?address=0x90F79bf6EB2c4f870365E785982E1f101E93b906

4. Frontend Not Loading

Symptom: Navigation timeout errors

Solution:

# Restart frontend
cd frontend
rm -rf node_modules/.vite  # Clear Vite cache
npm run dev

# Check browser console for errors
# Open http://localhost:5173 manually

5. Network Mismatch

Symptom: "Wrong network" warnings in tests

Solution:

# Ensure Ganache is running on correct port/chain ID
ganache -p 7545 -i 1337

# Verify chain ID in tests matches Ganache
# Expected: 0x539 (1337 in decimal)

6. Nonce Already Used

Symptom: "Nonce expired or already used" errors

Solution:

# Reset backend database
cd backend
rm -rf data/  # Remove PGlite database
npm run dev   # Restart to reinitialize

# Or wait 5 minutes for nonce expiration

Viewing Test Reports

# After tests complete
npm run report

Opens interactive HTML report with:

  • Test results (pass/fail)
  • Execution timeline
  • Screenshots (on failure)
  • Video recordings (if enabled)
  • Trace files for debugging

CI/CD Integration

GitHub Actions Example

name: E2E Tests

on: [push, pull_request]

jobs:
  e2e-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: |
          npm install
          cd e2e && npm install
          npx playwright install --with-deps

      - name: Start Ganache
        run: npx ganache -p 7545 -i 1337 &

      - name: Deploy contracts
        run: cd contracts && npx truffle migrate --network ganache

      - name: Start backend
        run: cd backend && npm run dev &

      - name: Wait for services
        run: sleep 10

      - name: Run E2E tests
        run: cd e2e && npm run test:all

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: playwright-report
          path: e2e/playwright-report/

Best Practices

1. State Isolation

  • Tests run sequentially (workers: 1) to maintain blockchain state consistency
  • Each test suite resets state when needed
  • Use Ganache snapshots for faster state reset (advanced)

2. Waiting Strategies

// ❌ Bad - Fixed delays
await page.waitForTimeout(5000);

// ✅ Good - Wait for specific conditions
await expect(element).toBeVisible({ timeout: 5000 });
await page.waitForSelector('[data-testid="balance"]');
await page.waitForLoadState('networkidle');

3. Selector Hierarchy

  1. data-testid attributes (most stable)
  2. Semantic selectors (button, input)
  3. Text content (:has-text("Login"))
  4. CSS classes (least stable)

4. Error Messages

Always verify error messages are user-friendly:

const error = await errorElement.textContent();
expect(error).toMatch(/invalid address|address format/i);

Next Steps

Enhancements

  1. Real MetaMask Testing

    • Integrate Synpress
    • Test actual signature flows
    • Verify MetaMask UI interactions
  2. Visual Regression Testing

    • Add screenshot comparisons
    • Use @playwright/test visual comparison
  3. Performance Testing

    • Measure transaction confirmation times
    • Track API response times
    • Monitor frontend rendering performance
  4. Accessibility Testing

    • Integrate axe-core
    • Verify WCAG compliance
    • Test keyboard navigation
  5. Multi-Browser Testing

    • Enable Firefox project in playwright.config.ts
    • Test Safari/WebKit
    • Verify mobile viewports

Resources

Support

For issues or questions:

  1. Check existing tests for examples
  2. Review helper functions in e2e/tests/helpers/
  3. Consult BDD scenarios in .specify/specs/e2e-test.feature
  4. Check Playwright documentation

Test Coverage Summary

Layer Component Coverage
L1 Smart Contract RBAC ✅ Role verification, granting, revoking
L1 Token Operations ✅ Transfer, mint, balance queries
L2 Authentication ✅ Challenge, signature verification, JWT
L2 Protected Endpoints ✅ Token validation, 401 handling
L3 Wallet Connection ✅ MetaMask integration, account switching
L3 UI State Management ✅ Balance updates, transaction tracking
L1+L2+L3 End-to-End Flows ✅ Login -> Transfer -> Confirmation
Security Input Validation ✅ Address format, self-transfer prevention
Security Nonce Replay ✅ Single-use nonces, expiration
Security Network Detection ✅ Wrong network warnings

Total Test Scenarios: 30+ BDD scenarios Total Test Files: 4 spec files + 2 helpers Estimated Execution Time: 2-5 minutes (depending on blockchain speed)