From 8d2088578298a865a493a8dd3d8d8e58c47ef251 Mon Sep 17 00:00:00 2001 From: Garrett Kadillak Date: Fri, 22 May 2020 22:12:07 -0700 Subject: [PATCH] Add config value to turn off camel casing for flags (#40) --- README.md | 5 ++++- src/init.js | 22 +++++++++++++--------- src/init.test.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f520a5e..a5be3e3 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ yarn add ld-redux ``` ## API -### init({clientSideId, dispatch, flags, user, subscribe, options}) +### init({clientSideId, dispatch, flags, useCamelCaseFlagKeys, user, subscribe, options}) The init method accepts an object with the above properties. `clientSideId`, `dispatch` are mandatory. The `flags` property is optional. This is an object containing all the flags you want to use and subscribe to in your app. @@ -133,6 +133,9 @@ const defaultUser = { For more info on the user object, see [here](http://docs.launchdarkly.com/docs/js-sdk-reference#section-users). +The `useCamelCaseFlagKeys` property is optional. This defaults to true which means by default the flags that are stored +in redux will be camel cased. If this property is false, no transformation on the flag name will be done. + The `options` property is optional. It can be used to pass in extra options such as [Bootstrapping](https://github.com/launchdarkly/js-client#bootstrapping). For example: diff --git a/src/init.js b/src/init.js index 9657d56..53508c6 100644 --- a/src/init.js +++ b/src/init.js @@ -10,21 +10,25 @@ const isMobileDevice = typeof window !== 'undefined' && userAgentParser.getDevic const isTabletDevice = typeof window !== 'undefined' && userAgentParser.getDevice().type === 'tablet'; // initialise flags with default values in ld redux store -const initFlags = (flags, dispatch) => { +const initFlags = (flags, dispatch, useCamelCaseFlagKeys) => { const flagValues = { isLDReady: false }; for (const flag in flags) { - const camelCasedKey = camelCase(flag); - flagValues[camelCasedKey] = flags[flag]; + if (useCamelCaseFlagKeys) { + const camelCasedKey = camelCase(flag); + flagValues[camelCasedKey] = flags[flag]; + } else { + flagValues[flag] = flags[flag]; + } } dispatch(setFlagsAction(flagValues)); }; // set flags with real values from ld server -const setFlags = (flags, dispatch) => { +const setFlags = (flags, dispatch, useCamelCaseFlagKeys) => { const flagValues = { isLDReady: true }; for (const flag in flags) { - const camelCasedKey = camelCase(flag); - flagValues[camelCasedKey] = ldClient.variation(flag, flags[flag]); + const flagKey = useCamelCaseFlagKeys ? camelCase(flag) : flag; + flagValues[flagKey] = ldClient.variation(flag, flags[flag]); } dispatch(setFlagsAction(flagValues)); }; @@ -61,8 +65,8 @@ const initUser = () => { }; }; -export default ({ clientSideId, dispatch, flags, user, subscribe, options }) => { - initFlags(flags, dispatch); +export default ({ clientSideId, dispatch, flags, useCamelCaseFlagKeys = true, user, subscribe, options }) => { + initFlags(flags, dispatch, useCamelCaseFlagKeys); // default subscribe to true const sanitisedSubscribe = typeof subscribe === 'undefined' ? true : subscribe; @@ -74,7 +78,7 @@ export default ({ clientSideId, dispatch, flags, user, subscribe, options }) => window.ldClient = ldClientInitialize(clientSideId, user, options); window.ldClient.on('ready', () => { const flagsSanitised = flags || ldClient.allFlags(); - setFlags(flagsSanitised, dispatch); + setFlags(flagsSanitised, dispatch, useCamelCaseFlagKeys); if (sanitisedSubscribe) { subscribeToChanges(flagsSanitised, dispatch); diff --git a/src/init.test.js b/src/init.test.js index f6a628f..2317ccf 100644 --- a/src/init.test.js +++ b/src/init.test.js @@ -222,4 +222,39 @@ describe('initialize', () => { td.verify(mock.on('change:test-flag', td.matchers.isA(Function))); td.verify(mock.on('change:another-test-flag', td.matchers.isA(Function))); }); + + it('should not camel case provided flags if specified', () => { + td.when(mock.variation('test-flag', false)).thenReturn(true); + td.when(mock.variation('another-test-flag', true)).thenReturn(false); + + ldReduxInit({ + clientSideId: MOCK_CLIENT_SIDE_ID, + dispatch: mock.store.dispatch, + useCamelCaseFlagKeys: false, + flags: { 'test-flag': false, 'another-test-flag': true }, + }); + + td.verify( + mock.store.dispatch( + td.matchers.contains({ + type: 'SET_FLAGS', + data: { isLDReady: false, 'test-flag': false, 'another-test-flag': true }, + }), + ), + ); + + mock.onReadyHandler(); + + jest.runAllTimers(); + + td.verify(mock.store.dispatch(td.matchers.anything()), { times: 2 }); + td.verify( + mock.store.dispatch( + td.matchers.contains({ + type: 'SET_FLAGS', + data: { isLDReady: false, 'test-flag': false, 'another-test-flag': true }, + }), + ), + ); + }); });