End-to-End Testing Strategy
Comprehensive E2E testing strategy for FishingLog platform covering backend API, web application, and React Native mobile app.
Overview
This document outlines the recommended E2E testing approach for the FishingLog platform, including:
- Backend API E2E testing
- Web Application E2E testing (React/Next.js)
- Mobile Application E2E testing (React Native)
- Cross-platform flow testing (e.g., payment flows)
Testing Pyramid
/\
/ \ E2E Tests (10%)
/----\ - Critical user journeys
/ \ - Payment flows
/--------\ - Cross-platform flows
/ \
/------------\ Integration Tests (30%)
/ \ - API endpoint testing
/----------------\ - Service integration
\----------------/ Unit Tests (60%)
- Business logic
- Utilities
- Helpers
Recommended Tools
1. Backend API E2E Testing
Primary Tool: xUnit/NUnit + TestContainers
- xUnit - Standard .NET testing framework
- TestContainers - Spin up real PostgreSQL containers for testing
- WebApplicationFactory - ASP.NET Core integration testing
- Moq - Mocking external services (Stripe, AWS Cognito, etc.)
Why:
- Native .NET integration
- Can test real database interactions
- Fast execution
- Easy CI/CD integration
2. Web Application E2E Testing
Primary Tool: Playwright
- Playwright - Modern browser automation
- Supports Chromium, Firefox, WebKit
- Built-in test runner and reporting
- Can test API endpoints too
- Excellent debugging tools
Why:
- Fast and reliable
- Multi-browser support
- Great developer experience
- Can test both UI and API
- Built-in video/screenshot on failure
Alternative: Cypress (if team prefers)
3. Mobile Application E2E Testing
Primary Tool: Detox
- Detox - React Native E2E testing framework
- Runs on real devices/simulators
- Fast execution
- Great for React Native apps
Why:
- Built specifically for React Native
- Fast and reliable
- Good CI/CD integration
- Supports both iOS and Android
Alternative: Maestro (if you prefer a more visual approach)
4. API Contract Testing
Tool: Pact or Postman/Newman
- Pact - Consumer-driven contract testing
- Postman/Newman - API collection testing
Why:
- Ensures API contracts between frontend and backend
- Catches breaking changes early
- Can be run in CI/CD
Test Infrastructure Setup
Backend Test Project Structure
FishingLog.API.Tests/
├── Integration/
│ ├── Controllers/
│ │ ├── AuthControllerTests.cs
│ │ ├── FishingLogControllerTests.cs
│ │ ├── TournamentControllerTests.cs
│ │ └── PaymentFlowTests.cs
│ ├── Services/
│ │ ├── StripeServiceTests.cs
│ │ └── ContentModerationServiceTests.cs
│ └── Database/
│ └── DbContextTests.cs
├── E2E/
│ ├── UserJourneyTests.cs
│ ├── PaymentFlowTests.cs
│ └── SocialFlowTests.cs
├── Helpers/
│ ├── TestWebApplicationFactory.cs
│ ├── TestDataBuilder.cs
│ └── AuthHelper.cs
└── FishingLog.API.Tests.csproj
Web App Test Structure
web-app/
├── e2e/
│ ├── tests/
│ │ ├── auth.spec.ts
│ │ ├── fishing-log.spec.ts
│ │ ├── tournament.spec.ts
│ │ ├── payment.spec.ts
│ │ └── social.spec.ts
│ ├── fixtures/
│ │ ├── test-users.ts
│ │ └── test-data.ts
│ ├── helpers/
│ │ ├── auth.ts
│ │ └── api.ts
│ └── playwright.config.ts
Mobile App Test Structure
mobile-app/
├── e2e/
│ ├── tests/
│ │ ├── auth.e2e.ts
│ │ ├── fishing-log.e2e.ts
│ │ ├── tournament.e2e.ts
│ │ └── payment.e2e.ts
│ ├── helpers/
│ │ └── auth.ts
│ └── .detoxrc.js
Critical Test Scenarios
1. Authentication Flows
Backend:
- ✅ User registration via Cognito
- ✅ User login
- ✅ Token refresh
- ✅ Auto user creation on first login
- ✅ JWT token validation
- ✅ Unauthorized access handling
Web App:
- ✅ Login page → Dashboard
- ✅ Protected route redirect
- ✅ Token expiration handling
- ✅ Logout flow
Mobile App:
- ✅ Login screen → Home screen
- ✅ Biometric authentication (if implemented)
- ✅ Token refresh in background
- ✅ Offline authentication state
2. Payment Flows (Stripe Integration)
Critical Path:
- User selects tournament/charter
- User clicks register/book
- Payment intent created
- Stripe payment sheet shown
- User completes payment
- Webhook received and processed
- Registration/booking confirmed
Test Scenarios:
- ✅ Successful payment flow
- ✅ Payment failure handling
- ✅ Webhook processing
- ✅ Payment intent creation
- ✅ Refund flow (admin)
- ✅ Payment retry logic
Tools Needed:
- Stripe test mode
- Stripe webhook testing tool
- Mock Stripe responses for edge cases
3. Fishing Log Flows
User Journey:
- User creates fishing log entry
- Adds catch details
- Uploads photos
- Sets privacy settings
- Shares to circles (if applicable)
- Entry appears in feed
Test Scenarios:
- ✅ Create log entry
- ✅ Add catch with species, length, weight
- ✅ Photo upload
- ✅ Privacy settings (Public/Friends/Private/Circle)
- ✅ Circle auto-sharing
- ✅ Edit/delete entry
- ✅ View entries list
- ✅ Filter by date/species/location
4. Social Features
User Journey:
- User creates post
- Post appears in feed
- Other users like/comment
- Notifications sent
- Content moderation applied
Test Scenarios:
- ✅ Create post
- ✅ Like/unlike post
- ✅ Comment on post
- ✅ Share to circles
- ✅ Content moderation (AI)
- ✅ Report content
- ✅ Privacy controls
5. Tournament Flows
User Journey:
- Browse tournaments
- View tournament details
- Register (with payment if required)
- Submit catches
- View leaderboard
- View results
Test Scenarios:
- ✅ Tournament listing
- ✅ Tournament registration
- ✅ Payment for registration
- ✅ Catch submission
- ✅ Leaderboard updates
- ✅ Results display
6. Circle (Community) Flows
User Journey:
- Discover/create circle
- Join circle (or apply)
- Share content to circle
- View circle feed
- Manage circle (if admin)
Test Scenarios:
- ✅ Circle discovery
- ✅ Circle creation
- ✅ Join/apply to circle
- ✅ Application approval/rejection
- ✅ Rule-based auto-sharing
- ✅ Contributor rankings
- ✅ Member management
Test Data Management
Test Users
Create dedicated test users in Cognito:
# Admin user
aws cognito-idp admin-create-user \
--user-pool-id us-east-2_TZtGx1T3X \
--username admin-test@fishinglog.test \
--user-attributes Name=email,Value=admin-test@fishinglog.test \
--temporary-password TempPass123! \
--message-action SUPPRESS
# Regular user
aws cognito-idp admin-create-user \
--user-pool-id us-east-2_TZtGx1T3X \
--username user-test@fishinglog.test \
--user-attributes Name=email,Value=user-test@fishinglog.test \
--temporary-password TempPass123! \
--message-action SUPPRESS
Test Database
Use TestContainers to spin up isolated PostgreSQL instances:
public class TestWebApplicationFactory : WebApplicationFactory<Program>
{
private readonly PostgreSQLContainer _postgres = new PostgreSQLBuilder()
.WithImage("postgres:16")
.WithDatabase("fishinglog_test")
.WithUsername("test_user")
.WithPassword("test_password")
.Build();
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Replace database connection
var descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
if (descriptor != null) services.Remove(descriptor);
services.AddDbContext<AppDbContext>(options =>
{
options.UseNpgsql(_postgres.GetConnectionString());
});
});
}
}
Test Data Builders
Create test data builders for consistent test data:
public class FishingLogEntryBuilder
{
private FishingLogEntry _entry = new();
public FishingLogEntryBuilder WithUser(User user)
{
_entry.UserId = user.Id;
return this;
}
public FishingLogEntryBuilder WithLocation(double lat, double lon)
{
_entry.Latitude = lat;
_entry.Longitude = lon;
return this;
}
public FishingLogEntry Build() => _entry;
}
Authentication in Tests
Backend Tests
Mock JWT tokens or use test authentication:
public class AuthHelper
{
public static string GenerateTestToken(string userId, string email)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("test-secret-key");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("sub", userId),
new Claim("email", email),
new Claim("cognito:username", email)
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
Frontend Tests
Use test credentials or mock authentication:
// Playwright auth helper
export async function loginAsTestUser(page: Page) {
await page.goto('/login');
await page.fill('[name="username"]', 'test-user@fishinglog.test');
await page.fill('[name="password"]', 'TestPassword123!');
await page.click('button[type="submit"]');
await page.waitForURL('/dashboard');
// Save auth state
await page.context().storageState({ path: 'auth-state.json' });
}
Stripe Testing
Test Mode
Always use Stripe test mode in E2E tests:
// appsettings.Test.json
{
"Stripe": {
"SecretKey": "sk_test_...",
"PublishableKey": "pk_test_...",
"WebhookSecret": "whsec_test_..."
}
}
Test Cards
Use Stripe test cards:
- Success:
4242 4242 4242 4242 - Decline:
4000 0000 0000 0002 - 3D Secure:
4000 0027 6000 3184
Webhook Testing
Use Stripe CLI for local webhook testing:
stripe listen --forward-to http://localhost:5000/api/stripe/webhook
CI/CD Integration
GitHub Actions Example
name: E2E Tests
on:
pull_request:
branches: [main, staging]
push:
branches: [main, staging]
jobs:
backend-e2e:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
POSTGRES_DB: fishinglog_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '9.0.x'
- run: dotnet test FishingLog.API.Tests/FishingLog.API.Tests.csproj
web-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: |
cd web-app
npm ci
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run E2E tests
run: |
cd web-app
npm run test:e2e
env:
API_URL: http://localhost:5000
COGNITO_USER_POOL_ID: ${{ secrets.COGNITO_USER_POOL_ID }}
COGNITO_CLIENT_ID: ${{ secrets.COGNITO_CLIENT_ID }}
mobile-e2e:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: |
cd mobile-app
npm ci
- name: Build app
run: |
cd mobile-app
npm run build:ios
- name: Run Detox tests
run: |
cd mobile-app
npm run test:e2e:ios
Test Environment Setup
Required Services
- PostgreSQL - Test database (via TestContainers or Docker)
- AWS Cognito - Test user pool (or mock)
- Stripe - Test mode API keys
- Test Users - Pre-created in Cognito
Environment Variables
# Backend
ASPNETCORE_ENVIRONMENT=Test
ConnectionStrings__DefaultConnection=Host=localhost;Database=fishinglog_test;...
Stripe__SecretKey=sk_test_...
Stripe__PublishableKey=pk_test_...
AWS__Cognito__UserPoolId=us-east-2_TZtGx1T3X
AWS__Cognito__ClientId=6i1opt39o2n5h5ihq471l1ev07
# Frontend
NEXT_PUBLIC_API_URL=http://localhost:5000
NEXT_PUBLIC_COGNITO_USER_POOL_ID=us-east-2_TZtGx1T3X
NEXT_PUBLIC_COGNITO_CLIENT_ID=6i1opt39o2n5h5ihq471l1ev07
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
Best Practices
1. Test Isolation
- Each test should be independent
- Clean up test data after each test
- Use transactions that rollback
- Don't rely on test execution order
2. Test Data
- Use factories/builders for test data
- Create minimal data needed for test
- Use realistic but anonymized data
- Clean up after tests
3. Flakiness Prevention
- Use explicit waits, not fixed delays
- Wait for network requests to complete
- Use stable selectors (data-testid)
- Retry flaky tests with exponential backoff
4. Performance
- Run tests in parallel when possible
- Use test databases, not production
- Mock external services (Stripe, AWS)
- Cache authentication tokens
5. Debugging
- Take screenshots/videos on failure
- Log test steps
- Use test data IDs in logs
- Provide clear error messages
Test Coverage Goals
Critical Paths (100% coverage)
- ✅ Authentication flows
- ✅ Payment flows
- ✅ User registration/login
- ✅ Core CRUD operations
Important Features (80% coverage)
- ✅ Social features
- ✅ Tournament flows
- ✅ Circle features
- ✅ Content moderation
Nice to Have (60% coverage)
- ✅ Advanced filtering
- ✅ Search functionality
- ✅ Analytics/reporting
Monitoring & Reporting
Test Results
- Backend: xUnit test results → Azure DevOps/GitHub Actions
- Web: Playwright HTML report
- Mobile: Detox test results
Test Metrics
Track:
- Test execution time
- Pass/fail rates
- Flaky test detection
- Coverage trends
Alerts
- Failed E2E tests → Slack/Email
- Flaky test detection
- Coverage drops below threshold
Getting Started
Phase 1: Backend E2E (Week 1-2)
- Create
FishingLog.API.Testsproject - Set up TestContainers
- Create test infrastructure helpers
- Write authentication flow tests
- Write payment flow tests
Phase 2: Web App E2E (Week 3-4)
- Install Playwright
- Set up test configuration
- Create auth helpers
- Write critical user journey tests
- Integrate with CI/CD
Phase 3: Mobile App E2E (Week 5-6)
- Install Detox
- Configure iOS/Android simulators
- Create test helpers
- Write critical flow tests
- Set up CI/CD for mobile
Phase 4: Cross-Platform Tests (Week 7+)
- Test payment flows end-to-end
- Test social features across platforms
- Test data synchronization
- Performance testing
Resources
Next Steps
- ✅ Review and approve this strategy
- ⬜ Set up backend test project
- ⬜ Set up web app E2E tests
- ⬜ Set up mobile app E2E tests
- ⬜ Create test data management system
- ⬜ Integrate with CI/CD
- ⬜ Write critical path tests
- ⬜ Expand test coverage
Last Updated: December 2025
Status: Strategy Document - Ready for Implementation