Skip to content

Commit dd4cd61

Browse files
Merge pull request #146 from splitio/add_hooks
Add internal hooks
2 parents 7bda0fe + a2ce834 commit dd4cd61

42 files changed

Lines changed: 386 additions & 322 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ module.exports = {
5555
'compat/compat': ['error', 'defaults, not ie < 11'],
5656
'no-throw-literal': 'error',
5757
'import/no-self-import': 'error',
58-
// 'import/no-default-export': 'error', // Default exports are a common practice in React
58+
'import/no-default-export': 'error',
5959
}
6060
}]
6161
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
},
101101
"husky": {
102102
"hooks": {
103-
"pre-commit": "npm run check",
103+
"pre-commit": "npm run check && npm run build",
104104
"pre-push": "npm test && npm run build"
105105
}
106106
}

src/SplitClient.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import SplitContext from './SplitContext';
2+
import { SplitContext } from './SplitContext';
33
import { ISplitClientProps, ISplitContextValues, IUpdateProps } from './types';
44
import { ERROR_SC_NO_FACTORY } from './constants';
55
import { getStatus, getSplitSharedClient, initAttributes } from './utils';
@@ -119,11 +119,13 @@ export class SplitComponent extends React.Component<IUpdateProps & { factory: Sp
119119
render() {
120120
const { children } = this.props;
121121
return (
122-
<SplitContext.Provider value={this.state} >{
123-
typeof children === 'function' ?
124-
children({ ...this.state }) :
125-
children
126-
}</SplitContext.Provider>
122+
<SplitContext.Provider value={this.state} >
123+
{
124+
typeof children === 'function' ?
125+
children({ ...this.state }) :
126+
children
127+
}
128+
</SplitContext.Provider>
127129
);
128130
}
129131
}
@@ -138,19 +140,17 @@ export class SplitComponent extends React.Component<IUpdateProps & { factory: Sp
138140
*
139141
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#advanced-instantiate-multiple-sdk-clients}
140142
*/
141-
function SplitClient(props: ISplitClientProps) {
143+
export function SplitClient(props: ISplitClientProps) {
142144
return (
143-
<SplitContext.Consumer>{
144-
(splitContext: ISplitContextValues) => {
145+
<SplitContext.Consumer>
146+
{(splitContext: ISplitContextValues) => {
145147
const { factory } = splitContext;
146148
// getSplitSharedClient is idempotent like factory.client: it returns the same client given the same factory, Split Key and TT
147149
const client = factory ? getSplitSharedClient(factory, props.splitKey, props.trafficType, props.attributes) : null;
148150
return (
149151
<SplitComponent {...props} factory={factory} client={client} attributes={props.attributes} />
150152
);
151-
}
152-
}</SplitContext.Consumer>
153+
}}
154+
</SplitContext.Consumer>
153155
);
154156
}
155-
156-
export default SplitClient;

src/SplitContext.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import { EXCEPTION_NO_REACT_OR_CREATECONTEXT } from './constants';
44

55
if (!React || !React.createContext) throw new Error(EXCEPTION_NO_REACT_OR_CREATECONTEXT);
66

7-
/**
8-
* Split Context is the React Context instance that represents our SplitIO global state.
9-
* It contains Split SDK objects, such as a factory instance, a client and its status (isReady, isTimedout, lastUpdate)
10-
* The context is created with default empty values, that eventually SplitFactory and SplitClient access and update.
11-
*/
12-
const SplitContext = React.createContext<ISplitContextValues>({
7+
export const INITIAL_CONTEXT: ISplitContextValues = {
138
client: null,
149
factory: null,
1510
isReady: false,
@@ -18,7 +13,11 @@ const SplitContext = React.createContext<ISplitContextValues>({
1813
hasTimedout: false,
1914
lastUpdate: 0,
2015
isDestroyed: false,
21-
});
16+
}
2217

23-
export default SplitContext;
24-
export { ISplitContextValues };
18+
/**
19+
* Split Context is the React Context instance that represents our SplitIO global state.
20+
* It contains Split SDK objects, such as a factory instance, a client and its status (isReady, isTimedout, lastUpdate)
21+
* The context is created with default empty values, that eventually SplitFactory and SplitClient access and update.
22+
*/
23+
export const SplitContext = React.createContext<ISplitContextValues>(INITIAL_CONTEXT);

src/SplitFactory.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { getSplitFactory, destroySplitFactory, IFactoryWithClients } from './uti
1515
*
1616
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK}
1717
*/
18-
class SplitFactory extends React.Component<ISplitFactoryProps, { factory: SplitIO.IBrowserSDK | null, client: SplitIO.IBrowserClient | null }> {
18+
export class SplitFactory extends React.Component<ISplitFactoryProps, { factory: SplitIO.IBrowserSDK | null, client: SplitIO.IBrowserClient | null }> {
1919

2020
static defaultProps: ISplitFactoryProps = {
2121
updateOnSdkUpdate: false,
@@ -77,5 +77,3 @@ class SplitFactory extends React.Component<ISplitFactoryProps, { factory: SplitI
7777
);
7878
}
7979
}
80-
81-
export default SplitFactory;

src/SplitTreatments.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import memoizeOne from 'memoize-one';
33
import shallowEqual from 'shallowequal';
4-
import SplitContext from './SplitContext';
4+
import { SplitContext } from './SplitContext';
55
import { ISplitTreatmentsProps, ISplitContextValues } from './types';
66
import { getControlTreatmentsWithConfig, WARN_ST_NO_CLIENT } from './constants';
77

@@ -23,7 +23,7 @@ function evaluateFeatureFlags(client: SplitIO.IBrowserClient, lastUpdate: number
2323
*
2424
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#get-treatments-with-configurations}
2525
*/
26-
class SplitTreatments extends React.Component<ISplitTreatmentsProps> {
26+
export class SplitTreatments extends React.Component<ISplitTreatmentsProps> {
2727

2828
private logWarning?: boolean;
2929

@@ -62,5 +62,3 @@ class SplitTreatments extends React.Component<ISplitTreatmentsProps> {
6262
}
6363

6464
}
65-
66-
export default SplitTreatments;

src/__tests__/SplitClient.test.tsx

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import { sdkBrowser } from './testUtils/sdkConfigs';
1111

1212
/** Test target */
1313
import { ISplitClientChildProps } from '../types';
14-
import SplitFactory from '../SplitFactory';
15-
import SplitClient from '../SplitClient';
16-
import SplitContext, { ISplitContextValues } from '../SplitContext';
14+
import { SplitFactory } from '../SplitFactory';
15+
import { SplitClient } from '../SplitClient';
16+
import { SplitContext } from '../SplitContext';
1717
import { ERROR_SC_NO_FACTORY } from '../constants';
1818
import { testAttributesBinding, TestComponentProps } from './testUtils/utils';
1919

@@ -121,7 +121,8 @@ describe('SplitClient', () => {
121121
return null;
122122
}}
123123
</SplitClient>
124-
</SplitFactory>);
124+
</SplitFactory>
125+
);
125126

126127
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY_TIMED_OUT));
127128
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY_FROM_CACHE));
@@ -171,7 +172,8 @@ describe('SplitClient', () => {
171172
return null;
172173
}}
173174
</SplitClient>
174-
</SplitFactory>);
175+
</SplitFactory>
176+
);
175177

