@@ -34,7 +34,7 @@ void main() {
3434 expect (channel.params, {
3535 'config' : {
3636 'broadcast' : {'ack' : false , 'self' : false },
37- 'presence' : {'key' : '' },
37+ 'presence' : {'key' : '' , 'enabled' : false },
3838 'private' : false ,
3939 }
4040 });
@@ -54,7 +54,7 @@ void main() {
5454 expect (joinPush.payload, {
5555 'config' : {
5656 'broadcast' : {'ack' : false , 'self' : false },
57- 'presence' : {'key' : '' },
57+ 'presence' : {'key' : '' , 'enabled' : false },
5858 'private' : true ,
5959 },
6060 });
@@ -386,4 +386,234 @@ void main() {
386386 expect (leaveCalled, isTrue);
387387 });
388388 });
389+
390+ group ('presence enabled' , () {
391+ setUp (() {
392+ socket = RealtimeClient ('' , timeout: const Duration (milliseconds: 1234 ));
393+ });
394+
395+ test (
396+ 'should enable presence when config.presence.enabled is true even without bindings' ,
397+ () {
398+ channel = RealtimeChannel (
399+ 'topic' ,
400+ socket,
401+ params: const RealtimeChannelConfig (enabled: true ),
402+ );
403+
404+ channel.subscribe ();
405+
406+ final joinPayload = channel.joinPush.payload;
407+ expect (joinPayload['config' ]['presence' ]['enabled' ], isTrue);
408+ });
409+
410+ test ('should enable presence when presence listeners exist' , () {
411+ channel = RealtimeChannel (
412+ 'topic' ,
413+ socket,
414+ params: const RealtimeChannelConfig (),
415+ );
416+
417+ channel.onPresenceSync ((payload) {});
418+ channel.subscribe ();
419+
420+ final joinPayload = channel.joinPush.payload;
421+ expect (joinPayload['config' ]['presence' ]['enabled' ], isTrue);
422+ });
423+
424+ test (
425+ 'should enable presence when both bindings exist and config.presence.enabled is true' ,
426+ () {
427+ channel = RealtimeChannel (
428+ 'topic' ,
429+ socket,
430+ params: const RealtimeChannelConfig (enabled: true ),
431+ );
432+
433+ channel.onPresenceSync ((payload) {});
434+ channel.subscribe ();
435+
436+ final joinPayload = channel.joinPush.payload;
437+ expect (joinPayload['config' ]['presence' ]['enabled' ], isTrue);
438+ });
439+
440+ test (
441+ 'should not enable presence when neither bindings exist nor config.presence.enabled is true' ,
442+ () {
443+ channel = RealtimeChannel (
444+ 'topic' ,
445+ socket,
446+ params: const RealtimeChannelConfig (),
447+ );
448+
449+ channel.subscribe ();
450+
451+ final joinPayload = channel.joinPush.payload;
452+ expect (joinPayload['config' ]['presence' ]['enabled' ], isFalse);
453+ });
454+
455+ test ('should enable presence when join listener exists' , () {
456+ channel = RealtimeChannel (
457+ 'topic' ,
458+ socket,
459+ params: const RealtimeChannelConfig (),
460+ );
461+
462+ channel.onPresenceJoin ((payload) {});
463+ channel.subscribe ();
464+
465+ final joinPayload = channel.joinPush.payload;
466+ expect (joinPayload['config' ]['presence' ]['enabled' ], isTrue);
467+ });
468+
469+ test ('should enable presence when leave listener exists' , () {
470+ channel = RealtimeChannel (
471+ 'topic' ,
472+ socket,
473+ params: const RealtimeChannelConfig (),
474+ );
475+
476+ channel.onPresenceLeave ((payload) {});
477+ channel.subscribe ();
478+
479+ final joinPayload = channel.joinPush.payload;
480+ expect (joinPayload['config' ]['presence' ]['enabled' ], isTrue);
481+ });
482+ });
483+
484+ group ('presence resubscription' , () {
485+ setUp (() {
486+ socket = RealtimeClient ('' , timeout: const Duration (milliseconds: 1234 ));
487+ });
488+
489+ test (
490+ 'should resubscribe when presence callback added to subscribed channel without initial presence' ,
491+ () {
492+ channel = RealtimeChannel (
493+ 'topic' ,
494+ socket,
495+ params: const RealtimeChannelConfig (),
496+ );
497+
498+ channel.subscribe ();
499+ channel.joinPush.trigger ('ok' , {});
500+ expect (channel.params['config' ]['presence' ]['enabled' ], isFalse);
501+
502+ channel.onPresenceSync ((payload) {});
503+
504+ expect (channel.params['config' ]['presence' ]['enabled' ], isTrue);
505+ });
506+
507+ test (
508+ 'should not resubscribe when presence callback added to channel with existing presence' ,
509+ () {
510+ channel = RealtimeChannel (
511+ 'topic' ,
512+ socket,
513+ params: const RealtimeChannelConfig (enabled: true ),
514+ );
515+
516+ channel.subscribe ();
517+ channel.joinPush.trigger ('ok' , {});
518+ final initialPayload = Map .from (channel.params);
519+
520+ channel.onPresenceSync ((payload) {});
521+
522+ expect (channel.params['config' ]['presence' ]['enabled' ], isTrue);
523+ expect (channel.params, equals (initialPayload));
524+ });
525+
526+ test ('should only resubscribe once when multiple presence callbacks added' ,
527+ () {
528+ channel = RealtimeChannel (
529+ 'topic' ,
530+ socket,
531+ params: const RealtimeChannelConfig (),
532+ );
533+
534+ channel.subscribe ();
535+ channel.joinPush.trigger ('ok' , {});
536+ expect (channel.params['config' ]['presence' ]['enabled' ], isFalse);
537+
538+ channel.onPresenceSync ((payload) {});
539+ expect (channel.params['config' ]['presence' ]['enabled' ], isTrue);
540+
541+ final payloadAfterFirst = Map .from (channel.params);
542+
543+ channel.onPresenceJoin ((payload) {});
544+ channel.onPresenceLeave ((payload) {});
545+
546+ expect (channel.params, equals (payloadAfterFirst));
547+ });
548+
549+ test (
550+ 'should not resubscribe when presence callback added to unsubscribed channel' ,
551+ () {
552+ channel = RealtimeChannel (
553+ 'topic' ,
554+ socket,
555+ params: const RealtimeChannelConfig (),
556+ );
557+
558+ expect (channel.joinedOnce, isFalse);
559+
560+ channel.onPresenceSync ((payload) {});
561+
562+ expect (channel.params['config' ]['presence' ]['enabled' ], isFalse);
563+ });
564+
565+ test (
566+ 'should receive presence events after resubscription triggered by adding callback' ,
567+ () {
568+ channel = RealtimeChannel (
569+ 'topic' ,
570+ socket,
571+ params: const RealtimeChannelConfig (),
572+ );
573+
574+ channel.subscribe ();
575+ channel.joinPush.trigger ('ok' , {});
576+
577+ bool syncCalled = false ;
578+ channel.onPresenceSync ((payload) {
579+ syncCalled = true ;
580+ });
581+
582+ channel.trigger ('presence' , {'event' : 'sync' }, '1' );
583+
584+ expect (syncCalled, isTrue);
585+ });
586+
587+ test ('should handle presence join callback resubscription' , () {
588+ channel = RealtimeChannel (
589+ 'topic' ,
590+ socket,
591+ params: const RealtimeChannelConfig (),
592+ );
593+
594+ channel.subscribe ();
595+ channel.joinPush.trigger ('ok' , {});
596+ expect (channel.params['config' ]['presence' ]['enabled' ], isFalse);
597+
598+ channel.onPresenceJoin ((payload) {});
599+
600+ expect (channel.params['config' ]['presence' ]['enabled' ], isTrue);
601+ });
602+
603+ test ('should handle presence leave callback resubscription' , () {
604+ channel = RealtimeChannel (
605+ 'topic' ,
606+ socket,
607+ params: const RealtimeChannelConfig (),
608+ );
609+
610+ channel.subscribe ();
611+ channel.joinPush.trigger ('ok' , {});
612+ expect (channel.params['config' ]['presence' ]['enabled' ], isFalse);
613+
614+ channel.onPresenceLeave ((payload) {});
615+
616+ expect (channel.params['config' ]['presence' ]['enabled' ], isTrue);
617+ });
618+ });
389619}
0 commit comments