55
66import { describe , expect , test } from "vitest" ;
77import { createSignal , createMemo , createResource , useTransition } from "../../src/index.js" ;
8+ import { getSuspenseContext } from "../../src/reactive/signal.js" ;
89import { render , Suspense } from "../src/index.js" ;
910
1011describe ( "Transition memo stale read (#2046)" , ( ) => {
1112 test ( "memo created during transition should not return undefined in committed state" , async ( ) => {
1213 const div = document . createElement ( "div" ) ;
13- const [ route , setRoute ] = createSignal ( "home" ) ;
14+ const [ showDetail , setShowDetail ] = createSignal ( false ) ;
15+ const [ resourceKey , setResourceKey ] = createSignal ( "home" ) ;
1416 const [ dbVersion , setDbVersion ] = createSignal ( 1 ) ;
1517 const [ pending , start ] = useTransition ( ) ;
1618 let dataRef : ( ( ) => { q : number } ) | null = null ;
1719 let resolveResource : ( v : string ) => void ;
1820
19- function RouteComponent ( ) {
20- // Always returns {q:42}. Never undefined.
21- const data = createMemo ( ( ) => ( { q : 42 } ) ) ;
22- // Reads both dbVersion (external signal) and data
23- const label = createMemo ( ( ) => dbVersion ( ) + ": " + data ( ) ! . q ) ;
24- dataRef = data ;
25- return < p > { label ( ) } </ p > ;
26- }
27-
2821 let fetchCount = 0 ;
2922 const dispose = render ( ( ) => {
3023 const [ resource ] = createResource (
31- ( ) => route ( ) ,
24+ ( ) => resourceKey ( ) ,
3225 r => {
3326 fetchCount ++ ;
3427 // First fetch resolves immediately
@@ -39,10 +32,22 @@ describe("Transition memo stale read (#2046)", () => {
3932 } ) ;
4033 }
4134 ) ;
35+ function RouteComponent ( ) {
36+ // Always returns {q:42}. Never undefined.
37+ const data = createMemo ( ( ) => ( { q : 42 } ) ) ;
38+ // Reads both dbVersion (external signal) and data
39+ const label = createMemo ( ( ) => dbVersion ( ) + ": " + data ( ) ! . q ) ;
40+ dataRef = data ;
41+ return (
42+ < >
43+ < p > { label ( ) } </ p >
44+ < p > { resource ( ) ! } </ p >
45+ </ >
46+ ) ;
47+ }
4248 return (
4349 < Suspense fallback = "loading" >
44- < p > { resource ( ) } </ p >
45- { route ( ) === "detail" && < RouteComponent /> }
50+ { showDetail ( ) && < RouteComponent /> }
4651 </ Suspense >
4752 ) ;
4853 } , div ) ;
@@ -51,11 +56,18 @@ describe("Transition memo stale read (#2046)", () => {
5156 await Promise . resolve ( ) ;
5257 await Promise . resolve ( ) ;
5358
59+ // Ensure startTransition creates a real transition in this test environment.
60+ getSuspenseContext ( ) ;
61+
5462 // Navigate via transition — resource refetches, keeps transition pending
55- start ( ( ) => setRoute ( "detail" ) ) ;
56- await Promise . resolve ( ) ;
57- await Promise . resolve ( ) ;
58- await Promise . resolve ( ) ;
63+ const transition = start ( ( ) => {
64+ setShowDetail ( true ) ;
65+ setResourceKey ( "detail" ) ;
66+ } ) ;
67+ for ( let i = 0 ; i < 10 && ( ! dataRef || ! pending ( ) ) ; i ++ ) {
68+ await Promise . resolve ( ) ;
69+ await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
70+ }
5971
6072 // RouteComponent mounted during transition, transition is pending
6173 expect ( dataRef ) . not . toBeNull ( ) ;
@@ -67,6 +79,8 @@ describe("Transition memo stale read (#2046)", () => {
6779 expect ( dataRef ! ( ) ) . toEqual ( { q : 42 } ) ;
6880
6981 resolveResource ! ( "done" ) ;
82+ await transition ;
83+ await Promise . resolve ( ) ;
7084 dispose ( ) ;
7185 } ) ;
7286} ) ;
0 commit comments