@@ -1551,5 +1551,159 @@ describe(`createLiveQueryCollection`, () => {
15511551 `Post F` ,
15521552 ] )
15531553 } )
1554+
1555+ it ( `setWindow returns true when no subset loading is triggered` , async ( ) => {
1556+ const extendedUsers = createCollection (
1557+ mockSyncCollectionOptions < User > ( {
1558+ id : `users-no-loading` ,
1559+ getKey : ( user ) => user . id ,
1560+ initialData : [
1561+ { id : 1 , name : `Alice` , active : true } ,
1562+ { id : 2 , name : `Bob` , active : true } ,
1563+ { id : 3 , name : `Charlie` , active : true } ,
1564+ ] ,
1565+ } )
1566+ )
1567+
1568+ const activeUsers = createLiveQueryCollection ( ( q ) =>
1569+ q
1570+ . from ( { user : extendedUsers } )
1571+ . where ( ( { user } ) => eq ( user . active , true ) )
1572+ . orderBy ( ( { user } ) => user . name , `asc` )
1573+ . limit ( 2 )
1574+ )
1575+
1576+ await activeUsers . preload ( )
1577+
1578+ // setWindow should return true when no loading is triggered
1579+ const result = activeUsers . utils . setWindow ( { offset : 1 , limit : 2 } )
1580+ expect ( result ) . toBe ( true )
1581+ } )
1582+
1583+ it ( `setWindow returns and resolves a Promise when async loading is triggered` , async ( ) => {
1584+ // This is an integration test that validates the full async flow:
1585+ // 1. setWindow triggers loading more data
1586+ // 2. Returns a Promise (not true)
1587+ // 3. The Promise waits for loading to complete
1588+ // 4. The Promise resolves once loading is done
1589+
1590+ vi . useFakeTimers ( )
1591+
1592+ try {
1593+ let loadSubsetCallCount = 0
1594+
1595+ const sourceCollection = createCollection < {
1596+ id : number
1597+ value : number
1598+ } > ( {
1599+ id : `source-async-subset-loading` ,
1600+ getKey : ( item ) => item . id ,
1601+ syncMode : `on-demand` ,
1602+ startSync : true ,
1603+ sync : {
1604+ sync : ( { markReady, begin, write, commit } ) => {
1605+ // Provide minimal initial data
1606+ begin ( )
1607+ write ( { type : `insert` , value : { id : 1 , value : 1 } } )
1608+ write ( { type : `insert` , value : { id : 2 , value : 2 } } )
1609+ write ( { type : `insert` , value : { id : 3 , value : 3 } } )
1610+ commit ( )
1611+ markReady ( )
1612+
1613+ return {
1614+ loadSubset : ( ) => {
1615+ loadSubsetCallCount ++
1616+
1617+ // First call is for the initial window request
1618+ if ( loadSubsetCallCount === 1 ) {
1619+ return true
1620+ }
1621+
1622+ // Second call (triggered by setWindow) returns a promise
1623+ const loadPromise = new Promise < void > ( ( resolve ) => {
1624+ // Simulate async data loading with a delay
1625+ setTimeout ( ( ) => {
1626+ begin ( )
1627+ // Load additional items that would be needed for the new window
1628+ write ( { type : `insert` , value : { id : 4 , value : 4 } } )
1629+ write ( { type : `insert` , value : { id : 5 , value : 5 } } )
1630+ write ( { type : `insert` , value : { id : 6 , value : 6 } } )
1631+ commit ( )
1632+ resolve ( )
1633+ } , 50 )
1634+ } )
1635+
1636+ return loadPromise
1637+ } ,
1638+ }
1639+ } ,
1640+ } ,
1641+ } )
1642+
1643+ const liveQuery = createLiveQueryCollection ( {
1644+ query : ( q ) =>
1645+ q
1646+ . from ( { item : sourceCollection } )
1647+ . orderBy ( ( { item } ) => item . value , `asc` )
1648+ . limit ( 2 )
1649+ . offset ( 0 ) ,
1650+ startSync : true ,
1651+ } )
1652+
1653+ await liveQuery . preload ( )
1654+
1655+ // Initial state: should have 2 items (values 1, 2)
1656+ expect ( liveQuery . size ) . toBe ( 2 )
1657+ expect ( liveQuery . isLoadingSubset ) . toBe ( false )
1658+ expect ( loadSubsetCallCount ) . toBe ( 1 )
1659+
1660+ // Move window to offset 3, which requires loading more data
1661+ // This should trigger loadSubset and return a Promise
1662+ const result = liveQuery . utils . setWindow ( { offset : 3 , limit : 2 } )
1663+
1664+ // CRITICAL VALIDATION: result should be a Promise, not true
1665+ expect ( result ) . toBeInstanceOf ( Promise )
1666+ expect ( result ) . not . toBe ( true )
1667+
1668+ // Advance just a bit to let the scheduler execute and trigger loadSubset
1669+ await vi . advanceTimersByTimeAsync ( 1 )
1670+
1671+ // Verify that loading was triggered and is in progress
1672+ expect ( loadSubsetCallCount ) . toBeGreaterThan ( 1 )
1673+ expect ( liveQuery . isLoadingSubset ) . toBe ( true )
1674+
1675+ // Track when the promise resolves
1676+ let promiseResolved = false
1677+ if ( result !== true ) {
1678+ result . then ( ( ) => {
1679+ promiseResolved = true
1680+ } )
1681+ }
1682+
1683+ // Promise should NOT be resolved yet because loading is still in progress
1684+ await vi . advanceTimersByTimeAsync ( 10 )
1685+ expect ( promiseResolved ) . toBe ( false )
1686+ expect ( liveQuery . isLoadingSubset ) . toBe ( true )
1687+
1688+ // Now advance time to complete the loading (50ms total from loadSubset call)
1689+ await vi . advanceTimersByTimeAsync ( 40 )
1690+
1691+ // Wait for the promise to resolve
1692+ if ( result !== true ) {
1693+ await result
1694+ }
1695+
1696+ // CRITICAL VALIDATION: Promise has resolved and loading is complete
1697+ expect ( promiseResolved ) . toBe ( true )
1698+ expect ( liveQuery . isLoadingSubset ) . toBe ( false )
1699+
1700+ // Verify the window was successfully moved and has the right data
1701+ expect ( liveQuery . size ) . toBe ( 2 )
1702+ const items = liveQuery . toArray
1703+ expect ( items . map ( ( i ) => i . value ) ) . toEqual ( [ 4 , 5 ] )
1704+ } finally {
1705+ vi . useRealTimers ( )
1706+ }
1707+ } )
15541708 } )
15551709} )
0 commit comments