From b178d68c1fc0fc8d660eec37f467afc02c7eb0ce Mon Sep 17 00:00:00 2001 From: "Leo Y. Li" Date: Wed, 24 Apr 2019 02:39:09 -0400 Subject: [PATCH] FIX addon-contexts: edge case bugs part.2 --- addons/contexts/src/manager/ContextsManager.tsx | 3 +-- addons/contexts/src/preview/ContextsPreviewAPI.ts | 10 +++++++--- addons/contexts/src/preview/libs/getPropsMap.test.ts | 6 +++--- addons/contexts/src/preview/libs/getPropsMap.ts | 11 ++++++----- addons/contexts/src/shared/serializers.test.ts | 1 + addons/contexts/src/shared/serializers.ts | 5 ++++- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/addons/contexts/src/manager/ContextsManager.tsx b/addons/contexts/src/manager/ContextsManager.tsx index e1fc2524d30d..82f314dcea69 100644 --- a/addons/contexts/src/manager/ContextsManager.tsx +++ b/addons/contexts/src/manager/ContextsManager.tsx @@ -21,8 +21,7 @@ export const ContextsManager: ContextsManager = ({ api }) => { ); // from preview - useChannel(UPDATE_MANAGER, newNodes => newNodes && setNodes(newNodes), []); - useChannel(UPDATE_MANAGER, (_, newState) => newState && setState(newState), []); + useChannel(UPDATE_MANAGER, newNodes => setNodes(newNodes), []); // to preview useEffect(() => api.emit(REBOOT_MANAGER), []); diff --git a/addons/contexts/src/preview/ContextsPreviewAPI.ts b/addons/contexts/src/preview/ContextsPreviewAPI.ts index e154bec9752c..10453c1d9430 100644 --- a/addons/contexts/src/preview/ContextsPreviewAPI.ts +++ b/addons/contexts/src/preview/ContextsPreviewAPI.ts @@ -46,9 +46,13 @@ export const ContextsPreviewAPI = singleton(() => { */ // from manager channel.on(SET_CURRENT_STORY, () => (contextsNodesMemo = null)); - channel.on(REBOOT_MANAGER, () => channel.emit(UPDATE_MANAGER, contextsNodesMemo, selectionState)); - channel.on(UPDATE_PREVIEW, state => state && (selectionState = state)); - channel.on(UPDATE_PREVIEW, () => channel.emit(FORCE_RE_RENDER)); + channel.on(REBOOT_MANAGER, () => channel.emit(UPDATE_MANAGER, contextsNodesMemo)); + channel.on(UPDATE_PREVIEW, state => { + if (state) { + selectionState = state; + channel.emit(FORCE_RE_RENDER); + } + }); // to manager const getContextNodesWithSideEffects: typeof getContextNodes = (...arg) => { diff --git a/addons/contexts/src/preview/libs/getPropsMap.test.ts b/addons/contexts/src/preview/libs/getPropsMap.test.ts index a5edb6cf0b60..c610eca94deb 100644 --- a/addons/contexts/src/preview/libs/getPropsMap.test.ts +++ b/addons/contexts/src/preview/libs/getPropsMap.test.ts @@ -10,7 +10,7 @@ describe('Test on behaviors from collecting the propsMap', () => { }); it('should return "OPT_OUT" token when the context being opted out', () => { - const result = _getPropsByParamName(someParams, OPT_OUT); + const result = _getPropsByParamName(someParams, OPT_OUT, { cancelable: true }); expect(result).toBe(OPT_OUT); }); @@ -66,7 +66,7 @@ describe('Test on the integrity of the method to get the propMaps', () => { ]; const someSelectionState = { 'Some Context': 'A1', - 'Another Context': OPT_OUT, + 'Another Context': OPT_OUT, // an inconsistent but possible state being introduced via query param }; // exercise @@ -75,7 +75,7 @@ describe('Test on the integrity of the method to get the propMaps', () => { // assertion expect(result).toEqual({ 'Some Context': { a: 1 }, - 'Another Context': OPT_OUT, + 'Another Context': { b: 1 }, // not equal to `OPT_OUT` due to the context is not cancelable 'Other Contexts': { c: 1 }, }); }); diff --git a/addons/contexts/src/preview/libs/getPropsMap.ts b/addons/contexts/src/preview/libs/getPropsMap.ts index ae945c9b8df9..d5e2007bbc01 100644 --- a/addons/contexts/src/preview/libs/getPropsMap.ts +++ b/addons/contexts/src/preview/libs/getPropsMap.ts @@ -7,13 +7,14 @@ import { ContextNode, GenericProp, PropsMap, SelectionState } from '../../shared */ type _getPropsByParamName = ( params: ContextNode['params'], - name?: string + name?: string, + options?: Partial ) => GenericProp | typeof OPT_OUT; -export const _getPropsByParamName: _getPropsByParamName = (params, name) => { +export const _getPropsByParamName: _getPropsByParamName = (params, name = '', options = {}) => { const { props = null } = // when opt-out context - (name === OPT_OUT && { props: OPT_OUT }) || + (options.cancelable && name === OPT_OUT && { props: OPT_OUT }) || // when menu option get selected (name && params.find(param => param.name === name)) || // when being initialized @@ -32,7 +33,7 @@ export const _getPropsByParamName: _getPropsByParamName = (params, name) => { type getPropsMap = (contextNodes: ContextNode[], selectionState: SelectionState) => PropsMap; export const getPropsMap: getPropsMap = (contextNodes, selectionState) => - contextNodes.reduce((agg, { nodeId, params }) => { - agg[nodeId] = _getPropsByParamName(params, selectionState[nodeId]); + contextNodes.reduce((agg, { nodeId, params, options }) => { + agg[nodeId] = _getPropsByParamName(params, selectionState[nodeId], options); return agg; }, Object()); diff --git a/addons/contexts/src/shared/serializers.test.ts b/addons/contexts/src/shared/serializers.test.ts index 4e97b1986f10..fd097438a042 100644 --- a/addons/contexts/src/shared/serializers.test.ts +++ b/addons/contexts/src/shared/serializers.test.ts @@ -14,6 +14,7 @@ describe('Test on serializers', () => { it('Should deserialize a string representation into the represented selection state', () => { expect(deserialize('')).toEqual(undefined); + expect(deserialize('I am a bad string=')).toEqual(undefined); expect(deserialize(someContextsQueryParam)).toEqual(someSelectionState); }); }); diff --git a/addons/contexts/src/shared/serializers.ts b/addons/contexts/src/shared/serializers.ts index c283c1bc36b4..bc89e10e206a 100644 --- a/addons/contexts/src/shared/serializers.ts +++ b/addons/contexts/src/shared/serializers.ts @@ -23,4 +23,7 @@ export const deserialize: deserialize = param => : param .split(/,+/g) .map(str => str.split(/=+/g)) - .reduce((acc, [nodeId, name]) => (nodeId && name ? { ...acc, [nodeId]: name } : acc), {}); + .reduce( + (acc, [nodeId, name]) => (nodeId && name ? { ...acc, [nodeId]: name } : acc), + undefined + );