Skip to content

Commit ed35f05

Browse files
committed
test globally nested context
Signed-off-by: Will Chou <[email protected]>
1 parent 097e1c3 commit ed35f05

File tree

1 file changed

+129
-48
lines changed

1 file changed

+129
-48
lines changed

packages/react/test/provider.spec.tsx

Lines changed: 129 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import { EvaluationContext, OpenFeature } from '@openfeature/web-sdk';
1+
import { EvaluationContext, InMemoryProvider, OpenFeature } from '@openfeature/web-sdk';
22
import '@testing-library/jest-dom'; // see: https://testing-library.com/docs/react-testing-library/setup
33
import { render, renderHook, screen, waitFor, fireEvent, act } from '@testing-library/react';
44
import * as React from 'react';
5-
import { OpenFeatureProvider, useOpenFeatureClient, useWhenProviderReady, useContextMutator, useStringFlagValue } from '../src';
5+
import {
6+
OpenFeatureProvider,
7+
useOpenFeatureClient,
8+
useWhenProviderReady,
9+
useContextMutator,
10+
useStringFlagValue,
11+
} from '../src';
612
import { TestingProvider } from './test.utils';
713

814
describe('OpenFeatureProvider', () => {
@@ -139,74 +145,149 @@ describe('OpenFeatureProvider', () => {
139145
await waitFor(() => expect(screen.queryByText('👍')).toBeInTheDocument(), { timeout: DELAY * 2 });
140146
});
141147
});
148+
});
149+
describe('useMutateContext', () => {
150+
const MutateButton = () => {
151+
const { setContext } = useContextMutator();
142152

143-
describe('useMutateContext', () => {
144-
const MutateButton = () => {
145-
const { mutateContext } = useContextMutator();
146-
147-
return <button onClick={() => mutateContext({ user: '[email protected]' })}>Update Context</button>;
148-
};
149-
const TestComponent = ({ name }: { name: string}) => {
150-
const flagValue = useStringFlagValue<'hi' | 'bye' | 'aloha'>(SUSPENSE_FLAG_KEY, 'hi');
153+
return <button onClick={() => setContext({ user: '[email protected]' })}>Update Context</button>;
154+
};
155+
const TestComponent = ({ name }: { name: string }) => {
156+
const flagValue = useStringFlagValue<'hi' | 'bye' | 'aloha'>(SUSPENSE_FLAG_KEY, 'hi');
151157

152-
return <div>
158+
return (
159+
<div>
153160
<MutateButton />
154161
<div>{`${name} says ${flagValue}`}</div>
155-
</div>;
156-
};
162+
</div>
163+
);
164+
};
157165

158-
it('should update context when a domain is set', async () => {
159-
const DOMAIN = 'mutate-context-tests';
160-
OpenFeature.setProvider(DOMAIN, suspendingProvider());
161-
render(<OpenFeatureProvider domain={DOMAIN}>
166+
it('should update context when a domain is set', async () => {
167+
const DOMAIN = 'mutate-context-tests';
168+
OpenFeature.setProvider(DOMAIN, suspendingProvider());
169+
render(
170+
<OpenFeatureProvider domain={DOMAIN}>
162171
<React.Suspense fallback={<div>{FALLBACK}</div>}>
163-
<TestComponent name="Will"/>
172+
<TestComponent name="Will" />
164173
</React.Suspense>
165-
</OpenFeatureProvider>,);
174+
</OpenFeatureProvider>,
175+
);
166176

167-
await waitFor(() => {
168-
expect(screen.getByText('Will says hi')).toBeInTheDocument();
169-
});
177+
await waitFor(() => {
178+
expect(screen.getByText('Will says hi')).toBeInTheDocument();
179+
});
170180

171-
act(() => {
172-
fireEvent.click(screen.getByText('Update Context'));
173-
});
174-
await waitFor(() => {
175-
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
176-
}, { timeout: DELAY * 4 });
181+
act(() => {
182+
fireEvent.click(screen.getByText('Update Context'));
177183
});
184+
await waitFor(
185+
() => {
186+
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
187+
},
188+
{ timeout: DELAY * 4 },
189+
);
190+
});
178191

179-
it('should update nested contexts', async () => {
180-
const DOMAIN1 = 'Wills Domain';
181-
const DOMAIN2 = 'Todds Domain';
182-
OpenFeature.setProvider(DOMAIN1, suspendingProvider());
183-
OpenFeature.setProvider(DOMAIN2, suspendingProvider());
184-
render(<OpenFeatureProvider domain={DOMAIN1}>
192+
it('should update nested contexts', async () => {
193+
const DOMAIN1 = 'Wills Domain';
194+
const DOMAIN2 = 'Todds Domain';
195+
OpenFeature.setProvider(DOMAIN1, suspendingProvider());
196+
OpenFeature.setProvider(DOMAIN2, suspendingProvider());
197+
render(
198+
<OpenFeatureProvider domain={DOMAIN1}>
185199
<React.Suspense fallback={<div>{FALLBACK}</div>}>
186-
<TestComponent name="Will"/>
200+
<TestComponent name="Will" />
187201
<OpenFeatureProvider domain={DOMAIN2}>
188202
<React.Suspense fallback={<div>{FALLBACK}</div>}>
189-
<TestComponent name="Todd"/>
203+
<TestComponent name="Todd" />
190204
</React.Suspense>
191205
</OpenFeatureProvider>
192206
</React.Suspense>
193-
</OpenFeatureProvider>,);
207+
</OpenFeatureProvider>,
208+
);
194209

195-
await waitFor(() => {
196-
expect(screen.getByText('Todd says hi')).toBeInTheDocument();
197-
});
210+
await waitFor(() => {
211+
expect(screen.getByText('Todd says hi')).toBeInTheDocument();
212+
});
198213

199-
act(() => {
200-
// Click the Update context button in Todds domain
201-
fireEvent.click(screen.getAllByText('Update Context')[1]);
202-
});
203-
await waitFor(() => {
214+
act(() => {
215+
// Click the Update context button in Todds domain
216+
fireEvent.click(screen.getAllByText('Update Context')[1]);
217+
});
218+
await waitFor(
219+
() => {
204220
expect(screen.getByText('Todd says aloha')).toBeInTheDocument();
205-
}, { timeout: DELAY * 4 });
206-
await waitFor(() => {
221+
},
222+
{ timeout: DELAY * 4 },
223+
);
224+
await waitFor(
225+
() => {
207226
expect(screen.getByText('Will says hi')).toBeInTheDocument();
208-
}, { timeout: DELAY * 4 });
227+
},
228+
{ timeout: DELAY * 4 },
229+
);
230+
});
231+
232+
it('should update nested global contexts', async () => {
233+
const DOMAIN1 = 'Wills Domain';
234+
OpenFeature.setProvider(DOMAIN1, suspendingProvider());
235+
OpenFeature.setProvider(new InMemoryProvider({
236+
globalFlagsHere: {
237+
defaultVariant: 'a',
238+
variants: {
239+
a: 'Smile',
240+
b: 'Frown',
241+
},
242+
disabled: false,
243+
contextEvaluator: (ctx: EvaluationContext) => {
244+
if (ctx.user === '[email protected]') {
245+
return 'b';
246+
}
247+
248+
return 'a';
249+
},
250+
}
251+
}));
252+
const GlobalComponent = ({ name }: { name: string }) => {
253+
const flagValue = useStringFlagValue<'b' | 'a'>('globalFlagsHere', 'a');
254+
255+
return (
256+
<div>
257+
<MutateButton />
258+
<div>{`${name} likes to ${flagValue}`}</div>
259+
</div>
260+
);
261+
};
262+
render(
263+
<OpenFeatureProvider domain={DOMAIN1}>
264+
<React.Suspense fallback={<div>{FALLBACK}</div>}>
265+
<TestComponent name="Will" />
266+
<OpenFeatureProvider>
267+
<React.Suspense fallback={<div>{FALLBACK}</div>}>
268+
<GlobalComponent name="Todd" />
269+
</React.Suspense>
270+
</OpenFeatureProvider>
271+
</React.Suspense>
272+
</OpenFeatureProvider>,
273+
);
274+
275+
await waitFor(() => {
276+
expect(screen.getByText('Todd likes to Smile')).toBeInTheDocument();
209277
});
278+
279+
act(() => {
280+
// Click the Update context button in Todds domain
281+
fireEvent.click(screen.getAllByText('Update Context')[1]);
282+
});
283+
await waitFor(
284+
() => {
285+
expect(screen.getByText('Todd likes to Frown')).toBeInTheDocument();
286+
},
287+
{ timeout: DELAY * 4 },
288+
);
289+
290+
expect(screen.getByText('Will says hi')).toBeInTheDocument();
210291
});
211292
});
212293
});

0 commit comments

Comments
 (0)