Skip to content

Commit

Permalink
simplify mock server serialization and add test for multiple realtime…
Browse files Browse the repository at this point in the history
… events
  • Loading branch information
tshedor committed Oct 29, 2024
1 parent a0a879d commit ff3efaf
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,14 @@ abstract class OfflineFirstWithSupabaseRepository
Map<String, dynamic> payload, {
required Map<String, RuntimeSupabaseColumnDefinition> supabaseDefinitions,
}) {
final fieldsWithValues = payload.entries.fold(<String, dynamic>{}, (acc, entry) {
for (final f in supabaseDefinitions.entries) {
if (f.value.columnName == entry.key) {
acc[f.key] = entry.value;
break;
}
}
final columnsToFields = supabaseDefinitions.entries.fold(<String, String>{}, (acc, entry) {
acc[entry.value.columnName] = entry.key;
return acc;
});

final fieldsWithValues = payload.entries.fold(<String, dynamic>{}, (acc, entry) {
if (columnsToFields[entry.key] == null) return acc;
acc[columnsToFields[entry.key]!] = entry.value;
return acc;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,6 @@ void main() async {
realtimeEvent: PostgresChangeEvent.insert,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.insert,
);
mock.handle({req: resp});

Expand Down Expand Up @@ -486,7 +485,6 @@ void main() async {
realtimeEvent: PostgresChangeEvent.delete,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.delete,
);
mock.handle({req: resp});

Expand Down Expand Up @@ -536,7 +534,6 @@ void main() async {
realtimeEvent: PostgresChangeEvent.update,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.update,
);
mock.handle({req: resp});
});
Expand Down Expand Up @@ -572,7 +569,6 @@ void main() async {
realtimeEvent: PostgresChangeEvent.insert,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.insert,
);
mock.handle({req: resp});

Expand Down Expand Up @@ -613,7 +609,6 @@ void main() async {
realtimeEvent: PostgresChangeEvent.delete,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.delete,
);
mock.handle({req: resp});

Expand Down Expand Up @@ -662,7 +657,54 @@ void main() async {
realtimeEvent: PostgresChangeEvent.update,
repository: repository,
),
realtimeEvent: PostgresChangeEvent.update,
);
mock.handle({req: resp});
});

test('with multiple events', () async {
final customer1 = Customer(
id: 1,
firstName: 'Thomas',
lastName: 'Guy',
pizzas: [
Pizza(id: 2, toppings: [Topping.pepperoni], frozen: false),
],
);
final customer2 = Customer(
id: 1,
firstName: 'Guy',
lastName: 'Thomas',
pizzas: [
Pizza(id: 2, toppings: [Topping.pepperoni], frozen: false),
],
);

final customers = repository.subscribeToRealtime<Customer>();
expect(
customers,
emitsInOrder([
[],
[customer1],
[customer2],
]),
);

final req = SupabaseRequest<Customer>();
final resp = SupabaseResponse(
await mock.serialize(
customer1,
realtimeEvent: PostgresChangeEvent.insert,
repository: repository,
),
realtimeSubsequentReplies: [
SupabaseResponse(
await mock.serialize(
customer2,
realtimeEvent: PostgresChangeEvent.update,
repository: repository,
),
),
],
);
mock.handle({req: resp});
});
Expand Down
21 changes: 4 additions & 17 deletions packages/brick_supabase/lib/src/testing/supabase_mock_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ class SupabaseMockServer {
final data = Map<String, dynamic>.from(r.data as Map);

return {
'id': _realtimeEventToId(r.realtimeEvent!),
'event': r.realtimeEvent!.name.toUpperCase(),
'id': data['payload']['ids'][0],
'event': data['payload']['data']['type'],
'schema': data['payload']['data']['schema'],
'table': data['payload']['data']['table'],
if (realtimeFilter != null) 'filter': realtimeFilter,
Expand All @@ -124,7 +124,7 @@ class SupabaseMockServer {
}

for (final realtimeResponses in matching.value.flattenedResponses) {
await Future.delayed(matching.value.realtimeDelayBetweenResponses);
await Future.delayed(matching.value.realtimeSubsequentReplyDelay);
final data = Map<String, dynamic>.from(realtimeResponses.data as Map);
final serialized = jsonEncode({...data, 'topic': topic});
webSocket!.add(serialized);
Expand Down Expand Up @@ -177,19 +177,6 @@ class SupabaseMockServer {
return resp;
}

int _realtimeEventToId(PostgresChangeEvent event) {
switch (event) {
case PostgresChangeEvent.insert:
return 77086988;
case PostgresChangeEvent.update:
return 25993878;
case PostgresChangeEvent.delete:
return 48673474;
case PostgresChangeEvent.all:
return 0;
}
}

/// Convert a model to a Supabase response.
///
/// For realtime responses, include the `realtimeEvent` argument.
Expand Down Expand Up @@ -224,7 +211,7 @@ class SupabaseMockServer {
'ref': null,
'event': 'postgres_changes',
'payload': {
'ids': [_realtimeEventToId(realtimeEvent)],
'ids': [realtimeEvent.index],
'data': {
'columns': adapter.fieldsToSupabaseColumns.entries.map((entry) {
return {'name': entry.value.columnName, 'type': 'text', 'type_modifier': 4294967295};
Expand Down
43 changes: 20 additions & 23 deletions packages/brick_supabase/lib/src/testing/supabase_response.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import 'package:supabase/supabase.dart';

class SupabaseResponse {
final dynamic data;

final Map<String, String>? headers;

final Duration realtimeDelayBetweenResponses;

final PostgresChangeEvent? realtimeEvent;

final List<SupabaseResponse> realtimeResponses;

/// All recursively-discovered [realtimeSubsequentReplies]
List<SupabaseResponse> get flattenedResponses {
final starter = <SupabaseResponse>[];
if (realtimeEvent != PostgresChangeEvent.all) {
starter.add(this);
}
return realtimeResponses.fold(starter, (acc, r) {
return realtimeSubsequentReplies.fold(<SupabaseResponse>[this], (acc, r) {
void recurse(SupabaseResponse response) {
if (response.realtimeResponses.isNotEmpty) {
acc.addAll(
response.realtimeResponses.where((e) => e.realtimeEvent != PostgresChangeEvent.all),
);
response.realtimeResponses.forEach(recurse);
acc.add(response);
if (response.realtimeSubsequentReplies.isNotEmpty) {
acc.addAll(response.realtimeSubsequentReplies);
response.realtimeSubsequentReplies.forEach(recurse);
}
}

Expand All @@ -31,11 +17,22 @@ class SupabaseResponse {
});
}

final Map<String, String>? headers;

/// Additional replies sent after this instance's [data].
/// Replies will be staggered by [realtimeSubsequentReplyDelay].
///
/// While [flattenedResponses] supports recursion, it should never be
/// necessary to have deeply nested responses.
final List<SupabaseResponse> realtimeSubsequentReplies;

/// Amount of time to delay each [realtimeSubsequentReplies]
final Duration realtimeSubsequentReplyDelay;

SupabaseResponse(
this.data, {
this.headers,
this.realtimeEvent,
this.realtimeDelayBetweenResponses = const Duration(milliseconds: 10),
this.realtimeResponses = const [],
this.realtimeSubsequentReplies = const [],
this.realtimeSubsequentReplyDelay = const Duration(milliseconds: 10),
});
}

0 comments on commit ff3efaf

Please sign in to comment.