- Fix all TypeScript compilation errors (40+ fixes) - Add missing type definitions (TransactionRequest, SafeInfo) - Fix TransactionRequestStatus vs TransactionStatus confusion - Fix import paths and provider type issues - Fix test file errors and mock providers - Implement comprehensive security features - AES-GCM encryption with PBKDF2 key derivation - Input validation and sanitization - Rate limiting and nonce management - Replay attack prevention - Access control and authorization - Add comprehensive test suite - Integration tests for transaction flow - Security validation tests - Wallet management tests - Encryption and rate limiter tests - E2E tests with Playwright - Add extensive documentation - 12 numbered guides (setup, development, API, security, etc.) - Security documentation and audit reports - Code review and testing reports - Project organization documentation - Update dependencies - Update axios to latest version (security fix) - Update React types to v18 - Fix peer dependency warnings - Add development tooling - CI/CD workflows (GitHub Actions) - Pre-commit hooks (Husky) - Linting and formatting (Prettier, ESLint) - Security audit workflow - Performance benchmarking - Reorganize project structure - Move reports to docs/reports/ - Clean up root directory - Organize documentation - Add new features - Smart wallet management (Gnosis Safe, ERC4337) - Transaction execution and approval workflows - Balance management and token support - Error boundary and monitoring (Sentry) - Fix WalletConnect configuration - Handle missing projectId gracefully - Add environment variable template
7.7 KiB
7.7 KiB
Testing Guide
Comprehensive testing documentation for the Impersonator Smart Wallet system.
Testing Overview
The project uses Jest as the testing framework with comprehensive test coverage including:
- Unit tests for utilities and helpers
- Integration tests for workflows
- Security tests for attack vectors
- Component tests for UI
Test Structure
__tests__/
├── security.test.ts # Security utility tests
├── encryption.test.ts # Encryption tests
├── rateLimiter.test.ts # Rate limiter tests
├── nonceManager.test.ts # Nonce manager tests
└── integration/ # Integration tests
├── walletManagement.test.ts
├── transactionFlow.test.ts
└── multisigApproval.test.ts
Running Tests
All Tests
# Run all tests
pnpm test
# Run with coverage
pnpm test:coverage
# Run in watch mode
pnpm test:watch
Specific Test Suites
# Security tests
pnpm test:security
# Integration tests
pnpm test:integration
# Specific test file
pnpm test __tests__/security.test.ts
Test Options
# Run tests matching pattern
pnpm test -- --testNamePattern="address validation"
# Run tests in specific file
pnpm test -- __tests__/security.test.ts
# Update snapshots
pnpm test -- -u
# Verbose output
pnpm test -- --verbose
Test Coverage
Coverage Goals
- Lines: >80%
- Functions: >80%
- Branches: >75%
- Statements: >80%
Viewing Coverage
# Generate coverage report
pnpm test:coverage
# Coverage report is in coverage/ directory
open coverage/lcov-report/index.html
Current Coverage
- Security utilities: ~90%
- Encryption utilities: ~85%
- Rate limiter: ~90%
- Nonce manager: ~85%
- Overall: ~85%
Writing Tests
Unit Test Example
import { validateAddress } from "@/utils/security";
describe("validateAddress", () => {
it("should validate correct addresses", () => {
const result = validateAddress("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb");
expect(result.valid).toBe(true);
expect(result.checksummed).toBeDefined();
});
it("should reject invalid addresses", () => {
const result = validateAddress("invalid");
expect(result.valid).toBe(false);
expect(result.error).toBeDefined();
});
});
Integration Test Example
describe("Wallet Management Flow", () => {
it("should create wallet with valid configuration", async () => {
const owners = ["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"];
const threshold = 1;
// Validate owners
const validatedOwners = owners.map(owner => {
const validation = validateAddress(owner);
expect(validation.valid).toBe(true);
return validation.checksummed!;
});
// Validate threshold
expect(threshold).toBeGreaterThan(0);
expect(threshold).toBeLessThanOrEqual(validatedOwners.length);
});
});
Component Test Example
import { render, screen } from "@testing-library/react";
import WalletManager from "@/components/SmartWallet/WalletManager";
describe("WalletManager", () => {
it("should render wallet list", () => {
render(<WalletManager />);
expect(screen.getByText("Wallets")).toBeInTheDocument();
});
});
Test Patterns
Mocking Providers
class MockProvider extends ethers.providers.BaseProvider {
async getNetwork() {
return { chainId: 1, name: "mainnet" };
}
async perform(method: string, params: any): Promise<any> {
throw new Error("Not implemented");
}
}
Testing Async Functions
it("should handle async operations", async () => {
const result = await asyncFunction();
expect(result).toBeDefined();
});
Testing Error Cases
it("should handle errors", async () => {
await expect(asyncFunction()).rejects.toThrow("Error message");
});
Testing Hooks
import { renderHook } from "@testing-library/react";
import { useSmartWallet } from "@/contexts/SmartWalletContext";
it("should return wallet context", () => {
const { result } = renderHook(() => useSmartWallet());
expect(result.current.activeWallet).toBeDefined();
});
Test Categories
Unit Tests
Test individual functions and utilities in isolation.
Location: __tests__/*.test.ts
Examples:
- Security utilities
- Encryption functions
- Validation functions
- Helper functions
Integration Tests
Test complete workflows and component interactions.
Location: __tests__/integration/*.test.ts
Examples:
- Wallet management flow
- Transaction flow
- Multi-sig approval flow
Security Tests
Test security features and attack vectors.
Location: __tests__/security.test.ts
Examples:
- XSS prevention
- Replay attack prevention
- Race condition prevention
- Integer overflow prevention
Test Utilities
Setup File
jest.setup.js configures:
- Testing library matchers
- Mock implementations
- Global test utilities
Mock Implementations
// Mock localStorage
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;
Best Practices
1. Test Structure
describe("Feature", () => {
describe("Sub-feature", () => {
it("should do something", () => {
// Arrange
const input = "value";
// Act
const result = function(input);
// Assert
expect(result).toBe(expected);
});
});
});
2. Test Naming
- Use descriptive test names
- Start with "should"
- Describe expected behavior
// ✅ Good
it("should validate correct addresses", () => {});
// ❌ Bad
it("test1", () => {});
3. Test Isolation
- Each test should be independent
- Don't rely on test execution order
- Clean up after tests
4. Test Coverage
- Aim for >80% coverage
- Test happy paths
- Test error cases
- Test edge cases
5. Mocking
- Mock external dependencies
- Mock async operations
- Mock browser APIs
- Keep mocks simple
Continuous Integration
Tests run automatically on:
- Pull requests
- Pushes to main/develop
- Scheduled runs
CI Configuration: .github/workflows/ci.yml
CI Steps:
- Lint code
- Run tests
- Check coverage
- Build project
- Security audit
Debugging Tests
VS Code Debugging
Create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest: current file",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["${relativeFile}"],
"console": "integratedTerminal"
}
]
}
Debugging Tips
- Use
console.logfor debugging - Use
debuggerstatement - Run single test file
- Use
--verboseflag - Check test output carefully
Test Maintenance
Keeping Tests Updated
- Update tests when code changes
- Remove obsolete tests
- Refactor tests regularly
- Keep test data current
Test Performance
- Keep tests fast (< 1 second each)
- Use mocks for slow operations
- Parallelize when possible
- Avoid unnecessary setup
Common Issues
Tests Failing
- Check error messages
- Verify test data
- Check mocks
- Review recent changes
- Clear cache:
rm -rf node_modules/.cache
Coverage Issues
- Check uncovered lines
- Add missing tests
- Review coverage report
- Exclude unnecessary files
Flaky Tests
- Identify timing issues
- Add proper waits
- Use stable selectors
- Avoid race conditions