Skip to main content

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

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:

  1. User selects tournament/charter
  2. User clicks register/book
  3. Payment intent created
  4. Stripe payment sheet shown
  5. User completes payment
  6. Webhook received and processed
  7. 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:

  1. User creates fishing log entry
  2. Adds catch details
  3. Uploads photos
  4. Sets privacy settings
  5. Shares to circles (if applicable)
  6. 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:

  1. User creates post
  2. Post appears in feed
  3. Other users like/comment
  4. Notifications sent
  5. 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:

  1. Browse tournaments
  2. View tournament details
  3. Register (with payment if required)
  4. Submit catches
  5. View leaderboard
  6. View results

Test Scenarios:

  • ✅ Tournament listing
  • ✅ Tournament registration
  • ✅ Payment for registration
  • ✅ Catch submission
  • ✅ Leaderboard updates
  • ✅ Results display

6. Circle (Community) Flows​

User Journey:

  1. Discover/create circle
  2. Join circle (or apply)
  3. Share content to circle
  4. View circle feed
  5. 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​

  1. PostgreSQL - Test database (via TestContainers or Docker)
  2. AWS Cognito - Test user pool (or mock)
  3. Stripe - Test mode API keys
  4. 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)​

  1. Create FishingLog.API.Tests project
  2. Set up TestContainers
  3. Create test infrastructure helpers
  4. Write authentication flow tests
  5. Write payment flow tests

Phase 2: Web App E2E (Week 3-4)​

  1. Install Playwright
  2. Set up test configuration
  3. Create auth helpers
  4. Write critical user journey tests
  5. Integrate with CI/CD

Phase 3: Mobile App E2E (Week 5-6)​

  1. Install Detox
  2. Configure iOS/Android simulators
  3. Create test helpers
  4. Write critical flow tests
  5. Set up CI/CD for mobile

Phase 4: Cross-Platform Tests (Week 7+)​

  1. Test payment flows end-to-end
  2. Test social features across platforms
  3. Test data synchronization
  4. Performance testing

Resources​

Next Steps​

  1. ✅ Review and approve this strategy
  2. ⬜ Set up backend test project
  3. ⬜ Set up web app E2E tests
  4. ⬜ Set up mobile app E2E tests
  5. ⬜ Create test data management system
  6. ⬜ Integrate with CI/CD
  7. ⬜ Write critical path tests
  8. ⬜ Expand test coverage

Last Updated: December 2025
Status: Strategy Document - Ready for Implementation