Skip to content

Commit 43613fc

Browse files
[FSSDK-9654] fix: Default to VUID without user(id) as Provider prop (#229)
* feat: Use vuid for user.id if user? provided * test: Add missing Optimizely.getVuid jest.fn mock * refactor: Move set user to componentDidMount * test: Update for rejected optimizely.onReady * refactor: Change use sync componentDidMount() lifecycle method * fix: remove localStorage & getVuid use * fix: Separate responsiblities of getUserContextInstance * refactor: getUserContextWithOverrides * fix: Update ReactSDKClient interface * refactor: Update warns + clean up * refactor: DRY + moves + warn updates * refactor: No wait fetchQualifiedSegments on setUser * fix(user): Allow latent setting of user * test: WIP Fixing tests * nit: Format with Prettier * nit: More formatting with Prettier * test: Fix now that instantiation is now async * fix: Remove use sync lifecycle method * test: WIP graceful promise reject test failing * test: WIP replace timers in tests * test: Better timeout handling in jest * refactor: Move client onReady check slightly It really is needed so that vuid in JS SDK is ready * fix: Use FeatureVariableValue; Remove excess checks; Better user assignment * refactor: Remove FeatureVariableValue for now * test: Fix code supported by tests * refactor: Move getUserWithOverrides() back to position * refactor: Move isReady() for easier PR * refactor: Change back to getUserContext() * refactor: Make set and make user context private
1 parent abf633d commit 43613fc

File tree

7 files changed

+174
-203
lines changed

7 files changed

+174
-203
lines changed

src/Experiment.spec.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
/// <reference types="jest" />
18+
1719
import * as React from 'react';
1820
import { act } from 'react-dom/test-utils';
1921
import { render, screen, waitFor } from '@testing-library/react';
@@ -43,10 +45,11 @@ describe('<OptimizelyExperiment>', () => {
4345
optimizelyMock = ({
4446
onReady: jest.fn().mockImplementation(() => onReadyPromise),
4547
activate: jest.fn().mockImplementation(() => variationKey),
46-
onUserUpdate: jest.fn().mockImplementation(() => () => { }),
48+
onUserUpdate: jest.fn().mockImplementation(() => () => {}),
49+
getVuid: jest.fn().mockImplementation(() => 'vuid_95bf72cebc774dfd8e8e580a5a1'),
4750
notificationCenter: {
48-
addNotificationListener: jest.fn().mockImplementation(() => { }),
49-
removeNotificationListener: jest.fn().mockImplementation(() => { }),
51+
addNotificationListener: jest.fn().mockImplementation(() => {}),
52+
removeNotificationListener: jest.fn().mockImplementation(() => {}),
5053
},
5154
user: {
5255
id: 'testuser',
@@ -55,7 +58,7 @@ describe('<OptimizelyExperiment>', () => {
5558
isReady: jest.fn().mockImplementation(() => isReady),
5659
getIsReadyPromiseFulfilled: () => true,
5760
getIsUsingSdkKey: () => true,
58-
onForcedVariationsUpdate: jest.fn().mockReturnValue(() => { }),
61+
onForcedVariationsUpdate: jest.fn().mockReturnValue(() => {}),
5962
} as unknown) as ReactSDKClient;
6063
});
6164

@@ -405,7 +408,9 @@ describe('<OptimizelyExperiment>', () => {
405408
await optimizelyMock.onReady();
406409

407410
expect(optimizelyMock.activate).toHaveBeenCalledWith('experiment1', undefined, undefined);
408-
await waitFor(() => expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation|true|false'));
411+
await waitFor(() =>
412+
expect(screen.getByTestId('variation-key')).toHaveTextContent('matchingVariation|true|false')
413+
);
409414
});
410415

411416
describe('when the onReady() promise return { success: false }', () => {

src/Feature.spec.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
/**
2-
* Copyright 2018-2019, Optimizely
2+
* Copyright 2018-2019, 2023 Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
17+
/// <reference types="jest" />
18+
1619
import * as React from 'react';
1720
import { act } from 'react-dom/test-utils';
1821
import { render, screen, waitFor } from '@testing-library/react';
@@ -45,6 +48,7 @@ describe('<OptimizelyFeature>', () => {
4548
getFeatureVariables: jest.fn().mockImplementation(() => featureVariables),
4649
isFeatureEnabled: jest.fn().mockImplementation(() => isEnabledMock),
4750
onUserUpdate: jest.fn().mockImplementation(handler => () => {}),
51+
getVuid: jest.fn().mockImplementation(() => 'vuid_95bf72cebc774dfd8e8e580a5a1'),
4852
notificationCenter: {
4953
addNotificationListener: jest.fn().mockImplementation((type, handler) => {}),
5054
removeNotificationListener: jest.fn().mockImplementation(id => {}),

src/Provider.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
import * as React from 'react';
1718
import { UserAttributes } from '@optimizely/optimizely-sdk';
1819
import { getLogger } from '@optimizely/optimizely-sdk';
1920

2021
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2122
import { OptimizelyContextProvider } from './Context';
22-
import { ReactSDKClient } from './client';
23+
import { ReactSDKClient, DefaultUser } from './client';
2324
import { areUsersEqual, UserInfo } from './utils';
2425

2526
const logger = getLogger('<OptimizelyProvider>');
@@ -42,9 +43,20 @@ interface OptimizelyProviderState {
4243
export class OptimizelyProvider extends React.Component<OptimizelyProviderProps, OptimizelyProviderState> {
4344
constructor(props: OptimizelyProviderProps) {
4445
super(props);
45-
const { optimizely, userId, userAttributes, user } = props;
46+
}
47+
48+
componentDidMount(): void {
49+
this.setUserInOptimizely();
50+
}
51+
52+
async setUserInOptimizely(): Promise<void> {
53+
const { optimizely, userId, userAttributes, user } = this.props;
54+
55+
if (!optimizely) {
56+
logger.error('OptimizelyProvider must be passed an instance of the Optimizely SDK client');
57+
return;
58+
}
4659

47-
// check if user id/attributes are provided as props and set them ReactSDKClient
4860
let finalUser: UserInfo | null = null;
4961

5062
if (user) {
@@ -65,17 +77,16 @@ export class OptimizelyProvider extends React.Component<OptimizelyProviderProps,
6577
};
6678
// deprecation warning
6779
logger.warn('Passing userId and userAttributes as props is deprecated, please switch to using `user` prop');
80+
} else {
81+
finalUser = DefaultUser;
6882
}
6983

7084
if (finalUser) {
71-
if (!optimizely) {
72-
logger.error(`Unable to set user ${finalUser} because optimizely object does not exist.`)
73-
} else {
74-
try {
75-
optimizely.setUser(finalUser);
76-
} catch (err) {
77-
logger.error(`Unable to set user ${finalUser} because passed in optimizely object does not contain the setUser function.`)
78-
}
85+
try {
86+
await optimizely.onReady();
87+
await optimizely.setUser(finalUser);
88+
} catch {
89+
logger.error('Error while trying to set user.');
7990
}
8091
}
8192
}
@@ -109,7 +120,7 @@ export class OptimizelyProvider extends React.Component<OptimizelyProviderProps,
109120
}
110121
}
111122

112-
render() {
123+
render(): JSX.Element {
113124
const { optimizely, children, timeout } = this.props;
114125
const isServerSide = !!this.props.isServerSide;
115126
const value = {

src/client.spec.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
jest.mock('@optimizely/optimizely-sdk');
1718
jest.mock('./logger', () => {
1819
return {
1920
logger: {
20-
warn: jest.fn(() => () => { }),
21-
info: jest.fn(() => () => { }),
22-
error: jest.fn(() => () => { }),
23-
debug: jest.fn(() => () => { }),
21+
warn: jest.fn(() => () => {}),
22+
info: jest.fn(() => () => {}),
23+
error: jest.fn(() => () => {}),
24+
debug: jest.fn(() => () => {}),
2425
},
2526
};
2627
});
@@ -1236,10 +1237,6 @@ describe('ReactSDKClient', () => {
12361237
const result = await instance.fetchQualifiedSegments();
12371238

12381239
expect(result).toEqual(false);
1239-
expect(logger.warn).toHaveBeenCalledTimes(1);
1240-
expect(logger.warn).toBeCalledWith(
1241-
'Unable to fetch qualified segments for user because Optimizely client failed to initialize.'
1242-
);
12431240
});
12441241

12451242
it('should return false if fetch fails', async () => {
@@ -1668,15 +1665,14 @@ describe('ReactSDKClient', () => {
16681665
instance.getUserContext();
16691666

16701667
expect(logger.warn).toHaveBeenCalledTimes(1);
1671-
expect(logger.warn).toBeCalledWith("Unable to get user context because Optimizely client failed to initialize.");
1668+
expect(logger.warn).toBeCalledWith('Unable to get user context. Optimizely client not initialized.');
16721669
});
16731670

1674-
16751671
it('should log a warning and return null if setUser is not called first', () => {
16761672
instance.getUserContext();
16771673

16781674
expect(logger.warn).toHaveBeenCalledTimes(1);
1679-
expect(logger.warn).toBeCalledWith("Unable to get user context because user was not set.");
1675+
expect(logger.warn).toBeCalledWith('Unable to get user context. User context not set.');
16801676
});
16811677

16821678
it('should return a userContext if setUser is called', () => {

0 commit comments

Comments
 (0)