Skip to main content

Source: ocean/docs/adr/ADR-041-testing-strategy-enhancement.md | ✏️ Edit on GitHub

ADR-041: Testing Strategy Enhancement

Status

Accepted

Context

The Ocean platform had minimal integration testing coverage for critical flows:

  1. Authentication Flow: Complex signup/signin flows with organization creation
  2. GraphQL Resolvers: RLS enforcement and role-based permissions
  3. Edge Functions: Shared authentication patterns and Stripe integrations

Without proper tests, these critical patterns were at risk of regression.

Decision

Implement comprehensive integration tests for core platform patterns.

Test Structure

tests/
├── integration/
│ ├── test-utils.ts # Shared test utilities
│ ├── auth-flow.test.ts # Authentication flow tests
│ ├── graphql-resolvers.test.ts # GraphQL API tests
│ ├── stripe-functions.test.ts # Edge Function tests
│ └── README.md # Test documentation
├── pre-commit/ # Existing unit tests
└── setup.ts # Test configuration

Implementation Details

1. Authentication Flow Tests

Tests critical auth scenarios:

  • User signup with automatic organization creation
  • Race condition handling in auth state changes
  • Session expiry and token refresh
  • Error handling for invalid credentials
  • Organization provisioning during signup

2. GraphQL Resolver Tests

Validates security patterns:

  • Row-level security (RLS) enforcement
  • Role-based access control (owner, admin, member)
  • Concurrent update handling with optimistic locking
  • Field-level permission validation
  • Provisioning retry logic

3. Edge Function Tests

Tests the shared wrapper pattern:

  • Authentication validation
  • CORS handling
  • Stripe integration patterns
  • Error handling and recovery
  • Customer portal session creation

Consequences

Positive

  • Confidence: Critical flows are protected from regression
  • Documentation: Tests serve as living documentation of patterns
  • Faster Development: Developers can refactor with confidence
  • Early Detection: Issues caught before production deployment

Negative

  • Maintenance: Tests must be updated when patterns change
  • Complexity: Integration tests are more complex than unit tests
  • Runtime: Integration tests take longer to run

Technical Patterns

Mock Service Pattern

function createMockSupabaseClient() {
return {
auth: {
getUser: vi.fn().mockResolvedValue({ data: { user }, error: null }),
signInWithOtp: vi.fn().mockResolvedValue({ data: null, error: null }),
// ... other auth methods
},
from: vi.fn((table) => ({
select: vi.fn().mockReturnThis(),
insert: vi.fn().mockReturnThis(),
// ... other query builders
})),
}
}

Wrapper Testing Pattern

const createStripeFunction = (handler) => {
return async (req) => {
// Test CORS
if (req.method === 'OPTIONS') return corsResponse()

// Test auth
const authResult = await authenticate(req)
if (authResult.error) return authResult.error

// Test handler
return handler(req, authResult.context)
}
}

Concurrent Operation Testing

// Execute concurrent updates
const [result1, result2] = await Promise.all([
updateOrganization({ name: 'Update 1' }),
updateOrganization({ name: 'Update 2' }),
])

// Verify one succeeded, one failed (optimistic locking)
expect([result1.error, result2.error].filter(Boolean)).toHaveLength(1)
  • ADR-005: Supabase JWT Authentication
  • ADR-014: Cloud-First Testing Strategy
  • ADR-028: Local Testing Environment
  • ADR-038: Edge Function Wrapper Pattern