Skip to content

Commit f5a33d1

Browse files
committed
chore: Improve test coverage for realtime_client
1 parent fb58bcd commit f5a33d1

File tree

4 files changed

+1573
-1
lines changed

4 files changed

+1573
-1
lines changed

packages/realtime_client/test/channel_test.dart

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ void main() {
352352
RealtimeChannel('topic', socket, params: RealtimeChannelConfig());
353353
});
354354

355-
test('description', () async {
355+
test('presence callbacks work correctly', () async {
356356
bool syncCalled = false, joinCalled = false, leaveCalled = false;
357357
channel.onPresenceSync((payload) {
358358
syncCalled = true;
@@ -386,4 +386,104 @@ void main() {
386386
expect(leaveCalled, isTrue);
387387
});
388388
});
389+
390+
group('postgres changes', () {
391+
setUp(() {
392+
socket = RealtimeClient('', timeout: const Duration(milliseconds: 1234));
393+
channel =
394+
RealtimeChannel('topic', socket, params: RealtimeChannelConfig());
395+
});
396+
397+
test('onPostgresChanges registers postgres change listener', () {
398+
var called = false;
399+
PostgresChangePayload? receivedPayload;
400+
401+
channel.onPostgresChanges(
402+
event: PostgresChangeEvent.insert,
403+
schema: 'public',
404+
table: 'users',
405+
callback: (payload) {
406+
called = true;
407+
receivedPayload = payload;
408+
},
409+
);
410+
411+
// Simulate postgres change event
412+
final payload = {
413+
'schema': 'public',
414+
'table': 'users',
415+
'eventType': 'INSERT',
416+
'new': {'id': 1, 'name': 'John'},
417+
'old': {},
418+
'commit_timestamp': '2023-01-01T00:00:00Z',
419+
'errors': null,
420+
};
421+
422+
channel.trigger('postgres_changes', {
423+
'type': 'INSERT',
424+
...payload,
425+
});
426+
427+
expect(called, isTrue);
428+
expect(receivedPayload?.eventType, PostgresChangeEvent.insert);
429+
expect(receivedPayload?.newRecord['name'], 'John');
430+
});
431+
});
432+
433+
group('broadcast', () {
434+
setUp(() {
435+
socket = RealtimeClient('', timeout: const Duration(milliseconds: 1234));
436+
channel =
437+
RealtimeChannel('topic', socket, params: RealtimeChannelConfig());
438+
});
439+
440+
test('onBroadcast registers broadcast listener', () {
441+
var called = false;
442+
Map<String, dynamic>? receivedPayload;
443+
444+
channel.onBroadcast(
445+
event: 'chat_message',
446+
callback: (payload) {
447+
called = true;
448+
receivedPayload = payload;
449+
},
450+
);
451+
452+
// Simulate broadcast event
453+
channel.trigger('broadcast', {
454+
'event': 'chat_message',
455+
'payload': {'text': 'Hello world'},
456+
});
457+
458+
expect(called, isTrue);
459+
expect(receivedPayload?['payload']['text'], 'Hello world');
460+
});
461+
});
462+
463+
group('helper methods', () {
464+
setUp(() {
465+
socket = RealtimeClient('', timeout: const Duration(milliseconds: 1234));
466+
channel =
467+
RealtimeChannel('topic', socket, params: RealtimeChannelConfig());
468+
});
469+
470+
test('replyEventName generates correct event name', () {
471+
expect(channel.replyEventName('ref123'), 'chan_reply_ref123');
472+
expect(channel.replyEventName(null), '');
473+
});
474+
475+
test('isMember checks topic membership correctly', () {
476+
expect(channel.isMember('topic'), isTrue);
477+
expect(channel.isMember('other:topic'), isFalse);
478+
expect(channel.isMember('*'), isTrue);
479+
});
480+
481+
test('state getters return correct values', () {
482+
expect(channel.isClosed, isTrue);
483+
expect(channel.isErrored, isFalse);
484+
expect(channel.isJoined, isFalse);
485+
expect(channel.isJoining, isFalse);
486+
expect(channel.isLeaving, isFalse);
487+
});
488+
});
389489
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import 'package:realtime_client/src/constants.dart';
2+
import 'package:test/test.dart';
3+
4+
void main() {
5+
group('Constants', () {
6+
test('has correct values', () {
7+
expect(Constants.vsn, '1.0.0');
8+
expect(Constants.defaultTimeout.inMilliseconds, 10000);
9+
expect(Constants.defaultHeartbeatIntervalMs, 25000);
10+
expect(Constants.wsCloseNormal, 1000);
11+
expect(Constants.defaultHeaders, isA<Map<String, String>>());
12+
expect(Constants.defaultHeaders.containsKey('X-Client-Info'), isTrue);
13+
});
14+
});
15+
16+
group('RealtimeConstants', () {
17+
test('is type alias for Constants', () {
18+
expect(RealtimeConstants.vsn, Constants.vsn);
19+
});
20+
});
21+
22+
group('SocketStates', () {
23+
test('enum values exist', () {
24+
expect(SocketStates.connecting, isNotNull);
25+
expect(SocketStates.open, isNotNull);
26+
expect(SocketStates.disconnecting, isNotNull);
27+
expect(SocketStates.closed, isNotNull);
28+
expect(SocketStates.disconnected, isNotNull);
29+
});
30+
});
31+
32+
group('ChannelStates', () {
33+
test('enum values exist', () {
34+
expect(ChannelStates.closed, isNotNull);
35+
expect(ChannelStates.errored, isNotNull);
36+
expect(ChannelStates.joined, isNotNull);
37+
expect(ChannelStates.joining, isNotNull);
38+
expect(ChannelStates.leaving, isNotNull);
39+
});
40+
});
41+
42+
group('ChannelEvents', () {
43+
test('enum values exist', () {
44+
expect(ChannelEvents.close, isNotNull);
45+
expect(ChannelEvents.error, isNotNull);
46+
expect(ChannelEvents.join, isNotNull);
47+
expect(ChannelEvents.reply, isNotNull);
48+
expect(ChannelEvents.leave, isNotNull);
49+
expect(ChannelEvents.heartbeat, isNotNull);
50+
expect(ChannelEvents.accessToken, isNotNull);
51+
expect(ChannelEvents.broadcast, isNotNull);
52+
expect(ChannelEvents.presence, isNotNull);
53+
expect(ChannelEvents.postgresChanges, isNotNull);
54+
});
55+
});
56+
57+
group('ChannelEventsExtended', () {
58+
test('fromType returns correct enum from name', () {
59+
expect(ChannelEventsExtended.fromType('close'), ChannelEvents.close);
60+
expect(ChannelEventsExtended.fromType('error'), ChannelEvents.error);
61+
expect(ChannelEventsExtended.fromType('join'), ChannelEvents.join);
62+
});
63+
64+
test('fromType returns correct enum from eventName', () {
65+
expect(ChannelEventsExtended.fromType('phx_close'), ChannelEvents.close);
66+
expect(ChannelEventsExtended.fromType('phx_error'), ChannelEvents.error);
67+
expect(ChannelEventsExtended.fromType('access_token'),
68+
ChannelEvents.accessToken);
69+
expect(ChannelEventsExtended.fromType('postgres_changes'),
70+
ChannelEvents.postgresChanges);
71+
expect(
72+
ChannelEventsExtended.fromType('broadcast'), ChannelEvents.broadcast);
73+
expect(
74+
ChannelEventsExtended.fromType('presence'), ChannelEvents.presence);
75+
});
76+
77+
test('fromType throws for invalid type', () {
78+
expect(
79+
() => ChannelEventsExtended.fromType('invalid_type'),
80+
throwsA(isA<String>().having(
81+
(s) => s, 'error', contains('No type invalid_type exists'))));
82+
});
83+
84+
test('eventName returns correct string', () {
85+
expect(ChannelEvents.close.eventName(), 'phx_close');
86+
expect(ChannelEvents.error.eventName(), 'phx_error');
87+
expect(ChannelEvents.join.eventName(), 'phx_join');
88+
expect(ChannelEvents.reply.eventName(), 'phx_reply');
89+
expect(ChannelEvents.leave.eventName(), 'phx_leave');
90+
expect(ChannelEvents.heartbeat.eventName(), 'phx_heartbeat');
91+
expect(ChannelEvents.accessToken.eventName(), 'access_token');
92+
expect(ChannelEvents.postgresChanges.eventName(), 'postgres_changes');
93+
expect(ChannelEvents.broadcast.eventName(), 'broadcast');
94+
expect(ChannelEvents.presence.eventName(), 'presence');
95+
});
96+
});
97+
98+
group('Transports', () {
99+
test('has correct websocket value', () {
100+
expect(Transports.websocket, 'websocket');
101+
});
102+
});
103+
104+
group('RealtimeLogLevel', () {
105+
test('enum values exist', () {
106+
expect(RealtimeLogLevel.info, isNotNull);
107+
expect(RealtimeLogLevel.debug, isNotNull);
108+
expect(RealtimeLogLevel.warn, isNotNull);
109+
expect(RealtimeLogLevel.error, isNotNull);
110+
});
111+
});
112+
}

0 commit comments

Comments
 (0)