From f682d7ca1d741fd6292361372d30e805784eb15e Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 11 Dec 2025 18:25:35 -0300 Subject: [PATCH 1/2] fix(realtime_client): make ref field optional in Message class Make the ref field nullable (String?) and optional in the Message constructor to match JavaScript SDK behavior. This allows null refs in scenarios like heartbeats and aligns with the JavaScript SDK implementation. - Changed ref from String to String? - Made ref optional in constructor - Updated toJson() to conditionally include ref only when not null - Added comprehensive tests for null ref scenarios Closes SDK-531 --- packages/realtime_client/lib/src/message.dart | 6 +- .../realtime_client/test/message_test.dart | 95 +++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 packages/realtime_client/test/message_test.dart diff --git a/packages/realtime_client/lib/src/message.dart b/packages/realtime_client/lib/src/message.dart index ef4fe366a..6458e4f67 100644 --- a/packages/realtime_client/lib/src/message.dart +++ b/packages/realtime_client/lib/src/message.dart @@ -5,14 +5,14 @@ class Message { final String topic; final ChannelEvents event; final dynamic payload; - final String ref; + final String? ref; final String? joinRef; Message({ required this.topic, required this.event, required this.payload, - required this.ref, + this.ref, this.joinRef, }); @@ -48,7 +48,7 @@ class Message { 'event': event != ChannelEvents.heartbeat ? event.eventName() : 'heartbeat', 'payload': processedPayload, - 'ref': ref, + if (ref != null) 'ref': ref, if (joinRef != null) 'join_ref': joinRef, }; } diff --git a/packages/realtime_client/test/message_test.dart b/packages/realtime_client/test/message_test.dart new file mode 100644 index 000000000..64b2adb26 --- /dev/null +++ b/packages/realtime_client/test/message_test.dart @@ -0,0 +1,95 @@ +import 'package:realtime_client/realtime_client.dart'; +import 'package:realtime_client/src/constants.dart'; +import 'package:realtime_client/src/message.dart'; +import 'package:test/test.dart'; + +void main() { + group('Message', () { + test('message with null refs serializes correctly', () { + final message = Message( + topic: 'phoenix', + event: ChannelEvents.heartbeat, + payload: {}, + ref: null, + joinRef: null, + ); + final json = message.toJson(); + expect(json['ref'], isNull); + expect(json['join_ref'], isNull); + expect(json['topic'], equals('phoenix')); + expect(json['event'], equals('heartbeat')); + expect(json['payload'], equals({})); + }); + + test('heartbeat message with null joinRef', () { + final message = Message( + topic: 'phoenix', + event: ChannelEvents.heartbeat, + payload: {}, + ref: '123', + joinRef: null, + ); + final json = message.toJson(); + expect(json['ref'], equals('123')); + expect(json.containsKey('join_ref'), isFalse); + expect(json['topic'], equals('phoenix')); + expect(json['event'], equals('heartbeat')); + }); + + test('message with null ref but valid joinRef', () { + final message = Message( + topic: 'room:lobby', + event: ChannelEvents.join, + payload: {'user_id': '123'}, + ref: null, + joinRef: 'join-456', + ); + final json = message.toJson(); + expect(json.containsKey('ref'), isFalse); + expect(json['join_ref'], equals('join-456')); + expect(json['topic'], equals('room:lobby')); + expect(json['payload'], equals({'user_id': '123'})); + }); + + test('message with both ref and joinRef', () { + final message = Message( + topic: 'room:lobby', + event: ChannelEvents.join, + payload: {'user_id': '123'}, + ref: 'ref-789', + joinRef: 'join-456', + ); + final json = message.toJson(); + expect(json['ref'], equals('ref-789')); + expect(json['join_ref'], equals('join-456')); + expect(json['topic'], equals('room:lobby')); + expect(json['payload'], equals({'user_id': '123'})); + }); + + test('message with ref but null joinRef', () { + final message = Message( + topic: 'room:lobby', + event: ChannelEvents.leave, + payload: {}, + ref: 'ref-999', + joinRef: null, + ); + final json = message.toJson(); + expect(json['ref'], equals('ref-999')); + expect(json.containsKey('join_ref'), isFalse); + expect(json['topic'], equals('room:lobby')); + }); + + test('ref parameter is optional in constructor', () { + final message = Message( + topic: 'phoenix', + event: ChannelEvents.heartbeat, + payload: {}, + // ref is not provided, should be null + ); + expect(message.ref, isNull); + final json = message.toJson(); + expect(json.containsKey('ref'), isFalse); + }); + }); +} From 72373c12fd67ce3e9a08db4354f4c342b73e4a99 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 11 Dec 2025 18:48:01 -0300 Subject: [PATCH 2/2] fix: remove unused import --- packages/realtime_client/test/message_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/realtime_client/test/message_test.dart b/packages/realtime_client/test/message_test.dart index 64b2adb26..8f3ed566f 100644 --- a/packages/realtime_client/test/message_test.dart +++ b/packages/realtime_client/test/message_test.dart @@ -1,4 +1,3 @@ -import 'package:realtime_client/realtime_client.dart'; import 'package:realtime_client/src/constants.dart'; import 'package:realtime_client/src/message.dart'; import 'package:test/test.dart';