Skip to content

Commit 38f3a29

Browse files
[FSSDK-8653] OptimizelyVariation with default and variation props set (#227)
* feat: add handling default & variation Issue #86 * test: add coverage for default + variation props * refactor: rename matching variation name * refactor: clean up some listed Problems
1 parent 0d4eb59 commit 38f3a29

File tree

2 files changed

+104
-16
lines changed

2 files changed

+104
-16
lines changed

src/Experiment.spec.tsx

+101-15
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import { ReactSDKClient } from './client';
2525
import { OptimizelyVariation } from './Variation';
2626

2727
describe('<OptimizelyExperiment>', () => {
28-
const variationKey = 'variationResult';
28+
const variationKey = 'matchingVariation';
29+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2930
let resolver: any;
3031
let optimizelyMock: ReactSDKClient;
3132
let isReady: boolean;
@@ -40,12 +41,12 @@ describe('<OptimizelyExperiment>', () => {
4041
});
4142

4243
optimizelyMock = ({
43-
onReady: jest.fn().mockImplementation(config => onReadyPromise),
44-
activate: jest.fn().mockImplementation(experimentKey => variationKey),
45-
onUserUpdate: jest.fn().mockImplementation(handler => () => {}),
44+
onReady: jest.fn().mockImplementation(() => onReadyPromise),
45+
activate: jest.fn().mockImplementation(() => variationKey),
46+
onUserUpdate: jest.fn().mockImplementation(() => () => { }),
4647
notificationCenter: {
47-
addNotificationListener: jest.fn().mockImplementation((type, handler) => {}),
48-
removeNotificationListener: jest.fn().mockImplementation(id => {}),
48+
addNotificationListener: jest.fn().mockImplementation(() => { }),
49+
removeNotificationListener: jest.fn().mockImplementation(() => { }),
4950
},
5051
user: {
5152
id: 'testuser',
@@ -54,7 +55,7 @@ describe('<OptimizelyExperiment>', () => {
5455
isReady: jest.fn().mockImplementation(() => isReady),
5556
getIsReadyPromiseFulfilled: () => true,
5657
getIsUsingSdkKey: () => true,
57-
onForcedVariationsUpdate: jest.fn().mockReturnValue(() => {}),
58+
onForcedVariationsUpdate: jest.fn().mockReturnValue(() => { }),
5859
} as unknown) as ReactSDKClient;
5960
});
6061

@@ -96,7 +97,7 @@ describe('<OptimizelyExperiment>', () => {
9697
</OptimizelyProvider>
9798
);
9899

99-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult'));
100+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation'));
100101

101102
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined);
102103
});
@@ -150,7 +151,7 @@ describe('<OptimizelyExperiment>', () => {
150151
<OptimizelyVariation variation="otherVariation">
151152
<span data-testid="variation-key">other variation</span>
152153
</OptimizelyVariation>
153-
<OptimizelyVariation variation="variationResult">
154+
<OptimizelyVariation variation="matchingVariation">
154155
<span data-testid="variation-key">correct variation</span>
155156
</OptimizelyVariation>
156157
<OptimizelyVariation default>
@@ -203,7 +204,7 @@ describe('<OptimizelyExperiment>', () => {
203204
<OptimizelyVariation default>
204205
<span data-testid="variation-key">default variation</span>
205206
</OptimizelyVariation>
206-
<OptimizelyVariation variation="variationResult">
207+
<OptimizelyVariation variation="matchingVariation">
207208
<span data-testid="variation-key">matching variation</span>
208209
</OptimizelyVariation>
209210
</OptimizelyExperiment>
@@ -246,6 +247,91 @@ describe('<OptimizelyExperiment>', () => {
246247
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('default variation'));
247248
});
248249

250+
describe('a OptimizelyVariation with default & variation props', () => {
251+
it('should render default with NO matching variations ', async () => {
252+
const { container } = render(
253+
<OptimizelyProvider optimizely={optimizelyMock}>
254+
<OptimizelyExperiment experiment="experiment1">
255+
<OptimizelyVariation default variation="nonMatchingVariation">
256+
<span data-testid="variation-key">default & non matching variation</span>
257+
</OptimizelyVariation>
258+
<OptimizelyVariation variation="anotherNonMatchingVariation">
259+
<span data-testid="variation-key">another non-matching variation</span>
260+
</OptimizelyVariation>
261+
</OptimizelyExperiment>
262+
</OptimizelyProvider>
263+
);
264+
265+
// while it's waiting for onReady()
266+
expect(container.innerHTML).toBe('');
267+
268+
// Simulate client becoming ready
269+
resolver.resolve({ success: true });
270+
271+
await optimizelyMock.onReady();
272+
273+
await waitFor(() =>
274+
expect(screen.getByTestId('variation-key')).toHaveTextContent('default & non matching variation')
275+
);
276+
});
277+
278+
it('should render matching variation with a default & non-matching ', async () => {
279+
const { container } = render(
280+
<OptimizelyProvider optimizely={optimizelyMock}>
281+
<OptimizelyExperiment experiment="experiment1">
282+
<OptimizelyVariation default variation="nonMatchingVariation">
283+
<span data-testid="variation-key">default & non matching variation</span>
284+
</OptimizelyVariation>
285+
<OptimizelyVariation variation="matchingVariation">
286+
<span data-testid="variation-key">matching variation</span>
287+
</OptimizelyVariation>
288+
</OptimizelyExperiment>
289+
</OptimizelyProvider>
290+
);
291+
292+
// while it's waiting for onReady()
293+
expect(container.innerHTML).toBe('');
294+
295+
// Simulate client becoming ready
296+
resolver.resolve({ success: true });
297+
298+
await optimizelyMock.onReady();
299+
300+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matching variation'));
301+
});
302+
});
303+
304+
it('should render the last default variation when multiple default props present', async () => {
305+
const { container } = render(
306+
<OptimizelyProvider optimizely={optimizelyMock}>
307+
<OptimizelyExperiment experiment="experiment1">
308+
<OptimizelyVariation default variation="nonMatchingVariation1">
309+
<span data-testid="variation-key">non-matching variation 1</span>
310+
</OptimizelyVariation>
311+
<OptimizelyVariation variation="nonMatchingVariation2">
312+
<span data-testid="variation-key">non-matching variation 2</span>
313+
</OptimizelyVariation>
314+
<OptimizelyVariation default variation="nonMatchingVariation3">
315+
<span data-testid="variation-key">non-matching variation 3</span>
316+
</OptimizelyVariation>
317+
<OptimizelyVariation variation="nonMatchingVariation4">
318+
<span data-testid="variation-key">non-matching variation 4</span>
319+
</OptimizelyVariation>
320+
</OptimizelyExperiment>
321+
</OptimizelyProvider>
322+
);
323+
324+
// while it's waiting for onReady()
325+
expect(container.innerHTML).toBe('');
326+
327+
// Simulate client becoming ready
328+
resolver.resolve({ success: true });
329+
330+
await optimizelyMock.onReady();
331+
332+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('non-matching variation 3'));
333+
});
334+
249335
it('should render an empty string when no default or matching variation is provided', async () => {
250336
const { container } = render(
251337
<OptimizelyProvider optimizely={optimizelyMock}>
@@ -296,7 +382,7 @@ describe('<OptimizelyExperiment>', () => {
296382

297383
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', 'james123', { betaUser: true });
298384

299-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult'));
385+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation'));
300386
});
301387

302388
it('should pass the values for clientReady and didTimeout', async () => {
@@ -319,7 +405,7 @@ describe('<OptimizelyExperiment>', () => {
319405
await optimizelyMock.onReady();
320406

321407
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined);
322-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult|true|false'));
408+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation|true|false'));
323409
});
324410

325411
describe('when the onReady() promise return { success: false }', () => {
@@ -371,7 +457,7 @@ describe('<OptimizelyExperiment>', () => {
371457

372458
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined);
373459

374-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult'));
460+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation'));
375461

376462
// capture the OPTIMIZELY_CONFIG_UPDATE function
377463
// change the return value of activate
@@ -406,7 +492,7 @@ describe('<OptimizelyExperiment>', () => {
406492
await act(async () => await optimizelyMock.onReady());
407493
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined);
408494

409-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult'));
495+
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation'));
410496

411497
// capture the onUserUpdate function
412498
const updateFn = (optimizelyMock.onUserUpdate as jest.Mock).mock.calls[0][0];
@@ -442,7 +528,7 @@ describe('<OptimizelyExperiment>', () => {
442528
<OptimizelyVariation variation="otherVariation">
443529
<span data-testid="variation-key">other variation</span>
444530
</OptimizelyVariation>
445-
<OptimizelyVariation variation="variationResult">
531+
<OptimizelyVariation variation="matchingVariation">
446532
<span data-testid="variation-key">correct variation</span>
447533
</OptimizelyVariation>
448534
<OptimizelyVariation default>

src/Experiment.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ const Experiment: React.FunctionComponent<ExperimentProps> = props => {
7070
if (variation === child.props.variation) {
7171
variationMatch = child;
7272
}
73-
} else if (child.props.default) {
73+
}
74+
// Last child with default prop wins
75+
if (child.props.default) {
7476
defaultMatch = child;
7577
}
7678
});

0 commit comments

Comments
 (0)