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:
- Authentication Flow: Complex signup/signin flows with organization creation
- GraphQL Resolvers: RLS enforcement and role-based permissions
- 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)
Related ADRs
- ADR-005: Supabase JWT Authentication
- ADR-014: Cloud-First Testing Strategy
- ADR-028: Local Testing Environment
- ADR-038: Edge Function Wrapper Pattern