@@ -626,6 +626,119 @@ public static async Task IfWithAsyncHereNowIsCalledThenItShouldReturnInfo()
626626 }
627627
628628
629+ // Parses a raw here_now server response through the same deserializer the SDK uses,
630+ // bypassing the network so occupancy parsing can be asserted deterministically.
631+ private static PNHereNowResult ParseHereNowResponse ( string serverResponse , string channelArg )
632+ {
633+ PNConfiguration config = new PNConfiguration ( new UserId ( "mytestuuid" ) )
634+ {
635+ PublishKey = PubnubCommon . PublishKey ,
636+ SubscribeKey = PubnubCommon . SubscribeKey ,
637+ Secure = false
638+ } ;
639+ Pubnub pn = createPubNubInstance ( config , authToken ) ;
640+ try
641+ {
642+ List < object > listObject = new List < object >
643+ {
644+ pn . JsonPluggableLibrary . DeserializeToObject ( serverResponse ) ,
645+ channelArg
646+ } ;
647+ return DeserializeToInternalObjectUtility
648+ . DeserializeToInternalObject < PNHereNowResult > ( pn . JsonPluggableLibrary , listObject ) ;
649+ }
650+ finally
651+ {
652+ pn . Destroy ( ) ;
653+ pn . PubnubUnitTest = null ;
654+ }
655+ }
656+
657+ [ Test ]
658+ public static void IfHereNowWithoutUUIDsIsCalledThenChannelOccupancyShouldMatchTotalOccupancy ( )
659+ {
660+ string channel = "mocha" ;
661+ // Single channel + disable_uuids returns the compact format: occupancy present, no payload wrapper, no uuids array.
662+ string serverResponse = "{\" status\" : 200, \" message\" : \" OK\" , \" service\" : \" Presence\" , \" occupancy\" : 3}" ;
663+
664+ PNHereNowResult result = ParseHereNowResponse ( serverResponse , channel ) ;
665+
666+ Assert . IsNotNull ( result , "here_now result not parsed" ) ;
667+ Assert . AreEqual ( 3 , result . TotalOccupancy , "TotalOccupancy mismatch" ) ;
668+ Assert . IsTrue ( result . Channels . TryGetValue ( channel , out var channelData ) , "channel data missing" ) ;
669+ Assert . AreEqual ( channel , channelData . ChannelName , "ChannelName not populated" ) ;
670+ Assert . AreEqual ( 3 , channelData . Occupancy , "channel Occupancy should match total occupancy, not be hardcoded to 1" ) ;
671+ }
672+
673+ [ Test ]
674+ public static void IfHereNowWithoutUUIDsIsCalledOnEmptyChannelThenOccupancyShouldBeZero ( )
675+ {
676+ string channel = "mocha" ;
677+ // Empty single channel + disable_uuids: occupancy 0, no uuids array.
678+ string serverResponse = "{\" status\" : 200, \" message\" : \" OK\" , \" service\" : \" Presence\" , \" occupancy\" : 0}" ;
679+
680+ PNHereNowResult result = ParseHereNowResponse ( serverResponse , channel ) ;
681+
682+ Assert . IsNotNull ( result , "here_now result not parsed" ) ;
683+ Assert . AreEqual ( 0 , result . TotalOccupancy , "TotalOccupancy mismatch" ) ;
684+ Assert . IsTrue ( result . Channels . TryGetValue ( channel , out var channelData ) , "channel data missing" ) ;
685+ Assert . AreEqual ( channel , channelData . ChannelName , "ChannelName not populated" ) ;
686+ Assert . AreEqual ( 0 , channelData . Occupancy , "empty channel occupancy should be 0, not hardcoded to 1" ) ;
687+ }
688+
689+ [ Test ]
690+ public static void IfHereNowWithUUIDsIsCalledThenChannelOccupancyShouldMatchTotalOccupancy ( )
691+ {
692+ string channel = "mocha" ;
693+ // Single channel + include uuids: uuids array present alongside occupancy.
694+ string serverResponse = "{\" status\" : 200, \" message\" : \" OK\" , \" service\" : \" Presence\" , \" uuids\" : [\" u1\" , \" u2\" , \" u3\" ], \" occupancy\" : 3}" ;
695+
696+ PNHereNowResult result = ParseHereNowResponse ( serverResponse , channel ) ;
697+
698+ Assert . IsNotNull ( result , "here_now result not parsed" ) ;
699+ Assert . AreEqual ( 3 , result . TotalOccupancy , "TotalOccupancy mismatch" ) ;
700+ Assert . IsTrue ( result . Channels . TryGetValue ( channel , out var channelData ) , "channel data missing" ) ;
701+ Assert . AreEqual ( channel , channelData . ChannelName , "ChannelName not populated" ) ;
702+ Assert . AreEqual ( 3 , channelData . Occupancy , "channel Occupancy should match total occupancy" ) ;
703+ Assert . AreEqual ( 3 , channelData . Occupants . Count , "occupant count mismatch" ) ;
704+ }
705+
706+ [ Test ]
707+ public static void IfHereNowWithUUIDsIsCalledOnEmptyChannelThenChannelEntryShouldStillExist ( )
708+ {
709+ string channel = "mocha" ;
710+ // Empty single channel with uuids requested: uuids array present but empty, occupancy 0.
711+ string serverResponse = "{\" status\" : 200, \" message\" : \" OK\" , \" service\" : \" Presence\" , \" uuids\" : [], \" occupancy\" : 0}" ;
712+
713+ PNHereNowResult result = ParseHereNowResponse ( serverResponse , channel ) ;
714+
715+ Assert . IsNotNull ( result , "here_now result not parsed" ) ;
716+ Assert . AreEqual ( 0 , result . TotalOccupancy , "TotalOccupancy mismatch" ) ;
717+ Assert . IsTrue ( result . Channels . TryGetValue ( channel , out var channelData ) , "channel entry should exist even when empty" ) ;
718+ Assert . AreEqual ( channel , channelData . ChannelName , "ChannelName not populated" ) ;
719+ Assert . AreEqual ( 0 , channelData . Occupancy , "empty channel occupancy should be 0" ) ;
720+ Assert . IsNotNull ( channelData . Occupants , "Occupants should be an empty list, not null" ) ;
721+ Assert . AreEqual ( 0 , channelData . Occupants . Count , "empty channel should have no occupants" ) ;
722+ }
723+
724+ [ Test ]
725+ public static void IfHereNowWithoutUUIDsIsCalledOnMultipleChannelsThenEachOccupancyShouldBeCorrect ( )
726+ {
727+ // Multiple channels always return the payload format with per-channel occupancy, even with disable_uuids.
728+ string serverResponse = "{\" status\" : 200, \" message\" : \" OK\" , \" payload\" : {\" channels\" : {\" mocha\" : {\" occupancy\" : 3}, \" chabc\" : {\" occupancy\" : 5}}, \" total_channels\" : 2, \" total_occupancy\" : 8}, \" service\" : \" Presence\" }" ;
729+
730+ PNHereNowResult result = ParseHereNowResponse ( serverResponse , "mocha,chabc" ) ;
731+
732+ Assert . IsNotNull ( result , "here_now result not parsed" ) ;
733+ Assert . AreEqual ( 8 , result . TotalOccupancy , "TotalOccupancy mismatch" ) ;
734+ Assert . AreEqual ( 2 , result . TotalChannels , "TotalChannels mismatch" ) ;
735+ Assert . IsTrue ( result . Channels . TryGetValue ( "mocha" , out var mochaData ) , "mocha channel data missing" ) ;
736+ Assert . AreEqual ( 3 , mochaData . Occupancy , "mocha occupancy mismatch" ) ;
737+ Assert . IsTrue ( result . Channels . TryGetValue ( "chabc" , out var chabcData ) , "chabc channel data missing" ) ;
738+ Assert . AreEqual ( 5 , chabcData . Occupancy , "chabc occupancy mismatch" ) ;
739+ }
740+
741+
629742 [ Test ]
630743 public static void IfHereNowIsCalledThenItShouldReturnInfoCipher ( )
631744 {
0 commit comments