@@ -60,7 +60,7 @@ describe('$query token', () => {
6060 const builder = createMockBuilder ( ) ;
6161 const MockModel = { query : vi . fn ( ( ) => builder ) , findAll : vi . fn ( ) } ;
6262 const stores = {
63- spaceStore : { perspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
63+ adamStore : { currentPerspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
6464 $getModel : ( ) => MockModel ,
6565 } ;
6666
@@ -86,7 +86,7 @@ describe('$query token', () => {
8686 const builder = createMockBuilder ( ) ;
8787 const MockModel = { query : vi . fn ( ( ) => builder ) , findAll : vi . fn ( ) } ;
8888 const stores = {
89- spaceStore : { perspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
89+ adamStore : { currentPerspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
9090 $getModel : ( ) => MockModel ,
9191 } ;
9292
@@ -116,7 +116,7 @@ describe('$query token', () => {
116116 const builder = createMockBuilder ( ) ;
117117 const MockModel = { query : vi . fn ( ( ) => builder ) , findAll : vi . fn ( ) } ;
118118 const stores = {
119- spaceStore : { perspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
119+ adamStore : { currentPerspective : ( ) => ( { uuid : 'test-perspective' } ) } ,
120120 $getModel : ( ) => MockModel ,
121121 } ;
122122
@@ -150,7 +150,7 @@ describe('$query token', () => {
150150
151151 const [ perspective , setPerspective ] = createSignal < unknown > ( { uuid : 'perspective-1' } ) ;
152152 const stores = {
153- spaceStore : { perspective } ,
153+ adamStore : { currentPerspective : perspective } ,
154154 $getModel : ( ) => MockModel ,
155155 } ;
156156
@@ -182,7 +182,7 @@ describe('$query token', () => {
182182 it ( 'returns empty array when perspective is null' , async ( ) => {
183183 const MockModel = { query : vi . fn ( ) , findAll : vi . fn ( ) } ;
184184 const stores = {
185- spaceStore : { perspective : ( ) => null } ,
185+ adamStore : { currentPerspective : ( ) => null } ,
186186 $getModel : ( ) => MockModel ,
187187 } ;
188188
@@ -209,7 +209,7 @@ describe('$query token', () => {
209209 findAll : vi . fn ( ( ) => Promise . resolve ( [ { id : 1 } ] ) ) ,
210210 } ;
211211 const stores = {
212- spaceStore : { perspective : ( ) => ( { uuid : 'p1' } ) } ,
212+ adamStore : { currentPerspective : ( ) => ( { uuid : 'p1' } ) } ,
213213 $getModel : ( ) => MockModel ,
214214 } ;
215215
@@ -228,13 +228,105 @@ describe('$query token', () => {
228228 expect ( JSON . parse ( el ?. textContent ?? '[]' ) ) . toEqual ( [ { id : 1 } ] ) ;
229229 } ) ;
230230
231+ // ---- AbortSignal threading + cleanup ----
232+
233+ it ( 'passes an AbortSignal to findAll and aborts it on unmount' , async ( ) => {
234+ let capturedSignal : AbortSignal | undefined ;
235+ const MockModel = {
236+ query : vi . fn ( ) ,
237+ findAll : vi . fn ( ( _p : unknown , _q : unknown , opts : { signal ?: AbortSignal } = { } ) => {
238+ capturedSignal = opts . signal ;
239+ return Promise . resolve ( [ ] ) ;
240+ } ) ,
241+ } ;
242+ const stores = {
243+ adamStore : { currentPerspective : ( ) => ( { uuid : 'p1' } ) } ,
244+ $getModel : ( ) => MockModel ,
245+ } ;
246+
247+ const node : SchemaNode = {
248+ type : 'DataDisplay' ,
249+ props : { data : { $query : { model : 'Post' , subscribe : false } } } ,
250+ } ;
251+
252+ const { unmount } = render ( ( ) => < RenderSchema node = { node } stores = { stores } registry = { registry } /> ) ;
253+ await tick ( ) ;
254+
255+ expect ( MockModel . findAll ) . toHaveBeenCalledOnce ( ) ;
256+ expect ( capturedSignal ) . toBeInstanceOf ( AbortSignal ) ;
257+ expect ( capturedSignal ! . aborted ) . toBe ( false ) ;
258+
259+ // Unmount should trigger onCleanup, which aborts the controller.
260+ unmount ( ) ;
261+ expect ( capturedSignal ! . aborted ) . toBe ( true ) ;
262+ } ) ;
263+
264+ it ( 'aborts a stale findAll when the effect re-runs' , async ( ) => {
265+ const signals : AbortSignal [ ] = [ ] ;
266+ const MockModel = {
267+ query : vi . fn ( ) ,
268+ findAll : vi . fn ( ( _p : unknown , _q : unknown , opts : { signal ?: AbortSignal } = { } ) => {
269+ if ( opts . signal ) signals . push ( opts . signal ) ;
270+ return new Promise < unknown [ ] > ( ( ) => {
271+ // Never resolve — simulate slow query
272+ } ) ;
273+ } ) ,
274+ } ;
275+ const [ perspective , setPerspective ] = createSignal < { uuid : string } | null > ( { uuid : 'p1' } ) ;
276+ const stores = {
277+ adamStore : { currentPerspective : perspective } ,
278+ $getModel : ( ) => MockModel ,
279+ } ;
280+
281+ const node : SchemaNode = {
282+ type : 'DataDisplay' ,
283+ props : { data : { $query : { model : 'Post' , subscribe : false } } } ,
284+ } ;
285+
286+ render ( ( ) => < RenderSchema node = { node } stores = { stores } registry = { registry } /> ) ;
287+ await tick ( ) ;
288+ expect ( signals . length ) . toBe ( 1 ) ;
289+ expect ( signals [ 0 ] . aborted ) . toBe ( false ) ;
290+
291+ // Trigger effect re-run by changing the reactive perspective dep.
292+ setPerspective ( { uuid : 'p2' } ) ;
293+ await tick ( ) ;
294+
295+ // Old run's controller aborted; new run got its own fresh signal.
296+ expect ( signals [ 0 ] . aborted ) . toBe ( true ) ;
297+ expect ( signals . length ) . toBe ( 2 ) ;
298+ expect ( signals [ 1 ] . aborted ) . toBe ( false ) ;
299+ } ) ;
300+
301+ it ( 'swallows AbortError from findAll without surfacing it' , async ( ) => {
302+ const MockModel = {
303+ query : vi . fn ( ) ,
304+ findAll : vi . fn ( ( ) => Promise . reject ( new DOMException ( 'Aborted' , 'AbortError' ) ) ) ,
305+ } ;
306+ const stores = {
307+ adamStore : { currentPerspective : ( ) => ( { uuid : 'p1' } ) } ,
308+ $getModel : ( ) => MockModel ,
309+ } ;
310+
311+ const node : SchemaNode = {
312+ type : 'DataDisplay' ,
313+ props : { data : { $query : { model : 'Post' , subscribe : false } } } ,
314+ } ;
315+
316+ // If the catch arm doesn't swallow AbortError, the unhandled rejection
317+ // would surface as a test failure.
318+ render ( ( ) => < RenderSchema node = { node } stores = { stores } registry = { registry } /> ) ;
319+ await tick ( ) ;
320+ expect ( MockModel . findAll ) . toHaveBeenCalledOnce ( ) ;
321+ } ) ;
322+
231323 // ---- Query params forwarding ----
232324
233325 it ( 'forwards where/order/limit params to query builder' , async ( ) => {
234326 const builder = createMockBuilder ( ) ;
235327 const MockModel = { query : vi . fn ( ( ) => builder ) , findAll : vi . fn ( ) } ;
236328 const stores = {
237- spaceStore : { perspective : ( ) => ( { uuid : 'p1' } ) } ,
329+ adamStore : { currentPerspective : ( ) => ( { uuid : 'p1' } ) } ,
238330 $getModel : ( ) => MockModel ,
239331 } ;
240332
@@ -267,7 +359,7 @@ describe('$query token', () => {
267359 it ( 'warns and returns empty array when $getModel is missing' , async ( ) => {
268360 const warnSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
269361 const stores = {
270- spaceStore : { perspective : ( ) => ( { uuid : 'p1' } ) } ,
362+ adamStore : { currentPerspective : ( ) => ( { uuid : 'p1' } ) } ,
271363 // Note: no $getModel
272364 } ;
273365
0 commit comments