Skip to content

feat: Add support for triggering error for PostgREST methods. #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 136 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,142 @@ void main() {
}
```

### Mocking Errors

You can simulate error scenarios by configuring an error trigger callback. This is useful for testing how your application handles various error conditions:

```dart
void main() {
late final SupabaseClient mockSupabase;
late final MockSupabaseHttpClient mockHttpClient;

setUp(() {
// Configure error trigger
mockHttpClient = MockSupabaseHttpClient(
postgrestExceptionTrigger: (schema, table, data, type) {
// Simulate unique constraint violation on email
if (table == 'users' && type == RequestType.insert) {
throw PostgrestException(
message: 'duplicate key value violates unique constraint "users_email_key"',
code: '23505', // Postgres unique violation code
);
}

// Simulate permission error for certain operations
if (table == 'private_data' && type == RequestType.select) {
throw PostgrestException(
message: 'permission denied for table private_data',
code: '42501', // Postgres permission denied code
);
}
},
);

mockSupabase = SupabaseClient(
'https://mock.supabase.co',
'fakeAnonKey',
httpClient: mockHttpClient,
);
});

test('handles duplicate email error', () async {
expect(
() => mockSupabase.from('users').insert({
'email': '[email protected]',
'name': 'Test User'
}),
throwsA(isA<PostgrestException>()),
);
});
}
```

### RPC Functions

You can mock Remote Procedure Call (RPC) functions by registering them with the mock client:

```dart
void main() {
late final SupabaseClient mockSupabase;
late final MockSupabaseHttpClient mockHttpClient;

setUp(() {
mockHttpClient = MockSupabaseHttpClient();

// Register mock RPC functions
mockHttpClient.registerRpcFunction(
'get_user_status',
(params, tables) => {'status': 'active', 'last_seen': '2024-03-20'},
);

mockHttpClient.registerRpcFunction(
'calculate_total',
(params, tables) {
final amount = params['amount'] as num;
final tax = params['tax_rate'] as num;
return {
'total': amount + (amount * tax),
'tax_amount': amount * tax,
};
},
);

mockSupabase = SupabaseClient(
'https://mock.supabase.co',
'fakeAnonKey',
httpClient: mockHttpClient,
);
});

test('calls RPC function with parameters', () async {
final result = await mockSupabase.rpc(
'calculate_total',
params: {'amount': 100, 'tax_rate': 0.1},
);

expect(result, {
'total': 110.0,
'tax_amount': 10.0,
});
});

test('mocks complex RPC function using database state', () async {
// Insert some test data
await mockSupabase.from('orders').insert([
{'id': 1, 'user_id': 123, 'amount': 100},
{'id': 2, 'user_id': 123, 'amount': 200},
]);

// Register RPC that uses the mock database state
mockHttpClient.registerRpcFunction(
'get_user_total_orders',
(params, tables) {
final userId = params['user_id'];
final orders = tables['public.orders'] as List<Map<String, dynamic>>;

final userOrders = orders.where((order) => order['user_id'] == userId);
final total = userOrders.fold<num>(
0,
(sum, order) => sum + (order['amount'] as num),
);

return {'total_orders': userOrders.length, 'total_amount': total};
},
);

final result = await mockSupabase.rpc(
'get_user_total_orders',
params: {'user_id': 123},
);

expect(result, {
'total_orders': 2,
'total_amount': 300,
});
});
}
```

## Current Limitations

- The mock Supabase client does not know the table schema. This means that it does not know if the inserted mock data is a referenced table data, or just a array/JSON object. This could potentially return more data than you construct a mock data with more than one referenced table.
Expand All @@ -154,7 +290,6 @@ void main() {
- count and head requests are not supported.
- aggregate functions are not supported.
- Respect nullsFirst on ordering is not supported.
- rpc support is not supported.
- The errors thrown by the mock Supabase client is not the same as the actual Supabase client.
- The mock Supabase client does not support auth, realtime, storage, or calling edge functions.
- You can either mock those using libraries like [mockito](https://pub.dev/packages/mockito) or use the Supabase CLI to do a full integration testing. You could use our [GitHub actions](https://github.com/supabase/setup-cli) to do that.
Expand Down
Loading