Skip to content

Commit 561d83d

Browse files
Component prop update test
1 parent 53a0a90 commit 561d83d

File tree

2 files changed

+54
-20
lines changed

2 files changed

+54
-20
lines changed

src/SplitFactoryProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function SplitFactoryProvider(props: ISplitFactoryProps) {
2828
}
2929

3030
const [stateFactory, setStateFactory] = React.useState(propFactory || null);
31-
const factory = propFactory || stateFactory;
31+
const factory = propFactory || (stateFactory && config === (stateFactory as IFactoryWithClients).config ? stateFactory : null);
3232
const client = factory ? getSplitClient(factory) : null;
3333

3434
React.useEffect(() => {

src/__tests__/SplitFactoryProvider.test.tsx

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -336,40 +336,74 @@ describe('SplitFactoryProvider', () => {
336336
logSpy.mockRestore();
337337
});
338338

339-
test('cleans up on unmount.', () => {
340-
let destroyMainClientSpy;
341-
let destroySharedClientSpy;
342-
const wrapper = render(
343-
<SplitFactoryProvider config={sdkBrowser} >
344-
{({ factory }) => {
345-
if (!factory) return null; // 1st render
339+
test('cleans up on update and unmount.', () => {
340+
let renderTimes = 0;
341+
const createdFactories = new Set<SplitIO.ISDK>();
342+
const clientDestroySpies: jest.SpyInstance[] = [];
343+
344+
const Component = ({ factory, isReady, hasTimedout }: ISplitFactoryChildProps) => {
345+
renderTimes++;
346+
if (factory) createdFactories.add(factory);
347+
348+
switch (renderTimes) {
349+
case 1:
350+
case 3:
351+
expect(isReady).toBe(false);
352+
expect(hasTimedout).toBe(false);
353+
expect(factory).toBe(null);
354+
return null;
346355

347-
// 2nd render (SDK ready)
356+
case 2:
357+
case 4:
358+
expect(isReady).toBe(true);
359+
expect(hasTimedout).toBe(true);
348360
expect(__factories.size).toBe(1);
349-
destroyMainClientSpy = jest.spyOn((factory as SplitIO.ISDK).client(), 'destroy');
361+
clientDestroySpies.push(jest.spyOn((factory as SplitIO.ISDK).client(), 'destroy'));
350362
return (
351363
<SplitClient splitKey='other_key' >
352364
{({ client }) => {
353-
destroySharedClientSpy = jest.spyOn(client as SplitIO.IClient, 'destroy');
365+
clientDestroySpies.push(jest.spyOn(client as SplitIO.IClient, 'destroy'));
354366
return null;
355367
}}
356368
</SplitClient>
357369
);
358-
}}
359-
</SplitFactoryProvider>
360-
);
370+
case 5:
371+
throw new Error('Child must not be rerendered');
372+
}
373+
};
361374

362-
// SDK ready to re-render
363-
act(() => {
375+
const emitSdkEvents = () => {
364376
const factory = (SplitSdk as jest.Mock).mock.results.slice(-1)[0].value;
377+
factory.client().__emitter__.emit(Event.SDK_READY_TIMED_OUT)
365378
factory.client().__emitter__.emit(Event.SDK_READY)
366-
});
379+
};
380+
381+
// 1st render
382+
const wrapper = render(
383+
<SplitFactoryProvider config={sdkBrowser} >
384+
{Component}
385+
</SplitFactoryProvider>
386+
);
387+
388+
// 2nd render: SDK ready (timeout is ignored due to updateOnSdkTimedout=false)
389+
act(emitSdkEvents);
390+
391+
// 3rd render: Update config prop -> factory is recreated
392+
wrapper.rerender(
393+
<SplitFactoryProvider config={{ ...sdkBrowser }} updateOnSdkReady={false} updateOnSdkTimedout={true} >
394+
{Component}
395+
</SplitFactoryProvider>
396+
);
397+
398+
// 4th render: SDK timeout (ready is ignored due to updateOnSdkReady=false)
399+
act(emitSdkEvents);
367400

368401
wrapper.unmount();
369-
// the factory created by the component is removed from `factories` cache and its clients are destroyed
402+
403+
// Created factories are removed from `factories` cache and their clients are destroyed
404+
expect(createdFactories.size).toBe(2);
370405
expect(__factories.size).toBe(0);
371-
expect(destroyMainClientSpy).toBeCalledTimes(1);
372-
expect(destroySharedClientSpy).toBeCalledTimes(1);
406+
clientDestroySpies.forEach(spy => expect(spy).toBeCalledTimes(1));
373407
});
374408

375409
test('doesn\'t clean up on unmount if the factory is provided as a prop.', () => {

0 commit comments

Comments
 (0)