Skip to content

Commit 7c04ec7

Browse files
committed
await context change in useContextMutator setContext
Signed-off-by: MattIPv4 <[email protected]>
1 parent 279f9bf commit 7c04ec7

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

packages/react/src/context/use-context-mutator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ export function useContextMutator(options: ContextMutationOptions = { defaultCon
4141

4242
if (previousContext.current !== resolvedContext) {
4343
if (!domain || options?.defaultContext) {
44-
OpenFeature.setContext(resolvedContext);
44+
await OpenFeature.setContext(resolvedContext);
4545
} else {
46-
OpenFeature.setContext(domain, resolvedContext);
46+
await OpenFeature.setContext(domain, resolvedContext);
4747
}
4848
previousContext.current = resolvedContext;
4949
}

packages/react/test/provider.spec.tsx

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { EvaluationContext} from '@openfeature/web-sdk';
2-
import { InMemoryProvider, OpenFeature } from '@openfeature/web-sdk';
2+
import { InMemoryProvider, OpenFeature, ProviderEvents } from '@openfeature/web-sdk';
33
import '@testing-library/jest-dom'; // see: https://testing-library.com/docs/react-testing-library/setup
44
import { render, renderHook, screen, waitFor, fireEvent, act } from '@testing-library/react';
55
import * as React from 'react';
@@ -164,8 +164,18 @@ describe('OpenFeatureProvider', () => {
164164
describe('useMutateContext', () => {
165165
const MutateButton = ({ setter }: { setter?: (prevContext: EvaluationContext) => EvaluationContext }) => {
166166
const { setContext } = useContextMutator();
167+
const [loading, setLoading] = React.useState(false);
167168

168-
return <button onClick={() => setContext(setter ?? { user: '[email protected]' })}>Update Context</button>;
169+
return (
170+
<button
171+
onClick={() => {
172+
setLoading(true);
173+
setContext(setter ?? { user: '[email protected]' }).finally(() => setLoading(false));
174+
}}
175+
>
176+
{loading ? 'Updating context...' : 'Update Context'}
177+
</button>
178+
);
169179
};
170180

171181
const TestComponent = ({ name, setter }: { name: string; setter?: (prevContext: EvaluationContext) => EvaluationContext }) => {
@@ -182,6 +192,10 @@ describe('OpenFeatureProvider', () => {
182192
it('should update context when a domain is set', async () => {
183193
const DOMAIN = 'mutate-context-tests';
184194
OpenFeature.setProvider(DOMAIN, suspendingProvider());
195+
196+
const changed = jest.fn();
197+
OpenFeature.getClient(DOMAIN).addHandler(ProviderEvents.ContextChanged, changed);
198+
185199
render(
186200
<OpenFeatureProvider domain={DOMAIN}>
187201
<React.Suspense fallback={<div>{FALLBACK}</div>}>
@@ -197,12 +211,17 @@ describe('OpenFeatureProvider', () => {
197211
act(() => {
198212
fireEvent.click(screen.getByText('Update Context'));
199213
});
214+
expect(screen.getByText('Updating context...')).toBeInTheDocument();
215+
200216
await waitFor(
201217
() => {
202-
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
218+
expect(screen.getByText('Update Context')).toBeInTheDocument();
203219
},
204-
{ timeout: DELAY * 4 },
220+
{ timeout: DELAY * 2 },
205221
);
222+
expect(changed).toHaveBeenCalledTimes(1);
223+
224+
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
206225
});
207226

208227
it('should update nested contexts', async () => {
@@ -231,18 +250,17 @@ describe('OpenFeatureProvider', () => {
231250
// Click the Update context button in Todds domain
232251
fireEvent.click(screen.getAllByText('Update Context')[1]);
233252
});
253+
expect(screen.getByText('Updating context...')).toBeInTheDocument();
254+
234255
await waitFor(
235256
() => {
236-
expect(screen.getByText('Todd says aloha')).toBeInTheDocument();
237-
},
238-
{ timeout: DELAY * 4 },
239-
);
240-
await waitFor(
241-
() => {
242-
expect(screen.getByText('Will says hi')).toBeInTheDocument();
257+
expect(screen.getAllByText('Update Context')).toHaveLength(2);
243258
},
244-
{ timeout: DELAY * 4 },
259+
{ timeout: DELAY * 2 },
245260
);
261+
262+
expect(screen.getByText('Todd says aloha')).toBeInTheDocument();
263+
expect(screen.getByText('Will says hi')).toBeInTheDocument();
246264
});
247265

248266
it('should update nested global contexts', async () => {
@@ -296,13 +314,16 @@ describe('OpenFeatureProvider', () => {
296314
// Click the Update context button in Todds domain
297315
fireEvent.click(screen.getAllByText('Update Context')[1]);
298316
});
317+
expect(screen.getByText('Updating context...')).toBeInTheDocument();
318+
299319
await waitFor(
300320
() => {
301-
expect(screen.getByText('Todd likes to Frown')).toBeInTheDocument();
321+
expect(screen.getAllByText('Update Context')).toHaveLength(2);
302322
},
303-
{ timeout: DELAY * 4 },
323+
{ timeout: DELAY * 2 },
304324
);
305325

326+
expect(screen.getByText('Todd likes to Frown')).toBeInTheDocument();
306327
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
307328
});
308329

@@ -326,13 +347,17 @@ describe('OpenFeatureProvider', () => {
326347
act(() => {
327348
fireEvent.click(screen.getByText('Update Context'));
328349
});
350+
expect(screen.getByText('Updating context...')).toBeInTheDocument();
351+
329352
await waitFor(
330353
() => {
331-
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
354+
expect(screen.getByText('Update Context')).toBeInTheDocument();
332355
},
333-
{ timeout: DELAY * 4 },
356+
{ timeout: DELAY * 2 },
334357
);
335358

359+
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
360+
336361
expect(setter).toHaveBeenCalledTimes(1);
337362
expect(setter).toHaveBeenCalledWith({ done: false });
338363
expect(OpenFeature.getContext(DOMAIN)).toEqual({ done: false, user: '[email protected]' });

0 commit comments

Comments
 (0)