@@ -144,6 +144,11 @@ describe.each([
144144 subscriber ( messages )
145145 }
146146
147+ function simulateUpToDateOnly ( ) {
148+ // Send only an up-to-date message with no data changes
149+ subscriber ( [ { headers : { control : `up-to-date` } } ] )
150+ }
151+
147152 beforeEach ( ( ) => {
148153 electricCollection = createElectricUsersCollection ( )
149154 } )
@@ -338,4 +343,98 @@ describe.each([
338343 expect ( testElectricCollection . status ) . toBe ( `ready` )
339344 expect ( liveQuery . status ) . toBe ( `ready` )
340345 } )
346+
347+ it ( `should not emit changes on up-to-date messages with no data changes` , async ( ) => {
348+ // Test to verify that up-to-date messages without actual data changes
349+ // don't trigger unnecessary renders in live query collections
350+
351+ // Create a live query collection
352+ const liveQuery = createLiveQueryCollection ( {
353+ startSync : true ,
354+ query : ( q ) =>
355+ q
356+ . from ( { user : electricCollection } )
357+ . where ( ( { user } ) => eq ( user . active , true ) )
358+ . select ( ( { user } ) => ( {
359+ id : user . id ,
360+ name : user . name ,
361+ active : user . active ,
362+ } ) ) ,
363+ } )
364+
365+ // Track changes emitted by the live query
366+ const changeNotifications : Array < any > = [ ]
367+ const subscription = liveQuery . subscribeChanges ( ( changes ) => {
368+ changeNotifications . push ( changes )
369+ } )
370+
371+ // Initial sync with data
372+ simulateInitialSync ( )
373+ expect ( liveQuery . status ) . toBe ( `ready` )
374+ expect ( liveQuery . size ) . toBe ( 3 ) // Only active users
375+
376+ // Clear any initial change notifications
377+ changeNotifications . length = 0
378+
379+ // Send an up-to-date message with no data changes
380+ // This simulates the scenario where Electric sends up-to-date
381+ // but there are no actual changes to the data
382+ simulateUpToDateOnly ( )
383+
384+ // Wait a tick to ensure any async operations complete
385+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
386+
387+ // The live query should not have emitted any changes
388+ // because there were no actual data changes
389+ expect ( changeNotifications ) . toHaveLength ( 0 )
390+
391+ // Verify the collection is still in ready state
392+ expect ( liveQuery . status ) . toBe ( `ready` )
393+ expect ( liveQuery . size ) . toBe ( 3 )
394+
395+ // Clean up
396+ subscription . unsubscribe ( )
397+ } )
398+
399+ it ( `should not emit changes on multiple consecutive up-to-date messages with no data changes` , async ( ) => {
400+ // Test to verify that multiple consecutive up-to-date messages
401+ // without data changes don't accumulate unnecessary renders
402+
403+ const liveQuery = createLiveQueryCollection ( {
404+ startSync : true ,
405+ query : ( q ) => q . from ( { user : electricCollection } ) ,
406+ } )
407+
408+ // Track changes emitted by the live query
409+ const changeNotifications : Array < any > = [ ]
410+ const subscription = liveQuery . subscribeChanges ( ( changes ) => {
411+ changeNotifications . push ( changes )
412+ } )
413+
414+ // Initial sync
415+ simulateInitialSync ( )
416+ expect ( liveQuery . status ) . toBe ( `ready` )
417+ expect ( liveQuery . size ) . toBe ( 4 )
418+
419+ // Clear initial change notifications
420+ changeNotifications . length = 0
421+
422+ // Send multiple up-to-date messages with no data changes
423+ simulateUpToDateOnly ( )
424+ simulateUpToDateOnly ( )
425+ simulateUpToDateOnly ( )
426+
427+ // Wait for any async operations
428+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
429+
430+ // Should not have emitted any changes despite multiple up-to-date messages
431+ expect ( changeNotifications ) . toHaveLength ( 0 )
432+
433+ // Verify collection state is still correct
434+ expect ( liveQuery . status ) . toBe ( `ready` )
435+ expect ( liveQuery . size ) . toBe ( 4 )
436+
437+ // Clean up
438+ subscription . unsubscribe ( )
439+ } )
341440} )
0 commit comments