diff --git a/lib/src/mock_supabase_http_client.dart b/lib/src/mock_supabase_http_client.dart index ebeab1c..b354ec5 100644 --- a/lib/src/mock_supabase_http_client.dart +++ b/lib/src/mock_supabase_http_client.dart @@ -434,13 +434,27 @@ class MockSupabaseHttpClient extends BaseClient { ? List>.from(data) : [Map.from(data)]; + // Get the onConflict columns + final onConflictColumns = + (request.url.queryParameters['on_conflict'] ?? 'id') + .split(',') + .map((e) => e.trim()) + .toList(); + // Upsert each item final results = items.map((item) { - final id = item['id']; - if (id != null) { - final index = - _database[tableKey]!.indexWhere((dbItem) => dbItem['id'] == id); + // Check if all onConflictColumns are set in item + final shouldUpdate = + onConflictColumns.every((column) => item[column] != null); + + if (shouldUpdate) { + // Find the index for an item that matches all onConflictColumns + final index = _database[tableKey]!.indexWhere((dbItem) => + onConflictColumns + .every((column) => dbItem[column] == item[column])); + if (index != -1) { + // Update the item in the database _database[tableKey]![index] = { ..._database[tableKey]![index], ...item diff --git a/test/mock_supabase_http_client_test.dart b/test/mock_supabase_http_client_test.dart index 63a158d..5917eaa 100644 --- a/test/mock_supabase_http_client_test.dart +++ b/test/mock_supabase_http_client_test.dart @@ -59,6 +59,49 @@ void main() { expect(postsUfterUpdate.first, {'id': 1, 'title': 'Updated post'}); }); + test('Upsert with single onConflict column, not id', () async { + final data = {'user_id': 1, 'name': 'John Doe'}; + const table = 'users'; + // Insert a record + await mockSupabase.from(table).insert(data); + final users = await mockSupabase.from(table).select(); + expect(users.first, data); + + final updatedData = { + ...data, + 'name': 'James Bond', + }; + await mockSupabase.from(table).upsert( + updatedData, + onConflict: 'user_id', + ); + final usersAfterUpdate = + await mockSupabase.from(table).select().eq('user_id', 1); + expect(usersAfterUpdate.length, 1); + expect(usersAfterUpdate.first, updatedData); + }); + + test('Upsert with multiple onConflict columns', () async { + final data = {'user': 2, 'post': 1, 'title': 'Initial post'}; + // Test upserting a record + await mockSupabase.from('posts').insert(data); + final posts = await mockSupabase.from('posts').select(); + expect(posts.first, data); + + final updatedData = { + ...data, + 'title': 'Updated post', + }; + await mockSupabase.from('posts').upsert( + updatedData, + onConflict: 'user, post', + ); + final postsAfterUpdate = + await mockSupabase.from('posts').select().eq('user', 2).eq('post', 1); + expect(postsAfterUpdate.length, 1); + expect(postsAfterUpdate.first, updatedData); + }); + test('Upsert then select', () async { // Test upserting a record await mockSupabase