@@ -527,4 +527,83 @@ describe('given a BrowserDataManager with mocked dependencies', () => {
527527 '[BrowserDataManager] Identify called after data manager was closed.' ,
528528 ) ;
529529 } ) ;
530+
531+ it ( 'retries initial polling until it succeeds' , async ( ) => {
532+ jest . useFakeTimers ( ) ;
533+ const context = Context . fromLDContext ( { kind : 'user' , key : 'test-user' } ) ;
534+ flagManager . loadCached . mockResolvedValue ( false ) ;
535+
536+ // Mock fetch to fail twice with 500 error, then succeed
537+ let callCount = 0 ;
538+ const mockedFetch = jest . fn ( ) . mockImplementation ( ( ) => {
539+ callCount += 1 ;
540+ if ( callCount <= 2 ) {
541+ return mockResponse ( '' , 500 ) ;
542+ }
543+ return mockResponse ( '{"flagA": true}' , 200 ) ;
544+ } ) ;
545+
546+ platform . requests . fetch = mockedFetch as typeof platform . requests . fetch ;
547+
548+ const identifyResolve = jest . fn ( ) ;
549+ const identifyReject = jest . fn ( ) ;
550+
551+ const identifyOptions : BrowserIdentifyOptions = { initialPollingRetries : 3 } ;
552+ const identifyPromise = dataManager . identify (
553+ identifyResolve ,
554+ identifyReject ,
555+ context ,
556+ identifyOptions ,
557+ ) ;
558+
559+ // Fast-forward through the retry delays (2 retries * 1000ms each)
560+ await jest . advanceTimersByTimeAsync ( 2000 ) ;
561+
562+ await identifyPromise ;
563+
564+ expect ( mockedFetch ) . toHaveBeenCalledTimes ( 3 ) ;
565+ expect ( identifyResolve ) . toHaveBeenCalled ( ) ;
566+ expect ( identifyReject ) . not . toHaveBeenCalled ( ) ;
567+ expect ( flagManager . init ) . toHaveBeenCalledWith (
568+ expect . anything ( ) ,
569+ expect . objectContaining ( { flagA : { flag : true , version : undefined } } ) ,
570+ ) ;
571+
572+ jest . useRealTimers ( ) ;
573+ } ) ;
574+
575+ it ( 'throws an error when initial polling reaches max retry limit' , async ( ) => {
576+ jest . useFakeTimers ( ) ;
577+ const context = Context . fromLDContext ( { kind : 'user' , key : 'test-user' } ) ;
578+ flagManager . loadCached . mockResolvedValue ( false ) ;
579+
580+ // Mock fetch to always fail with 500 error
581+ const mockedFetch = jest . fn ( ) . mockImplementation ( ( ) => mockResponse ( '' , 500 ) ) ;
582+
583+ platform . requests . fetch = mockedFetch as typeof platform . requests . fetch ;
584+
585+ const identifyResolve = jest . fn ( ) ;
586+ const identifyReject = jest . fn ( ) ;
587+
588+ const identifyOptions : BrowserIdentifyOptions = { initialPollingRetries : 2 } ;
589+ const identifyPromise = dataManager . identify (
590+ identifyResolve ,
591+ identifyReject ,
592+ context ,
593+ identifyOptions ,
594+ ) ;
595+
596+ // Fast-forward through the retry delays (2 retries * 1000ms each)
597+ await jest . advanceTimersByTimeAsync ( 2000 ) ;
598+
599+ await identifyPromise ;
600+
601+ // Should attempt initial request + 2 retries = 3 total attempts
602+ expect ( mockedFetch ) . toHaveBeenCalledTimes ( 3 ) ;
603+ expect ( identifyResolve ) . not . toHaveBeenCalled ( ) ;
604+ expect ( identifyReject ) . toHaveBeenCalled ( ) ;
605+ expect ( identifyReject ) . toHaveBeenCalledWith ( expect . objectContaining ( { status : 500 } ) ) ;
606+
607+ jest . useRealTimers ( ) ;
608+ } ) ;
530609} ) ;
0 commit comments