@@ -110,16 +110,17 @@ describe("useEligibleMethods", () => {
110110 } ) ;
111111
112112 describe ( "isLoading state" , ( ) => {
113- test ( "should return isLoading=false initially when not fetching " , ( ) => {
113+ test ( "should return isLoading=true when no eligibility data and no error " , ( ) => {
114114 const { result } = renderHook ( ( ) => useEligibleMethods ( ) , {
115115 wrapper : createWrapper ( {
116116 loadingStatus : INSTANCE_LOADING_STATE . PENDING ,
117+ eligiblePaymentMethods : null ,
117118 } ) ,
118119 } ) ;
119120
120- // isLoading reflects isFetching state, not loadingStatus
121- // Initially false because no fetch has started yet (no sdkInstance)
122- expect ( result . current . isLoading ) . toBe ( false ) ;
121+ // isLoading is true when we don't have eligibility data yet
122+ // This prevents UI flash before effect runs
123+ expect ( result . current . isLoading ) . toBe ( true ) ;
123124 } ) ;
124125
125126 test ( "should return isLoading=false when eligibility already in context" , ( ) => {
@@ -139,15 +140,23 @@ describe("useEligibleMethods", () => {
139140 expect ( result . current . isLoading ) . toBe ( false ) ;
140141 } ) ;
141142
142- test ( "should return isLoading=false when context has error" , ( ) => {
143+ test ( "should return isLoading=true when context has error but no eligibility data" , ( ) => {
144+ // Context error (SDK load failure) doesn't set eligibilityError,
145+ // but we still don't have eligibility data, so isLoading is true
143146 const { result } = renderHook ( ( ) => useEligibleMethods ( ) , {
144147 wrapper : createWrapper ( {
145148 loadingStatus : INSTANCE_LOADING_STATE . REJECTED ,
146149 error : new Error ( "Failed" ) ,
150+ eligiblePaymentMethods : null ,
147151 } ) ,
148152 } ) ;
149153
150- expect ( result . current . isLoading ) . toBe ( false ) ;
154+ // isLoading is true because we don't have eligibility data
155+ // The context error is returned separately
156+ expect ( result . current . isLoading ) . toBe ( true ) ;
157+ expect ( result . current . error ?. message ) . toContain (
158+ "PayPal context error" ,
159+ ) ;
151160 } ) ;
152161 } ) ;
153162
@@ -185,26 +194,28 @@ describe("useEligibleMethods", () => {
185194 } ) ,
186195 } ) ;
187196
188- // isLoading is false because no fetch has started (no sdkInstance)
197+ // isLoading is true because we don't have eligibility data yet
198+ // This prevents UI flash before the effect has a chance to run
189199 expect ( result . current ) . toEqual ( {
190200 eligiblePaymentMethods : null ,
191- isLoading : false ,
201+ isLoading : true ,
192202 error : null ,
193203 } ) ;
194204 } ) ;
195205
196- test ( "should return correct shape during error state" , ( ) => {
206+ test ( "should return correct shape during error state with no eligibility " , ( ) => {
197207 const { result } = renderHook ( ( ) => useEligibleMethods ( ) , {
198208 wrapper : createWrapper ( {
199209 eligiblePaymentMethods : null ,
200210 loadingStatus : INSTANCE_LOADING_STATE . REJECTED ,
201211 } ) ,
202212 } ) ;
203213
204- // Error from hook's local state, not context
214+ // isLoading is true because we have no eligibility data and no eligibility error
215+ // (context error is different from eligibility fetch error)
205216 expect ( result . current ) . toEqual ( {
206217 eligiblePaymentMethods : null ,
207- isLoading : false ,
218+ isLoading : true ,
208219 error : null ,
209220 } ) ;
210221 } ) ;
@@ -298,7 +309,7 @@ describe("useEligibleMethods", () => {
298309 expect ( mockDispatch ) . not . toHaveBeenCalled ( ) ;
299310 } ) ;
300311
301- test ( "should set isLoading=true while fetching and false after " , async ( ) => {
312+ test ( "should set isLoading=true while fetching" , async ( ) => {
302313 let resolvePromise : ( value : unknown ) => void ;
303314 const pendingPromise = new Promise ( ( resolve ) => {
304315 resolvePromise = resolve ;
@@ -315,13 +326,33 @@ describe("useEligibleMethods", () => {
315326 } ) ,
316327 } ) ;
317328
318- // Effect runs synchronously, so isLoading is already true
329+ // isLoading is true because no eligibility data yet
319330 expect ( result . current . isLoading ) . toBe ( true ) ;
320331
321- // After promise resolves, should be false
332+ // After promise resolves, isLoading is still true because
333+ // eligiblePaymentMethods in context hasn't been updated
334+ // (dispatch is mocked). In real usage, context would update.
322335 await act ( async ( ) => {
323336 resolvePromise ! ( mockEligibilityResult ) ;
324337 } ) ;
338+ // The fetch itself completes but context isn't updated in this test setup
339+ // so isLoading remains true. See "isLoading state" tests for cases
340+ // where eligibility is in context.
341+ expect ( result . current . isLoading ) . toBe ( true ) ;
342+ } ) ;
343+
344+ test ( "should return isLoading=false when eligibility data exists" , ( ) => {
345+ const mockSdkInstance = createMockSdkInstance ( ) ;
346+
347+ const { result } = renderHook ( ( ) => useEligibleMethods ( ) , {
348+ wrapper : createWrapper ( {
349+ sdkInstance : mockSdkInstance ,
350+ eligiblePaymentMethods : mockEligibilityResult ,
351+ loadingStatus : INSTANCE_LOADING_STATE . RESOLVED ,
352+ } ) ,
353+ } ) ;
354+
355+ // isLoading is false because eligibility data exists in context
325356 expect ( result . current . isLoading ) . toBe ( false ) ;
326357 } ) ;
327358
0 commit comments