@@ -51,12 +51,19 @@ describe("ReforgeProvider", () => {
5151 const renderInProvider = ( {
5252 contextAttributes,
5353 onError,
54+ initialFlags,
5455 } : {
5556 contextAttributes ?: { [ key : string ] : Record < string , ContextValue > } ;
5657 onError ?: ( err : Error ) => void ;
58+ initialFlags ?: Record < string , unknown > ;
5759 } ) =>
5860 render (
59- < ReforgeProvider sdkKey = "sdk-key" contextAttributes = { contextAttributes } onError = { onError } >
61+ < ReforgeProvider
62+ sdkKey = "sdk-key"
63+ contextAttributes = { contextAttributes }
64+ onError = { onError }
65+ initialFlags = { initialFlags }
66+ >
6067 < MyComponent />
6168 </ ReforgeProvider >
6269 ) ;
@@ -230,6 +237,38 @@ describe("ReforgeProvider", () => {
230237 expect ( updatedAlert ) . toHaveTextContent ( "UPDATED FROM CONTEXT" ) ;
231238 } ) ;
232239
240+ it . only ( "shows pre-hydrated flags without making a request" , ( ) => {
241+ const context = { user : { email : "test@example.com" } } ;
242+
243+ // Mock the fetch response to return nothing
244+ // If this ran, we would end up rendering only default values
245+ // and no secret feature
246+ global . fetch = jest . fn ( ( ) =>
247+ Promise . resolve ( {
248+ ok : true ,
249+ json : ( ) => ( { evaluations : { } } ) ,
250+ } )
251+ ) as jest . Mock ;
252+
253+ render (
254+ < ReforgeProvider
255+ sdkKey = "sdk-key"
256+ contextAttributes = { context }
257+ onError = { ( ) => { } }
258+ initialFlags = { { greeting : "My seeded greeting" , secretFeature : true } }
259+ >
260+ < MyComponent />
261+ </ ReforgeProvider >
262+ ) ;
263+
264+ const alert = screen . queryByRole ( "alert" ) ;
265+ expect ( alert ) . toHaveTextContent ( "My seeded greeting" ) ;
266+ const banner = screen . queryByRole ( "banner" ) ;
267+ expect ( banner ) . toHaveTextContent ( "Default Subtitle" ) ;
268+ const secretFeature = screen . queryByTitle ( "secret-feature" ) ;
269+ expect ( secretFeature ) . toBeInTheDocument ( ) ;
270+ } ) ;
271+
233272 it ( "allows providing an afterEvaluationCallback" , async ( ) => {
234273 const context = { user : { email : "test@example.com" } } ;
235274
@@ -402,7 +441,7 @@ describe("createReforgeHook functionality with ReforgeProvider", () => {
402441
403442 React . useEffect ( ( ) => {
404443 // Force multiple re-renders
405- if ( counter < 3 ) {
444+ if ( counter < 6 ) {
406445 setTimeout ( ( ) => setCounter ( counter + 1 ) , 10 ) ;
407446 }
408447 } , [ counter ] ) ;
@@ -430,13 +469,16 @@ describe("createReforgeHook functionality with ReforgeProvider", () => {
430469
431470 // Wait for all re-renders to complete
432471 await waitFor ( ( ) => {
433- expect ( screen . getByTestId ( "hook-result" ) ) . toHaveTextContent ( "(Render count: 3 )" ) ;
472+ expect ( screen . getByTestId ( "hook-result" ) ) . toHaveTextContent ( "(Render count: 6 )" ) ;
434473 } ) ;
435474
436- // In ReforgeProvider, constructor may be called twice due to React's strict mode
475+ // In ReforgeProvider, constructor is called:
476+ // - once on initial render
477+ // - once during initialization (set's context key)
478+ // - once for unclear reasons, but unrelated to renders per increased render count in test component
437479 // or the provider's initialization process, which is still valid behavior
438- expect ( constructorSpy ) . toHaveBeenCalledTimes ( 2 ) ;
480+ expect ( constructorSpy ) . toHaveBeenCalledTimes ( 3 ) ;
439481 // Method is called once on initial render, once during initialization, and three more times for re-renders
440- expect ( methodSpy ) . toHaveBeenCalledTimes ( 5 ) ;
482+ expect ( methodSpy ) . toHaveBeenCalledTimes ( 9 ) ;
441483 } ) ;
442484} ) ;
0 commit comments