@@ -144,6 +144,11 @@ describe.each([
144
144
subscriber ( messages )
145
145
}
146
146
147
+ function simulateUpToDateOnly ( ) {
148
+ // Send only an up-to-date message with no data changes
149
+ subscriber ( [ { headers : { control : `up-to-date` } } ] )
150
+ }
151
+
147
152
beforeEach ( ( ) => {
148
153
electricCollection = createElectricUsersCollection ( )
149
154
} )
@@ -338,4 +343,98 @@ describe.each([
338
343
expect ( testElectricCollection . status ) . toBe ( `ready` )
339
344
expect ( liveQuery . status ) . toBe ( `ready` )
340
345
} )
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
+ } )
341
440
} )
0 commit comments