Skip to content

Commit ca9a7b6

Browse files
refactor withSplitFactory and withSplitClient tests
1 parent 42001c2 commit ca9a7b6

File tree

5 files changed

+69
-57
lines changed

5 files changed

+69
-57
lines changed

jest.config.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ module.exports = {
44
testEnvironment: 'jsdom',
55

66
// Test files are .js, .jsx, .ts and .tsx files inside of __tests__ folders and with a suffix of .test or .spec
7-
testMatch: [ "**/__tests__/**/?(*.)+(spec|test).[jt]s?(x)" ],
7+
testMatch: ['**/__tests__/**/?(*.)+(spec|test).[jt]s?(x)'],
88

99
// Included files for test coverage (npm run test:coverage)
1010
collectCoverageFrom: [
11-
"src/**/*.{js,jsx,ts,tsx}",
12-
"!src/__tests__/**",
11+
'src/**/*.{js,jsx,ts,tsx}',
12+
'!src/__tests__/**',
1313
]
1414
};

src/__tests__/SplitTreatments.test.tsx

+20-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { mount, ReactWrapper } from 'enzyme';
2+
import { render, RenderResult } from '@testing-library/react';
33

44
/** Mocks */
55
import { mockSdk, Event } from './testUtils/mockSplitSdk';
@@ -32,7 +32,7 @@ describe('SplitTreatments', () => {
3232

3333
it('passes as treatments prop the value returned by the function "getControlTreatmentsWithConfig" if the SDK is not ready.', (done) => {
3434
const splitNames = ['split1', 'split2'];
35-
mount(
35+
render(
3636
<SplitFactory config={sdkBrowser} >{
3737
({ factory }) => {
3838
return (
@@ -57,7 +57,7 @@ describe('SplitTreatments', () => {
5757
const outerFactory = SplitSdk(sdkBrowser);
5858
(outerFactory as any).client().__emitter__.emit(Event.SDK_READY);
5959
setTimeout(() => {
60-
mount(
60+
render(
6161
<SplitFactory factory={outerFactory} >{
6262
({ factory, isReady }) => {
6363
expect(getStatus(outerFactory.client()).isReady).toBe(isReady);
@@ -83,7 +83,7 @@ describe('SplitTreatments', () => {
8383
it('logs error and passes control treatments ("getControlTreatmentsWithConfig") if rendered outside an SplitProvider component.', () => {
8484
const splitNames = ['split1', 'split2'];
8585
let passedTreatments;
86-
mount(
86+
render(
8787
<SplitTreatments names={splitNames} >
8888
{({ treatments }: ISplitTreatmentsChildProps) => {
8989
passedTreatments = treatments;
@@ -102,7 +102,7 @@ describe('SplitTreatments', () => {
102102
it('Input validation: invalid "names" and "attributes" props in SplitTreatments.', (done) => {
103103
const splitNames = ['split1', 'split2'];
104104

105-
mount(
105+
render(
106106
<SplitFactory config={sdkBrowser} >{
107107
() => {
108108
return (
@@ -175,49 +175,49 @@ describe('SplitTreatments optimization', () => {
175175
const attributes = { att1: 'att1' };
176176
const splitKey = sdkBrowser.core.key;
177177

178-
let wrapper: ReactWrapper;
178+
let wrapper: RenderResult;
179179

180180
beforeEach(() => {
181181
renderTimes = 0;
182182
(outerFactory.client().getTreatmentsWithConfig as jest.Mock).mockClear();
183-
wrapper = mount(<Component names={names} attributes={attributes} splitKey={splitKey} />);
183+
wrapper = render(<Component names={names} attributes={attributes} splitKey={splitKey} />);
184184
})
185185

186186
afterEach(() => {
187187
wrapper.unmount(); // unmount to remove event listener from factory
188188
})
189189

190190
it('rerenders but does not re-evaluate splits if client, lastUpdate, names and attributes are the same object.', () => {
191-
wrapper.setProps({ names, attributes, splitKey });
191+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={splitKey} />);
192192

193193
expect(renderTimes).toBe(2);
194194
expect(outerFactory.client().getTreatmentsWithConfig).toBeCalledTimes(1);
195195
});
196196

197197
it('rerenders but does not re-evaluate splits if client, lastUpdate, names and attributes are equals (shallow comparison).', () => {
198-
wrapper.setProps({ names: [...names], attributes: { ...attributes }, splitKey });
198+
wrapper.rerender(<Component names={[...names]} attributes={{ ...attributes }} splitKey={splitKey} />);
199199

200200
expect(renderTimes).toBe(2);
201201
expect(outerFactory.client().getTreatmentsWithConfig).toBeCalledTimes(1);
202202
});
203203

204204
it('rerenders and re-evaluates splits if names are not equals (shallow array comparison).', () => {
205-
wrapper.setProps({ names: [...names, 'split3'], attributes: { ...attributes }, splitKey });
205+
wrapper.rerender(<Component names={[...names, 'split3']} attributes={{ ...attributes }} splitKey={splitKey} />);
206206

207207
expect(renderTimes).toBe(2);
208208
expect(outerFactory.client().getTreatmentsWithConfig).toBeCalledTimes(2);
209209
});
210210

211211
it('rerenders and re-evaluates splits if attributes are not equals (shallow object comparison).', () => {
212212
const attributesRef = { ...attributes, att2: 'att2' };
213-
wrapper.setProps({ names: [...names], attributes: attributesRef, splitKey });
213+
wrapper.rerender(<Component names={[...names]} attributes={attributesRef} splitKey={splitKey} />);
214214

215215
expect(renderTimes).toBe(2);
216216
expect(outerFactory.client().getTreatmentsWithConfig).toBeCalledTimes(2);
217217

218218
// If passing same reference but mutated (bad practice), the component re-renders but doesn't re-evaluate splits
219219
attributesRef.att2 = 'att2_val2';
220-
wrapper.setProps({ names: [...names], attributes: attributesRef, splitKey });
220+
wrapper.rerender(<Component names={[...names]} attributes={attributesRef} splitKey={splitKey} />);
221221
expect(renderTimes).toBe(3);
222222
expect(outerFactory.client().getTreatmentsWithConfig).toBeCalledTimes(2);
223223
});
@@ -230,7 +230,7 @@ describe('SplitTreatments optimization', () => {
230230

231231
// State update after destroy doesn't re-evaluate because the sdk is not operational
232232
(outerFactory as any).client().destroy();
233-
wrapper.setProps({ names, attributes, splitKey });
233+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={splitKey} />);
234234

235235
setTimeout(() => {
236236
// Updates were batched as a single render, due to automatic batching https://reactjs.org/blog/2022/03/29/react-v18.html#new-feature-automatic-batching
@@ -245,7 +245,7 @@ describe('SplitTreatments optimization', () => {
245245
});
246246

247247
it('rerenders and re-evaluates splits if client changes.', (done) => {
248-
wrapper.setProps({ names, attributes, splitKey: 'otherKey' });
248+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={'otherKey'} />);
249249
(outerFactory as any).client('otherKey').__emitter__.emit(Event.SDK_READY);
250250

251251
setTimeout(() => {
@@ -266,7 +266,7 @@ describe('SplitTreatments optimization', () => {
266266
let renderTimesComp2 = 0;
267267

268268
// test context updates on SplitFactory
269-
mount(
269+
render(
270270
<SplitFactory factory={outerFactory} updateOnSdkReady={false} updateOnSdkTimedout={true} updateOnSdkUpdate={true} >
271271
<SplitTreatments names={names} attributes={attributes} >
272272
{() => {
@@ -277,7 +277,7 @@ describe('SplitTreatments optimization', () => {
277277
</SplitFactory>);
278278

279279
// test context updates on SplitClient
280-
mount(
280+
render(
281281
<SplitFactory factory={outerFactory} >
282282
<SplitClient splitKey='user2' updateOnSdkReadyFromCache={false} updateOnSdkTimedout={true} updateOnSdkUpdate={true} >
283283
<SplitTreatments names={names} attributes={attributes} >
@@ -333,18 +333,17 @@ describe('SplitTreatments optimization', () => {
333333
}
334334

335335
client.on(client.Event.SDK_READY, () => {
336-
wrapper = mount(<Component names={names} attributes={attributes} splitKey={'emma2'} />);
336+
wrapper = render(<Component names={names} attributes={attributes} splitKey={'emma2'} />);
337337
expect(clientSpy.getTreatmentsWithConfig).toBeCalledTimes(1);
338-
339-
wrapper.setProps({ names, attributes, clientAttributes: { att2: 'att1_val1' } });
338+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={'emma2'} clientAttributes={{ att2: 'att1_val1' }} />);
340339
expect(renderTimes).toBe(3);
341340
expect(clientSpy.getTreatmentsWithConfig).toBeCalledTimes(2);
342341

343-
wrapper.setProps({ names, attributes, clientAttributes: { att2: 'att1_val2' } });
342+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={'emma2'} clientAttributes={{ att2: 'att1_val2' }} />);
344343
expect(renderTimes).toBe(4);
345344
expect(clientSpy.getTreatmentsWithConfig).toBeCalledTimes(3);
346345

347-
wrapper.setProps({ names, attributes, clientAttributes: { att2: 'att1_val2' } });
346+
wrapper.rerender(<Component names={names} attributes={attributes} splitKey={'emma2'} clientAttributes={{ att2: 'att1_val2' }} />);
348347
expect(renderTimes).toBe(5);
349348
expect(clientSpy.getTreatmentsWithConfig).toBeCalledTimes(3); // not called again. clientAttributes object is shallow equal
350349

src/__tests__/testUtils/utils.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { mount } from 'enzyme';
2+
import { render } from '@testing-library/react';
33
const { SplitFactory: originalSplitFactory } = jest.requireActual('@splitsoftware/splitio/client');
44

55
export interface TestComponentProps {
@@ -90,11 +90,11 @@ export function testAttributesBinding(Component: React.FunctionComponent<TestCom
9090
}
9191
}
9292

93-
let wrapper = mount(<Component splitKey='user1' attributesFactory={{ at1: 'at1' }} attributesClient={{ at2: 'at2' }} testSwitch={attributesBindingSwitch} factory={factory} />);
93+
let wrapper = render(<Component splitKey='user1' attributesFactory={{ at1: 'at1' }} attributesClient={{ at2: 'at2' }} testSwitch={attributesBindingSwitch} factory={factory} />);
9494

95-
wrapper.setProps({ attributesFactory: undefined, attributesClient: { at3: 'at3' } });
96-
wrapper.setProps({ attributesFactory: { at4: 'at4' }, attributesClient: undefined });
97-
wrapper.setProps({ attributesFactory: undefined, attributesClient: undefined });
95+
wrapper.rerender(<Component splitKey='user1' attributesFactory={undefined} attributesClient={{ at3: 'at3' }} testSwitch={attributesBindingSwitch} factory={factory} />);
96+
wrapper.rerender(<Component splitKey='user1' attributesFactory={{ at4: 'at4' }} attributesClient={undefined} testSwitch={attributesBindingSwitch} factory={factory} />);
97+
wrapper.rerender(<Component splitKey='user1' attributesFactory={undefined} attributesClient={undefined} testSwitch={attributesBindingSwitch} factory={factory} />);
9898

9999
wrapper.unmount()
100100

@@ -107,10 +107,10 @@ export function testAttributesBinding(Component: React.FunctionComponent<TestCom
107107
client.clearAttributes();
108108
renderTimes = 0;
109109

110-
// @ts-expect-error. With splitKey undefined, mainClient and client refer to the same client instance.
111-
wrapper = mount(<Component splitKey={undefined} attributesFactory={{ at1: 'at1' }} attributesClient={{ at2: 'at2' }} testSwitch={attributesBindingSwitch} factory={factory} />);
110+
// With splitKey undefined, mainClient and client refer to the same client instance.
111+
wrapper = render(<Component splitKey={undefined} attributesFactory={{ at1: 'at1' }} attributesClient={{ at2: 'at2' }} testSwitch={attributesBindingSwitch} factory={factory} />);
112112

113-
wrapper.setProps({ attributesFactory: undefined, attributesClient: { at3: 'at3' } });
114-
wrapper.setProps({ attributesFactory: { at4: 'at4' }, attributesClient: undefined });
115-
wrapper.setProps({ attributesFactory: undefined, attributesClient: undefined });
113+
wrapper.rerender(<Component splitKey={undefined} attributesFactory={undefined} attributesClient={{ at3: 'at3' }} testSwitch={attributesBindingSwitch} factory={factory} />);
114+
wrapper.rerender(<Component splitKey={undefined} attributesFactory={{ at4: 'at4' }} attributesClient={undefined} testSwitch={attributesBindingSwitch} factory={factory} />);
115+
wrapper.rerender(<Component splitKey={undefined} attributesFactory={undefined} attributesClient={undefined} testSwitch={attributesBindingSwitch} factory={factory} />);
116116
}

src/__tests__/withSplitClient.test.tsx

+18-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { mount, shallow } from 'enzyme';
2+
import { render } from '@testing-library/react';
33

44
/** Mocks */
55
import { mockSdk, Event } from './testUtils/mockSplitSdk';
@@ -8,12 +8,13 @@ jest.mock('@splitsoftware/splitio/client', () => {
88
});
99
import { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client';
1010
import { sdkBrowser } from './testUtils/sdkConfigs';
11+
import * as SplitClient from '../SplitClient';
12+
const SplitClientSpy = jest.spyOn(SplitClient, 'default');
13+
import { testAttributesBinding, TestComponentProps } from './testUtils/utils';
1114

1215
/** Test target */
1316
import withSplitFactory from '../withSplitFactory';
1417
import withSplitClient from '../withSplitClient';
15-
import SplitClient from '../SplitClient';
16-
import { testAttributesBinding, TestComponentProps } from './testUtils/utils';
1718

1819
describe('SplitClient', () => {
1920

@@ -25,7 +26,7 @@ describe('SplitClient', () => {
2526
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]);
2627
return null;
2728
}));
28-
mount(<Component />);
29+
render(<Component />);
2930
});
3031

3132
test('passes ready props to the child if client is ready.', (done) => {
@@ -40,7 +41,7 @@ describe('SplitClient', () => {
4041
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]);
4142
return null;
4243
}));
43-
mount(<Component />);
44+
render(<Component />);
4445
done();
4546
});
4647
});
@@ -55,7 +56,7 @@ describe('SplitClient', () => {
5556
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]);
5657
return null;
5758
}));
58-
mount(<Component outerProp1='outerProp1' outerProp2={2} />);
59+
render(<Component outerProp1='outerProp1' outerProp2={2} />);
5960
});
6061

6162
test('passes Status props to SplitClient.', () => {
@@ -65,12 +66,17 @@ describe('SplitClient', () => {
6566
const updateOnSdkReadyFromCache = false;
6667
const Component = withSplitClient('user1')<{ outerProp1: string, outerProp2: number }>(
6768
() => null, updateOnSdkUpdate, updateOnSdkTimedout, updateOnSdkReady, updateOnSdkReadyFromCache);
68-
const wrapper = shallow(<Component outerProp1='outerProp1' outerProp2={2} />);
69-
expect(wrapper.type()).toBe(SplitClient);
70-
expect(wrapper.prop('updateOnSdkUpdate')).toBe(updateOnSdkUpdate);
71-
expect(wrapper.prop('updateOnSdkTimedout')).toBe(updateOnSdkTimedout);
72-
expect(wrapper.prop('updateOnSdkReady')).toBe(updateOnSdkReady);
73-
expect(wrapper.prop('updateOnSdkReadyFromCache')).toBe(updateOnSdkReadyFromCache);
69+
render(<Component outerProp1='outerProp1' outerProp2={2} />);
70+
71+
expect(SplitClientSpy).toHaveBeenLastCalledWith(
72+
expect.objectContaining({
73+
updateOnSdkUpdate,
74+
updateOnSdkTimedout,
75+
updateOnSdkReady,
76+
updateOnSdkReadyFromCache,
77+
}),
78+
expect.anything()
79+
);
7480
});
7581

7682
test('attributes binding test with utility', (done) => {

src/__tests__/withSplitFactory.test.tsx

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { mount, shallow } from 'enzyme';
2+
import { render } from '@testing-library/react';
33

44
/** Mocks */
55
import { mockSdk, Event } from './testUtils/mockSplitSdk';
@@ -8,11 +8,12 @@ jest.mock('@splitsoftware/splitio/client', () => {
88
});
99
import { SplitFactory as SplitSdk } from '@splitsoftware/splitio/client';
1010
import { sdkBrowser } from './testUtils/sdkConfigs';
11+
import SplitFactory from '../SplitFactory';
12+
jest.mock('../SplitFactory');
1113

1214
/** Test target */
1315
import { ISplitFactoryChildProps } from '../types';
1416
import withSplitFactory from '../withSplitFactory';
15-
import SplitFactory from '../SplitFactory';
1617

1718
describe('SplitFactory', () => {
1819

@@ -23,7 +24,7 @@ describe('SplitFactory', () => {
2324
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]);
2425
return null;
2526
});
26-
mount(<Component />);
27+
render(<Component />);
2728
});
2829

2930
test('passes ready props to the child if initialized with a ready factory.', (done) => {
@@ -37,7 +38,7 @@ describe('SplitFactory', () => {
3738
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([true, false, false, false, false, 0]);
3839
return null;
3940
});
40-
mount(<Component />);
41+
render(<Component />);
4142
done();
4243
});
4344
});
@@ -51,7 +52,7 @@ describe('SplitFactory', () => {
5152
expect([isReady, isReadyFromCache, hasTimedout, isTimedout, isDestroyed, lastUpdate]).toStrictEqual([false, false, false, false, false, 0]);
5253
return null;
5354
});
54-
mount(<Component outerProp1='outerProp1' outerProp2={2} />);
55+
render(<Component outerProp1='outerProp1' outerProp2={2} />);
5556
});
5657

5758
test('passes Status props to SplitFactory.', () => {
@@ -61,12 +62,18 @@ describe('SplitFactory', () => {
6162
const updateOnSdkReadyFromCache = false;
6263
const Component = withSplitFactory(sdkBrowser)<{ outerProp1: string, outerProp2: number }>(
6364
() => null, updateOnSdkUpdate, updateOnSdkTimedout, updateOnSdkReady, updateOnSdkReadyFromCache);
64-
const wrapper = shallow(<Component outerProp1='outerProp1' outerProp2={2} />);
65-
expect(wrapper.type()).toBe(SplitFactory);
66-
expect(wrapper.prop('updateOnSdkUpdate')).toBe(updateOnSdkUpdate);
67-
expect(wrapper.prop('updateOnSdkTimedout')).toBe(updateOnSdkTimedout);
68-
expect(wrapper.prop('updateOnSdkReady')).toBe(updateOnSdkReady);
69-
expect(wrapper.prop('updateOnSdkReadyFromCache')).toBe(updateOnSdkReadyFromCache);
65+
66+
render(<Component outerProp1='outerProp1' outerProp2={2} />);
67+
68+
expect(SplitFactory).toHaveBeenLastCalledWith(
69+
expect.objectContaining({
70+
updateOnSdkUpdate,
71+
updateOnSdkTimedout,
72+
updateOnSdkReady,
73+
updateOnSdkReadyFromCache
74+
}),
75+
expect.anything(),
76+
);
7077
});
7178

7279
});

0 commit comments

Comments
 (0)