@@ -3,7 +3,7 @@ import { PublicBarekeyClient } from "@barekey/sdk/public";
33import { Component , createElement } from "react" ;
44import { act , create , type ReactTestRenderer } from "react-test-renderer" ;
55
6- import { BarekeyProvider , useBarekey } from "../src/index.js" ;
6+ import { BarekeyProvider , type BarekeyReactEnv , useBarekey } from "../src/index.js" ;
77import { resetBarekeyReactCacheForTests } from "../src/cache.js" ;
88import { resetLeakGuardForTests } from "../src/leak-guard.js" ;
99
@@ -280,7 +280,7 @@ describe("@barekey/react", () => {
280280 } ) ;
281281 } ) ;
282282
283- test ( "supports reads through a caller-provided public client" , async ( ) => {
283+ test ( "supports reads through a caller-provided public client without a provider " , async ( ) => {
284284 (
285285 globalThis as typeof globalThis & {
286286 IS_REACT_ACT_ENVIRONMENT ?: boolean ;
@@ -308,7 +308,7 @@ describe("@barekey/react", () => {
308308 } ) as typeof globalThis . fetch ;
309309
310310 function Theme ( ) {
311- const env = useBarekey ( ) ;
311+ const env = useBarekey ( client ) ;
312312 return createElement ( "span" , null , env . get ( "PUBLIC_THEME" ) ) ;
313313 }
314314
@@ -325,7 +325,6 @@ describe("@barekey/react", () => {
325325 await act ( async ( ) => {
326326 renderer = create (
327327 renderWithClient ( {
328- client,
329328 children : createElement ( Theme ) ,
330329 } ) ,
331330 ) ;
@@ -415,7 +414,103 @@ describe("@barekey/react", () => {
415414 expect ( testDocument . getOverlay ( ) ?. innerHTML ) . toContain ( "<img src=x onerror=alert("xss")>" ) ;
416415 } ) ;
417416
418- test ( "throws a clear error when used outside BarekeyProvider" , ( ) => {
417+ test ( "prefers an explicit client over provider context" , async ( ) => {
418+ (
419+ globalThis as typeof globalThis & {
420+ IS_REACT_ACT_ENVIRONMENT ?: boolean ;
421+ }
422+ ) . IS_REACT_ACT_ENVIRONMENT = true ;
423+ globalThis . fetch = ( async ( _input , init ) => {
424+ expect ( JSON . parse ( String ( init ?. body ?? "" ) ) ) . toEqual ( {
425+ orgSlug : "acme" ,
426+ projectSlug : "web-react-explicit" ,
427+ stageSlug : "production" ,
428+ names : [ "PUBLIC_THEME" ] ,
429+ } ) ;
430+
431+ return jsonResponse ( {
432+ definitions : [
433+ {
434+ name : "PUBLIC_THEME" ,
435+ kind : "secret" ,
436+ declaredType : "string" ,
437+ visibility : "public" ,
438+ value : "dark" ,
439+ } ,
440+ ] ,
441+ } ) ;
442+ } ) as typeof globalThis . fetch ;
443+
444+ const providerClient = new PublicBarekeyClient ( {
445+ organization : "acme" ,
446+ project : "web-react-provider" ,
447+ environment : "production" ,
448+ baseUrl : "https://api.example.test" ,
449+ } ) ;
450+ const explicitClient = new PublicBarekeyClient ( {
451+ organization : "acme" ,
452+ project : "web-react-explicit" ,
453+ environment : "production" ,
454+ baseUrl : "https://api.example.test" ,
455+ } ) ;
456+
457+ function Theme ( ) {
458+ const env = useBarekey ( explicitClient ) ;
459+ return createElement ( "span" , null , env . get ( "PUBLIC_THEME" ) ) ;
460+ }
461+
462+ let renderer ! : ReactTestRenderer ;
463+ await act ( async ( ) => {
464+ renderer = create (
465+ renderWithClient ( {
466+ client : providerClient ,
467+ children : createElement ( Theme ) ,
468+ } ) ,
469+ ) ;
470+ await Promise . resolve ( ) ;
471+ } ) ;
472+
473+ expect ( renderer . toJSON ( ) ) . toEqual ( {
474+ type : "span" ,
475+ props : { } ,
476+ children : [ "dark" ] ,
477+ } ) ;
478+ } ) ;
479+
480+ test ( "returns a stable env object when the resolved client stays the same" , ( ) => {
481+ (
482+ globalThis as typeof globalThis & {
483+ IS_REACT_ACT_ENVIRONMENT ?: boolean ;
484+ }
485+ ) . IS_REACT_ACT_ENVIRONMENT = true ;
486+
487+ const client = new PublicBarekeyClient ( {
488+ organization : "acme" ,
489+ project : "web-react-stable-env" ,
490+ environment : "production" ,
491+ baseUrl : "https://api.example.test" ,
492+ } ) ;
493+ const seen : Array < BarekeyReactEnv > = [ ] ;
494+
495+ function StableEnvProbe ( ) {
496+ const env = useBarekey ( client ) ;
497+ seen . push ( env ) ;
498+ return createElement ( "span" , null , "ok" ) ;
499+ }
500+
501+ let renderer ! : ReactTestRenderer ;
502+ act ( ( ) => {
503+ renderer = create ( createElement ( StableEnvProbe ) ) ;
504+ } ) ;
505+ act ( ( ) => {
506+ renderer . update ( createElement ( StableEnvProbe ) ) ;
507+ } ) ;
508+
509+ expect ( seen ) . toHaveLength ( 2 ) ;
510+ expect ( seen [ 0 ] ) . toBe ( seen [ 1 ] ) ;
511+ } ) ;
512+
513+ test ( "throws a clear error when no client is provided and no provider exists" , ( ) => {
419514 (
420515 globalThis as typeof globalThis & {
421516 IS_REACT_ACT_ENVIRONMENT ?: boolean ;
@@ -440,7 +535,7 @@ describe("@barekey/react", () => {
440535 type : "span" ,
441536 props : { } ,
442537 children : [
443- "[barekey/react] useBarekey() must be used within <BarekeyProvider client={new PublicBarekeyClient(...)} ...>." ,
538+ "[barekey/react] useBarekey() requires a PublicBarekeyClient argument or a parent <BarekeyProvider client={new PublicBarekeyClient(...)} ...>." ,
444539 ] ,
445540 } ) ;
446541 } ) ;
0 commit comments