From 38f3a29455bd845987f1c6e9b1fdfb7fc9b5be3b Mon Sep 17 00:00:00 2001 From: Mike Chu <104384559+mikechu-optimizely@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:39:47 -0500 Subject: [PATCH] [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 --- src/Experiment.spec.tsx | 116 ++++++++++++++++++++++++++++++++++------ src/Experiment.tsx | 4 +- 2 files changed, 104 insertions(+), 16 deletions(-) diff --git a/src/Experiment.spec.tsx b/src/Experiment.spec.tsx index e4dab4e..dab0ff2 100644 --- a/src/Experiment.spec.tsx +++ b/src/Experiment.spec.tsx @@ -25,7 +25,8 @@ import { ReactSDKClient } from './client'; import { OptimizelyVariation } from './Variation'; describe('', () => { - const variationKey = 'variationResult'; + const variationKey = 'matchingVariation'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any let resolver: any; let optimizelyMock: ReactSDKClient; let isReady: boolean; @@ -40,12 +41,12 @@ describe('', () => { }); optimizelyMock = ({ - onReady: jest.fn().mockImplementation(config => onReadyPromise), - activate: jest.fn().mockImplementation(experimentKey => variationKey), - onUserUpdate: jest.fn().mockImplementation(handler => () => {}), + onReady: jest.fn().mockImplementation(() => onReadyPromise), + activate: jest.fn().mockImplementation(() => variationKey), + onUserUpdate: jest.fn().mockImplementation(() => () => { }), notificationCenter: { - addNotificationListener: jest.fn().mockImplementation((type, handler) => {}), - removeNotificationListener: jest.fn().mockImplementation(id => {}), + addNotificationListener: jest.fn().mockImplementation(() => { }), + removeNotificationListener: jest.fn().mockImplementation(() => { }), }, user: { id: 'testuser', @@ -54,7 +55,7 @@ describe('', () => { isReady: jest.fn().mockImplementation(() => isReady), getIsReadyPromiseFulfilled: () => true, getIsUsingSdkKey: () => true, - onForcedVariationsUpdate: jest.fn().mockReturnValue(() => {}), + onForcedVariationsUpdate: jest.fn().mockReturnValue(() => { }), } as unknown) as ReactSDKClient; }); @@ -96,7 +97,7 @@ describe('', () => { ); - await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult')); + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation')); expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined); }); @@ -150,7 +151,7 @@ describe('', () => { other variation - + correct variation @@ -203,7 +204,7 @@ describe('', () => { default variation - + matching variation @@ -246,6 +247,91 @@ describe('', () => { await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('default variation')); }); + describe('a OptimizelyVariation with default & variation props', () => { + it('should render default with NO matching variations ', async () => { + const { container } = render( + + + + default & non matching variation + + + another non-matching variation + + + + ); + + // while it's waiting for onReady() + expect(container.innerHTML).toBe(''); + + // Simulate client becoming ready + resolver.resolve({ success: true }); + + await optimizelyMock.onReady(); + + await waitFor(() => + expect(screen.getByTestId('variation-key')).toHaveTextContent('default & non matching variation') + ); + }); + + it('should render matching variation with a default & non-matching ', async () => { + const { container } = render( + + + + default & non matching variation + + + matching variation + + + + ); + + // while it's waiting for onReady() + expect(container.innerHTML).toBe(''); + + // Simulate client becoming ready + resolver.resolve({ success: true }); + + await optimizelyMock.onReady(); + + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matching variation')); + }); + }); + + it('should render the last default variation when multiple default props present', async () => { + const { container } = render( + + + + non-matching variation 1 + + + non-matching variation 2 + + + non-matching variation 3 + + + non-matching variation 4 + + + + ); + + // while it's waiting for onReady() + expect(container.innerHTML).toBe(''); + + // Simulate client becoming ready + resolver.resolve({ success: true }); + + await optimizelyMock.onReady(); + + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('non-matching variation 3')); + }); + it('should render an empty string when no default or matching variation is provided', async () => { const { container } = render( @@ -296,7 +382,7 @@ describe('', () => { expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', 'james123', { betaUser: true }); - await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult')); + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation')); }); it('should pass the values for clientReady and didTimeout', async () => { @@ -319,7 +405,7 @@ describe('', () => { await optimizelyMock.onReady(); expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined); - await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult|true|false')); + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation|true|false')); }); describe('when the onReady() promise return { success: false }', () => { @@ -371,7 +457,7 @@ describe('', () => { expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined); - await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult')); + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation')); // capture the OPTIMIZELY_CONFIG_UPDATE function // change the return value of activate @@ -406,7 +492,7 @@ describe('', () => { await act(async () => await optimizelyMock.onReady()); expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined); - await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('variationResult')); + await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation')); // capture the onUserUpdate function const updateFn = (optimizelyMock.onUserUpdate as jest.Mock).mock.calls[0][0]; @@ -442,7 +528,7 @@ describe('', () => { other variation - + correct variation diff --git a/src/Experiment.tsx b/src/Experiment.tsx index 22662dd..c84d39e 100644 --- a/src/Experiment.tsx +++ b/src/Experiment.tsx @@ -70,7 +70,9 @@ const Experiment: React.FunctionComponent = props => { if (variation === child.props.variation) { variationMatch = child; } - } else if (child.props.default) { + } + // Last child with default prop wins + if (child.props.default) { defaultMatch = child; } });