@@ -130,6 +130,22 @@ describe(YRedisClient.name, () => {
130130 expect ( result ) . toEqual ( expectedResult ) ;
131131 } ) ;
132132 } ) ;
133+
134+ describe ( 'when redis.readStreams returns null' , ( ) => {
135+ it ( 'should return empty array' , async ( ) => {
136+ // @ts -ignore
137+ redis . readStreams . mockResolvedValueOnce ( [ { name : 'stream1' , messages : null } ] ) ;
138+
139+ const result = await yRedisClient . getMessages ( [
140+ {
141+ key : 'stream1' ,
142+ id : '1' ,
143+ } ,
144+ ] ) ;
145+
146+ expect ( result ) . toEqual ( [ { stream : 'stream1' , messages : [ ] , lastId : '' } ] ) ;
147+ } ) ;
148+ } ) ;
133149 } ) ;
134150
135151 describe ( 'addMessage' , ( ) => {
@@ -350,4 +366,146 @@ describe(YRedisClient.name, () => {
350366 } ) ;
351367 } ) ;
352368 } ) ;
369+
370+ describe ( 'logExistingPendingStructs' , ( ) => {
371+ describe ( 'when document has no pending structures' , ( ) => {
372+ const setup = ( ) => {
373+ const room = 'test-room' ;
374+ const docid = 'test-doc' ;
375+ const ydoc = new Doc ( ) ;
376+ const logger = module . get ( Logger ) ;
377+
378+ return { room, docid, ydoc, logger } ;
379+ } ;
380+
381+ it ( 'should not log warning' , ( ) => {
382+ const { room, docid, ydoc, logger } = setup ( ) ;
383+
384+ // @ts -ignore it is private method
385+ yRedisClient . logExistingPendingStructs ( room , docid , ydoc ) ;
386+
387+ expect ( logger . warning ) . not . toHaveBeenCalled ( ) ;
388+ } ) ;
389+ } ) ;
390+
391+ describe ( 'when document has pending structures' , ( ) => {
392+ const setup = ( ) => {
393+ const room = 'test-room' ;
394+ const docid = 'test-doc' ;
395+ const ydoc = new Doc ( ) ;
396+ const logger = module . get ( Logger ) ;
397+ const mockPendingStructs = {
398+ missing : new Map ( [
399+ [ 1 , 5 ] ,
400+ [ 3 , 2 ] ,
401+ ] ) ,
402+ update : new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 ] ) ,
403+ } ;
404+
405+ // Mock the ydoc.store.pendingStructs
406+ Object . defineProperty ( ydoc . store , 'pendingStructs' , {
407+ value : mockPendingStructs ,
408+ writable : true ,
409+ } ) ;
410+
411+ return { room, docid, ydoc, logger, mockPendingStructs } ;
412+ } ;
413+
414+ it ( 'should log warning with detailed analysis' , ( ) => {
415+ const { room, docid, ydoc, logger } = setup ( ) ;
416+
417+ // @ts -ignore it is private method
418+ yRedisClient . logExistingPendingStructs ( room , docid , ydoc ) ;
419+
420+ expect ( logger . warning ) . toHaveBeenCalledWith (
421+ `Document ${ room } /${ docid } has pending structures. Details: ${ JSON . stringify ( {
422+ missingStructs : [
423+ [ 1 , 5 ] ,
424+ [ 3 , 2 ] ,
425+ ] ,
426+ updateSize : 5 ,
427+ } ) } `,
428+ ) ;
429+ } ) ;
430+ } ) ;
431+ } ) ;
432+
433+ describe ( 'analyzePendingStructs' , ( ) => {
434+ describe ( 'when analyzing pending structures' , ( ) => {
435+ const setup = ( ) => {
436+ const mockPendingStructs = {
437+ missing : new Map ( [
438+ [ 1 , 5 ] ,
439+ [ 3 , 2 ] ,
440+ [ 10 , 1 ] ,
441+ ] ) ,
442+ update : new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ) ,
443+ } ;
444+
445+ return { mockPendingStructs } ;
446+ } ;
447+
448+ it ( 'should return correct analysis with missing structures and update size' , ( ) => {
449+ const { mockPendingStructs } = setup ( ) ;
450+
451+ // @ts -ignore it is private method
452+ const result = yRedisClient . analyzePendingStructs ( mockPendingStructs ) ;
453+
454+ expect ( result ) . toEqual ( {
455+ missingStructs : [
456+ [ 1 , 5 ] ,
457+ [ 3 , 2 ] ,
458+ [ 10 , 1 ] ,
459+ ] ,
460+ updateSize : 7 ,
461+ } ) ;
462+ } ) ;
463+ } ) ;
464+
465+ describe ( 'when missing structures is empty' , ( ) => {
466+ const setup = ( ) => {
467+ const mockPendingStructs = {
468+ missing : new Map ( ) ,
469+ update : new Uint8Array ( [ 1 , 2 , 3 ] ) ,
470+ } ;
471+
472+ return { mockPendingStructs } ;
473+ } ;
474+
475+ it ( 'should handle empty missing structures' , ( ) => {
476+ const { mockPendingStructs } = setup ( ) ;
477+
478+ // @ts -ignore it is private method
479+ const result = yRedisClient . analyzePendingStructs ( mockPendingStructs ) ;
480+
481+ expect ( result ) . toEqual ( {
482+ missingStructs : [ ] ,
483+ updateSize : 3 ,
484+ } ) ;
485+ } ) ;
486+ } ) ;
487+
488+ describe ( 'when update array is empty' , ( ) => {
489+ const setup = ( ) => {
490+ const mockPendingStructs = {
491+ missing : new Map ( [ [ 5 , 10 ] ] ) ,
492+ update : new Uint8Array ( [ ] ) ,
493+ } ;
494+
495+ return { mockPendingStructs } ;
496+ } ;
497+
498+ it ( 'should handle empty update array' , ( ) => {
499+ const { mockPendingStructs } = setup ( ) ;
500+
501+ // @ts -ignore it is private method
502+ const result = yRedisClient . analyzePendingStructs ( mockPendingStructs ) ;
503+
504+ expect ( result ) . toEqual ( {
505+ missingStructs : [ [ 5 , 10 ] ] ,
506+ updateSize : 0 ,
507+ } ) ;
508+ } ) ;
509+ } ) ;
510+ } ) ;
353511} ) ;
0 commit comments