176178
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY_TIMED_OUT));
177179
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY));
@@ -216,7 +218,8 @@ describe('SplitClient', () => {
216218
return null;
217219
}}
218220
</SplitClient>
219-
</SplitFactory>);
221+
</SplitFactory>
222+
);
220223

221224
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY_TIMED_OUT));
222225
act(() => (outerFactory as any).client('user2').__emitter__.emit(Event.SDK_READY));
@@ -229,14 +232,16 @@ describe('SplitClient', () => {
229232

230233
const Component = () => {
231234
return (
232-
<SplitContext.Consumer>{(value: ISplitContextValues) => {
233-
expect(value.client).toBe(outerFactory.client('user2'));
234-
expect(value.isReady).toBe(false);
235-
expect(value.isTimedout).toBe(false);
236-
expect(value.lastUpdate).toBe(0);
237-
done();
238-
return null;
239-
}}</SplitContext.Consumer>
235+
<SplitContext.Consumer>
236+
{(value) => {
237+
expect(value.client).toBe(outerFactory.client('user2'));
238+
expect(value.isReady).toBe(false);
239+
expect(value.isTimedout).toBe(false);
240+
expect(value.lastUpdate).toBe(0);
241+
done();
242+
return null;
243+
}}
244+
</SplitContext.Consumer>
240245
);
241246
};
242247

@@ -245,7 +250,8 @@ describe('SplitClient', () => {
245250
<SplitClient splitKey='user2' >
246251
<Component />
247252
</SplitClient>
248-
</SplitFactory>);
253+
</SplitFactory>
254+
);
249255
});
250256

251257
test('logs error and passes null client if rendered outside an SplitProvider component.', () => {
@@ -256,7 +262,8 @@ describe('SplitClient', () => {
256262
expect(client).toBe(null);
257263
return null;
258264
}}
259-
</SplitClient>);
265+
</SplitClient>
266+
);
260267
expect(errorSpy).toBeCalledWith(ERROR_SC_NO_FACTORY);
261268
});
262269

@@ -355,7 +362,8 @@ describe('SplitClient', () => {
355362
const wrapper = render(
356363
<SplitFactory factory={outerFactory} >
357364
<InnerComponent />
358-
</SplitFactory>);
365+
</SplitFactory>
366+
);
359367
});
360368

361369
test('attributes binding test with utility', (done) => {
Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import React from 'react';
22
import { render } from '@testing-library/react';
3-
import SplitContext, { ISplitContextValues } from '../SplitContext';
3+
import { SplitContext } from '../SplitContext';
44

55
/**
66
* Test default SplitContext value
77
*/
88
test('SplitContext.Consumer shows default value', () => {
9-
render(<SplitContext.Consumer>{(value: ISplitContextValues) => {
10-
expect(value.factory).toBe(null);
11-
expect(value.client).toBe(null);
12-
expect(value.isReady).toBe(false);
13-
expect(value.isReadyFromCache).toBe(false);
14-
expect(value.hasTimedout).toBe(false);
15-
expect(value.isTimedout).toBe(false);
16-
expect(value.isDestroyed).toBe(false);
17-
expect(value.lastUpdate).toBe(0);
18-
return null;
19-
}}</SplitContext.Consumer>);
9+
render(
10+
<SplitContext.Consumer>
11+
{(value) => {
12+
expect(value.factory).toBe(null);
13+
expect(value.client).toBe(null);
14+
expect(value.isReady).toBe(false);
15+
expect(value.isReadyFromCache).toBe(false);
16+
expect(value.hasTimedout).toBe(false);
17+
expect(value.isTimedout).toBe(false);
18+
expect(value.isDestroyed).toBe(false);
19+
expect(value.lastUpdate).toBe(0);
20+
return null;
21+
}}
22+
</SplitContext.Consumer>
23+
);
2024
});

0 commit comments

Comments
 (0)