@@ -336,40 +336,74 @@ describe('SplitFactoryProvider', () => {
336336 logSpy . mockRestore ( ) ;
337337 } ) ;
338338
339- test ( 'cleans up on unmount.' , ( ) => {
340- let destroyMainClientSpy ;
341- let destroySharedClientSpy ;
342- const wrapper = render (
343- < SplitFactoryProvider config = { sdkBrowser } >
344- { ( { factory } ) => {
345- if ( ! factory ) return null ; // 1st render
339+ test ( 'cleans up on update and unmount.' , ( ) => {
340+ let renderTimes = 0 ;
341+ const createdFactories = new Set < SplitIO . ISDK > ( ) ;
342+ const clientDestroySpies : jest . SpyInstance [ ] = [ ] ;
343+
344+ const Component = ( { factory, isReady, hasTimedout } : ISplitFactoryChildProps ) => {
345+ renderTimes ++ ;
346+ if ( factory ) createdFactories . add ( factory ) ;
347+
348+ switch ( renderTimes ) {
349+ case 1 :
350+ case 3 :
351+ expect ( isReady ) . toBe ( false ) ;
352+ expect ( hasTimedout ) . toBe ( false ) ;
353+ expect ( factory ) . toBe ( null ) ;
354+ return null ;
346355
347- // 2nd render (SDK ready)
356+ case 2 :
357+ case 4 :
358+ expect ( isReady ) . toBe ( true ) ;
359+ expect ( hasTimedout ) . toBe ( true ) ;
348360 expect ( __factories . size ) . toBe ( 1 ) ;
349- destroyMainClientSpy = jest . spyOn ( ( factory as SplitIO . ISDK ) . client ( ) , 'destroy' ) ;
361+ clientDestroySpies . push ( jest . spyOn ( ( factory as SplitIO . ISDK ) . client ( ) , 'destroy' ) ) ;
350362 return (
351363 < SplitClient splitKey = 'other_key' >
352364 { ( { client } ) => {
353- destroySharedClientSpy = jest . spyOn ( client as SplitIO . IClient , 'destroy' ) ;
365+ clientDestroySpies . push ( jest . spyOn ( client as SplitIO . IClient , 'destroy' ) ) ;
354366 return null ;
355367 } }
356368 </ SplitClient >
357369 ) ;
358- } }
359- </ SplitFactoryProvider >
360- ) ;
370+ case 5 :
371+ throw new Error ( 'Child must not be rerendered' ) ;
372+ }
373+ } ;
361374
362- // SDK ready to re-render
363- act ( ( ) => {
375+ const emitSdkEvents = ( ) => {
364376 const factory = ( SplitSdk as jest . Mock ) . mock . results . slice ( - 1 ) [ 0 ] . value ;
377+ factory . client ( ) . __emitter__ . emit ( Event . SDK_READY_TIMED_OUT )
365378 factory . client ( ) . __emitter__ . emit ( Event . SDK_READY )
366- } ) ;
379+ } ;
380+
381+ // 1st render
382+ const wrapper = render (
383+ < SplitFactoryProvider config = { sdkBrowser } >
384+ { Component }
385+ </ SplitFactoryProvider >
386+ ) ;
387+
388+ // 2nd render: SDK ready (timeout is ignored due to updateOnSdkTimedout=false)
389+ act ( emitSdkEvents ) ;
390+
391+ // 3rd render: Update config prop -> factory is recreated
392+ wrapper . rerender (
393+ < SplitFactoryProvider config = { { ...sdkBrowser } } updateOnSdkReady = { false } updateOnSdkTimedout = { true } >
394+ { Component }
395+ </ SplitFactoryProvider >
396+ ) ;
397+
398+ // 4th render: SDK timeout (ready is ignored due to updateOnSdkReady=false)
399+ act ( emitSdkEvents ) ;
367400
368401 wrapper . unmount ( ) ;
369- // the factory created by the component is removed from `factories` cache and its clients are destroyed
402+
403+ // Created factories are removed from `factories` cache and their clients are destroyed
404+ expect ( createdFactories . size ) . toBe ( 2 ) ;
370405 expect ( __factories . size ) . toBe ( 0 ) ;
371- expect ( destroyMainClientSpy ) . toBeCalledTimes ( 1 ) ;
372- expect ( destroySharedClientSpy ) . toBeCalledTimes ( 1 ) ;
406+ clientDestroySpies . forEach ( spy => expect ( spy ) . toBeCalledTimes ( 1 ) ) ;
373407 } ) ;
374408
375409 test ( 'doesn\'t clean up on unmount if the factory is provided as a prop.' , ( ) => {
0 commit comments