This document describes the End-to-End (E2E) testing framework for GasGuard, designed to validate complete gasless transaction workflows and ensure system reliability across all components.
E2E tests simulate real-world scenarios to verify that:
- Gasless transaction flows work from initiation to completion
- All services (API, workers, blockchain) integrate correctly
- Failure scenarios are handled gracefully
- System behavior remains consistent across deployments
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Test Runner │◄──►│ API Service │◄──►│ Blockchain │
│ (Jest) │ │ (NestJS) │ │ (Hardhat) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ PostgreSQL │ │ Redis │ │ Mock Services │
│ (Test DB) │ │ (Queue) │ │ (RPC/Relayer) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Test Framework: Jest with Supertest for HTTP testing
- Blockchain: Hardhat local network for contract interactions
- Database: PostgreSQL with isolated test schemas
- Queue System: Redis for BullMQ worker testing
- Mock Services: Simulated RPC providers and relayers
- Node.js 18+
- Docker (for containerized services)
- PostgreSQL client
- pnpm package manager
# Install dependencies
pnpm install
# Install Hardhat globally (optional)
npm install -g hardhatCreate a .env.test file in apps/api-service/:
# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/gasguard_test
# Redis
REDIS_URL=redis://localhost:6379
# Blockchain
RPC_URL=http://localhost:8545
CHAIN_ID=31337
# Testing
NODE_ENV=test
LOG_LEVEL=error# Run all E2E tests
pnpm run test:e2e
# Run specific test suite
pnpm run test:e2e --testNamePattern="Basic API"
# Run with verbose output
pnpm run test:e2e --verbose
# Run in watch mode
pnpm run test:e2e --watch# Start test environment
docker-compose -f docker-compose.e2e.yml up -d
# Run tests
pnpm run test:e2e
# Clean up
docker-compose -f docker-compose.e2e.yml downTests automatically run in GitHub Actions on:
- Pull requests to
mainanddevelopbranches - Push events to
mainanddevelopbranches
apps/api-service/test/
├── e2e/ # E2E test suites
│ ├── basic-api.e2e-spec.ts
│ ├── gasless-transaction.e2e-spec.ts
│ ├── failure-scenarios.e2e-spec.ts
│ └── contract-interaction.e2e-spec.ts
├── utils/ # Test utilities
│ ├── test-helpers.ts
│ ├── mock-data.ts
│ └── blockchain-setup.ts
└── fixtures/ # Test data fixtures
├── contracts/
└── transactions/
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../../src/app.module';
describe('Gasless Transaction E2E', () => {
let app: INestApplication;
let testHelpers: TestHelpers;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
testHelpers = new TestHelpers();
await testHelpers.setupTestEnvironment();
});
afterAll(async () => {
await testHelpers.cleanup();
await app.close();
});
it('should complete gasless transaction successfully', async () => {
// Arrange
const transactionData = testHelpers.createTransactionRequest();
// Act
const response = await request(app.getHttpServer())
.post('/transactions/gasless')
.send(transactionData)
.expect(201);
// Assert
expect(response.body).toHaveProperty('transactionHash');
expect(response.body.status).toBe('pending');
});
});Key utilities available in test/utils/test-helpers.ts:
createTransactionRequest()- Generate mock transaction datasetupTestDatabase()- Initialize test database schemaresetDatabase()- Clean database between testsdeployTestContract()- Deploy contracts to local blockchainwaitForTransaction()- Wait for blockchain confirmationsmockRpcProvider()- Mock external RPC calls
- Health check endpoints
- Rule validation APIs
- Scanner functionality
- Error handling
- Transaction creation via API
- Queue processing and worker execution
- Signature generation and verification
- Relayer submission
- Transaction confirmation monitoring
- RPC provider timeouts
- Insufficient gas errors
- Signature expiration
- Contract revert scenarios
- Network connectivity issues
- Smart contract deployment
- Method calls and state changes
- Event emission and listening
- Gas estimation accuracy
beforeEach(async () => {
await testHelpers.resetDatabase();
await testHelpers.seedTestData();
});const mockTransaction = {
merchantId: 'test-merchant-123',
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
value: '1000000000000000000', // 1 ETH
data: '0x',
chainId: 1,
gasLimit: '21000'
};# Enable debug logs
LOG_LEVEL=debug pnpm run test:e2e
# Show database queries
DEBUG=typeorm:* pnpm run test:e2eEach test runs in isolation with:
- Fresh database connection
- Clean blockchain state
- Reset mock services
- Isolated Redis instance
- Parallel Execution: Tests run in parallel where possible
- Database Pooling: Connection pooling for faster database operations
- Blockchain Snapshots: Use Hardhat snapshots to reset state quickly
- Caching: Cache expensive setup operations
// Efficient cleanup pattern
afterEach(async () => {
await Promise.all([
testHelpers.resetDatabase(),
testHelpers.resetBlockchain(),
testHelpers.clearRedis()
]);
});E2E tests include security validation:
- Authentication and authorization
- Input validation and sanitization
- Rate limiting effectiveness
- Signature verification
- Access control enforcement
The E2E tests run automatically in CI with:
- Service containers (PostgreSQL, Redis)
- Environment variable configuration
- Test result reporting
- Artifact storage for failed tests
Tests must pass before:
- Pull request merge
- Deployment to staging
- Production release
- Clear Test Names: Use descriptive test names that explain the scenario
- AAA Pattern: Arrange-Act-Assert structure
- Isolation: Each test should be independent
- Realistic Data: Use production-like test data
- Comprehensive Coverage: Test both happy paths and edge cases
- Regular Updates: Keep tests updated with code changes
- Performance Monitoring: Track test execution times
- Flake Detection: Identify and fix flaky tests
- Documentation: Keep this documentation current
Database Connection Failed
# Ensure PostgreSQL is running
docker-compose -f docker-compose.e2e.yml up -d postgresBlockchain Not Responding
# Restart Hardhat node
npx hardhat node --port 8545Tests Timeout
# Increase timeout
jest.setTimeout(30000);Permission Errors
# Fix file permissions
chmod 755 apps/api-service/test/# Run single test file
pnpm run test:e2e apps/api-service/test/e2e/basic-api.e2e-spec.ts
# Run with debug output
DEBUG=* pnpm run test:e2e
# Check service status
docker-compose -f docker-compose.e2e.yml psFor issues with E2E tests, please:
- Check the troubleshooting section above
- Review recent CI build logs
- Create an issue with detailed reproduction steps
- Include relevant test output and logs
Last updated: February 2026