@@ -18,14 +18,35 @@ export function createProgressiveTestSuite(
1818) {
1919 describe ( `Progressive Mode Suite (Electric only)` , ( ) => {
2020 describe ( `Basic Progressive Mode` , ( ) => {
21- it ( `should validate snapshot phase behavior and atomic swap with status transition` , async ( ) => {
21+ it ( `should explicitly validate snapshot phase and atomic swap transition` , async ( ) => {
2222 const config = await getConfig ( )
23- if ( ! config . collections . progressive ) {
24- return // Skip if progressive collections not available
23+ if ( ! config . collections . progressive || ! config . progressiveTestControl ) {
24+ return // Skip if progressive collections or test control not available
2525 }
2626 const progressiveUsers = config . collections . progressive . users
2727
28- // Create a query - this will trigger a snapshot fetch if still in snapshot phase
28+ // Start sync for this test
29+ progressiveUsers . startSyncImmediate ( )
30+
31+ // === PHASE 1: SNAPSHOT PHASE ===
32+ // Collection might already be ready from a previous test
33+ // (progressive collections are shared and not cleaned up between tests)
34+ await new Promise ( ( resolve ) => setTimeout ( resolve , 50 ) )
35+
36+ const initialStatus = progressiveUsers . status
37+
38+ // If already ready, we can't test the explicit transition
39+ if ( initialStatus === `ready` ) {
40+ console . log (
41+ `Progressive collection already ready, skipping explicit transition test`
42+ )
43+ return
44+ }
45+
46+ // Should be loading or idle (hook prevents marking ready)
47+ expect ( [ `idle` , `loading` ] ) . toContain ( initialStatus )
48+
49+ // Create a query - this triggers fetchSnapshot
2950 const query = createLiveQueryCollection ( ( q ) =>
3051 q
3152 . from ( { user : progressiveUsers } )
@@ -35,49 +56,47 @@ export function createProgressiveTestSuite(
3556 await query . preload ( )
3657 await waitForQueryData ( query , { minSize : 1 , timeout : 10000 } )
3758
38- const querySize = query . size
39- const queryItems = Array . from ( query . values ( ) )
59+ // Validate snapshot data
60+ const snapshotQuerySize = query . size
61+ const snapshotItems = Array . from ( query . values ( ) )
4062
41- // Validate query data
42- expect ( querySize ) . toBeGreaterThan ( 0 )
43- queryItems . forEach ( ( user ) => {
63+ expect ( snapshotQuerySize ) . toBeGreaterThan ( 0 )
64+ snapshotItems . forEach ( ( user ) => {
4465 expect ( user . age ) . toBe ( 25 )
4566 expect ( user . id ) . toBeDefined ( )
67+ expect ( user . name ) . toBeDefined ( )
4668 } )
4769
48- // If we're still loading, we should be in snapshot phase
49- // Base collection should have data from snapshot (query subset)
50- const statusDuringQuery = progressiveUsers . status
51- if ( statusDuringQuery === `loading` ) {
52- // We're in snapshot phase! Validate snapshot behavior
53- // Collection should have the snapshot data
54- expect ( progressiveUsers . size ) . toBeGreaterThan ( 0 )
55-
56- // But collection size should be <= query size (only snapshot loaded)
57- // Actually it might have multiple snapshots if other tests ran, so just verify we have data
58- expect ( progressiveUsers . size ) . toBeGreaterThan ( 0 )
59- }
70+ // Collection should STILL be loading (paused before atomic swap)
71+ expect ( progressiveUsers . status ) . toBe ( `loading` )
72+
73+ // Collection has snapshot data
74+ const snapshotCollectionSize = progressiveUsers . size
75+ expect ( snapshotCollectionSize ) . toBeGreaterThan ( 0 )
6076
61- // Wait for full sync to complete
77+ // === PHASE 2: TRIGGER ATOMIC SWAP ===
78+ config . progressiveTestControl . releaseInitialSync ( )
79+
80+ // === PHASE 3: POST-SWAP (FULLY SYNCED) ===
81+ // Wait for ready (atomic swap complete)
6282 await waitFor ( ( ) => progressiveUsers . status === `ready` , {
6383 timeout : 30000 ,
6484 message : `Progressive collection did not complete sync` ,
6585 } )
6686
67- // After atomic swap to full synced state
68- // Collection should have ALL users (not just age=25)
87+ // Collection now has full dataset (more than just snapshot)
6988 const finalCollectionSize = progressiveUsers . size
70- expect ( finalCollectionSize ) . toBeGreaterThan ( querySize ) // More than just our query subset
89+ expect ( finalCollectionSize ) . toBeGreaterThan ( snapshotQuerySize )
7190
72- // Query should still work with consistent data
91+ // Query still works with consistent data
7392 const finalQueryItems = Array . from ( query . values ( ) )
7493 finalQueryItems . forEach ( ( user ) => {
7594 expect ( user . age ) . toBe ( 25 ) // Still matches predicate
7695 expect ( user . id ) . toBeDefined ( )
7796 } )
7897
79- // Verify some of the original snapshot items are still present
80- queryItems . forEach ( ( originalUser ) => {
98+ // Verify original snapshot items are still present after swap
99+ snapshotItems . forEach ( ( originalUser ) => {
81100 const foundInCollection = progressiveUsers . get ( originalUser . id )
82101 expect ( foundInCollection ) . toBeDefined ( )
83102 expect ( foundInCollection ?. age ) . toBe ( 25 )
@@ -93,11 +112,10 @@ export function createProgressiveTestSuite(
93112 }
94113 const progressiveUsers = config . collections . progressive . users
95114
96- // Progressive collections should only be marked ready AFTER first up-to-date
97- // If already ready, the full sync completed very fast - we can still test the end state
98- const wasStillLoading = progressiveUsers . status === `loading`
115+ // Start sync for this test
116+ progressiveUsers . startSyncImmediate ( )
99117
100- // Query a subset
118+ // Query a subset (triggers snapshot fetch)
101119 const query = createLiveQueryCollection ( ( q ) =>
102120 q
103121 . from ( { user : progressiveUsers } )
@@ -106,9 +124,17 @@ export function createProgressiveTestSuite(
106124
107125 await query . preload ( )
108126
109- // Wait for query to have data (either from snapshot during loading, or from final state if already ready)
127+ // Wait for query to have snapshot data
110128 await waitForQueryData ( query , { minSize : 1 , timeout : 10000 } )
111129
130+ // Collection should still be loading if test control is active
131+ const wasStillLoading = progressiveUsers . status === `loading`
132+
133+ // Release the initial sync to allow atomic swap
134+ if ( config . progressiveTestControl ) {
135+ config . progressiveTestControl . releaseInitialSync ( )
136+ }
137+
112138 const beforeSwapSize = query . size
113139 const beforeSwapItems = Array . from ( query . values ( ) )
114140
@@ -158,6 +184,9 @@ export function createProgressiveTestSuite(
158184 }
159185 const progressiveUsers = config . collections . progressive . users
160186
187+ // Start sync for this test
188+ progressiveUsers . startSyncImmediate ( )
189+
161190 // Create multiple queries with different predicates
162191 const query1 = createLiveQueryCollection ( ( q ) =>
163192 q
@@ -179,6 +208,11 @@ export function createProgressiveTestSuite(
179208 waitForQueryData ( query2 , { minSize : 1 , timeout : 10000 } ) ,
180209 ] )
181210
211+ // Release initial sync to allow atomic swap
212+ if ( config . progressiveTestControl ) {
213+ config . progressiveTestControl . releaseInitialSync ( )
214+ }
215+
182216 expect ( query1 . size ) . toBeGreaterThan ( 0 )
183217 expect ( query2 . size ) . toBeGreaterThan ( 0 )
184218
@@ -223,7 +257,12 @@ export function createProgressiveTestSuite(
223257 }
224258 const progressiveUsers = config . collections . progressive . users
225259
226- // Wait for full sync first
260+ // Release initial sync immediately (we don't care about snapshot phase for this test)
261+ if ( config . progressiveTestControl ) {
262+ config . progressiveTestControl . releaseInitialSync ( )
263+ }
264+
265+ // Wait for full sync
227266 await waitFor ( ( ) => progressiveUsers . status === `ready` , {
228267 timeout : 30000 ,
229268 message : `Progressive collection did not complete sync` ,
@@ -287,6 +326,11 @@ export function createProgressiveTestSuite(
287326
288327 const snapshotPhaseSize = query . size
289328
329+ // Release initial sync to allow atomic swap
330+ if ( config . progressiveTestControl ) {
331+ config . progressiveTestControl . releaseInitialSync ( )
332+ }
333+
290334 // Wait for atomic swap
291335 await waitFor ( ( ) => progressiveUsers . status === `ready` , {
292336 timeout : 30000 ,
@@ -337,6 +381,11 @@ export function createProgressiveTestSuite(
337381 )
338382 )
339383
384+ // Release initial sync to allow completion
385+ if ( config . progressiveTestControl ) {
386+ config . progressiveTestControl . releaseInitialSync ( )
387+ }
388+
340389 // All should have the same size and same data
341390 const sizes = queries . map ( ( q ) => q . size )
342391 expect ( new Set ( sizes ) . size ) . toBe ( 1 ) // All sizes are identical
@@ -366,8 +415,6 @@ export function createProgressiveTestSuite(
366415 const progressiveUsers = config . collections . progressive . users
367416
368417 // This test verifies the collection can be cleaned up even during snapshot phase
369- // and that the atomic swap doesn't cause issues
370-
371418 const query = createLiveQueryCollection ( ( q ) =>
372419 q
373420 . from ( { user : progressiveUsers } )
@@ -376,6 +423,11 @@ export function createProgressiveTestSuite(
376423
377424 await query . preload ( )
378425
426+ // Release initial sync
427+ if ( config . progressiveTestControl ) {
428+ config . progressiveTestControl . releaseInitialSync ( )
429+ }
430+
379431 // Don't wait for data, just cleanup immediately
380432 await query . cleanup ( )
381433
0 commit comments