From 7f38db28a9154b523260a26462d1c064984afdb8 Mon Sep 17 00:00:00 2001 From: Matt Vickers Date: Wed, 28 Feb 2024 08:42:47 -0600 Subject: [PATCH] Allow id to be null --- packages/polaris-viz/CHANGELOG.md | 8 ++ packages/polaris-viz/src/hooks/index.ts | 5 +- .../hooks/tests/useWatchActiveSeries.test.tsx | 94 +++++++++++++++++++ .../src/hooks/useWatchActiveSeries.ts | 24 +++-- packages/polaris-viz/src/index.ts | 1 + 5 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 packages/polaris-viz/src/hooks/tests/useWatchActiveSeries.test.tsx diff --git a/packages/polaris-viz/CHANGELOG.md b/packages/polaris-viz/CHANGELOG.md index d611a0a5c..176f08314 100644 --- a/packages/polaris-viz/CHANGELOG.md +++ b/packages/polaris-viz/CHANGELOG.md @@ -17,6 +17,14 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - Fixed the positioning of the `` for the Stacked Horizontal Chart when all values are negative. +### Changed + +- Allow `useWatchActiveSeries` to accept `null` as an `id` to disable attaching events. + +### Added + +- Export `setActiveSeriesListener()`. + ## [10.5.2] - 2024-02-22 ### Added diff --git a/packages/polaris-viz/src/hooks/index.ts b/packages/polaris-viz/src/hooks/index.ts index 11db91bee..1a24fd354 100644 --- a/packages/polaris-viz/src/hooks/index.ts +++ b/packages/polaris-viz/src/hooks/index.ts @@ -29,5 +29,8 @@ export { getSeriesColors, usePrevious, } from '@shopify/polaris-viz-core'; -export {useWatchActiveSeries} from './useWatchActiveSeries'; +export { + useWatchActiveSeries, + setActiveSeriesListener, +} from './useWatchActiveSeries'; export {useExternalHideEvents, setHiddenItems} from './ExternalEvents'; diff --git a/packages/polaris-viz/src/hooks/tests/useWatchActiveSeries.test.tsx b/packages/polaris-viz/src/hooks/tests/useWatchActiveSeries.test.tsx new file mode 100644 index 000000000..1052178e0 --- /dev/null +++ b/packages/polaris-viz/src/hooks/tests/useWatchActiveSeries.test.tsx @@ -0,0 +1,94 @@ +import {mount} from '@shopify/react-testing'; +import {COLOR_VISION_SINGLE_ITEM} from '@shopify/polaris-viz-core'; + +import { + useWatchActiveSeries, + setActiveSeriesListener, +} from '../useWatchActiveSeries'; +import {getEventName} from '../ColorVisionA11y'; +import {useCallbackRef} from '../useCallbackRef'; + +jest.mock('../useCallbackRef'); + +const mockUseCallbackRef = useCallbackRef as jest.MockedFunction< + typeof useCallbackRef +>; + +const onIndexChangeCallback = jest.fn(); + +describe('useWatchActiveSeries()', () => { + beforeEach(() => { + mockUseCallbackRef.mockReturnValue(onIndexChangeCallback); + }); + + afterEach(() => { + mockUseCallbackRef.mockReset(); + }); + + describe('useWatchActiveSeries()', () => { + it('attaches event listener to window when id is passed', () => { + const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); + + function MockComponent() { + useWatchActiveSeries('id', onIndexChangeCallback); + + return null; + } + + mount(); + + expect(addEventListenerSpy).toHaveBeenCalledWith( + 'id:color-vision-event:singleItem', + onIndexChangeCallback, + ); + }); + + it('removes event listener from window when component is unmounted', () => { + const onIndexChangeCallback = jest.fn(); + const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); + + mockUseCallbackRef.mockReturnValue(onIndexChangeCallback); + + function MockComponent() { + useWatchActiveSeries('id', onIndexChangeCallback); + + return null; + } + + const component = mount(); + + component.unmount(); + + expect(removeEventListenerSpy).toHaveBeenCalledWith( + 'id:color-vision-event:singleItem', + onIndexChangeCallback, + ); + }); + }); + + describe('setActiveSeriesListener()', () => { + it('adds an event listener using an event name generated using the given ID', () => { + const id = getEventName('someChartId', COLOR_VISION_SINGLE_ITEM); + const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); + + setActiveSeriesListener('someChartId', onIndexChangeCallback); + + expect(addEventListenerSpy).toHaveBeenCalledWith( + id, + onIndexChangeCallback, + ); + }); + + it('returns a method that removes the previously set event listener', () => { + const id = getEventName('someChartId', COLOR_VISION_SINGLE_ITEM); + const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); + + setActiveSeriesListener('someChartId', onIndexChangeCallback); + + expect(addEventListenerSpy).toHaveBeenCalledWith( + id, + onIndexChangeCallback, + ); + }); + }); +}); diff --git a/packages/polaris-viz/src/hooks/useWatchActiveSeries.ts b/packages/polaris-viz/src/hooks/useWatchActiveSeries.ts index 4a035314a..d3fc8ef10 100644 --- a/packages/polaris-viz/src/hooks/useWatchActiveSeries.ts +++ b/packages/polaris-viz/src/hooks/useWatchActiveSeries.ts @@ -13,12 +13,24 @@ export function useWatchActiveSeries( const onIndexChangeCallback = useCallbackRef(onIndexChange); useEffect(() => { - const eventName = getEventName(id, COLOR_VISION_SINGLE_ITEM); + const clearActiveSeriesListener = setActiveSeriesListener( + id, + onIndexChangeCallback, + ); - window.addEventListener(eventName, onIndexChangeCallback); - - return () => { - window.removeEventListener(eventName, onIndexChangeCallback); - }; + return () => clearActiveSeriesListener(); }, [id, onIndexChangeCallback]); } + +export function setActiveSeriesListener( + id: string, + onIndexChange: (event: ColorVisionEventReturn) => void, +) { + const eventName = getEventName(id, COLOR_VISION_SINGLE_ITEM); + + window.addEventListener(eventName, onIndexChange); + + return () => { + window.removeEventListener(eventName, onIndexChange); + }; +} diff --git a/packages/polaris-viz/src/index.ts b/packages/polaris-viz/src/index.ts index 8624c60ad..9e0479d8e 100644 --- a/packages/polaris-viz/src/index.ts +++ b/packages/polaris-viz/src/index.ts @@ -86,6 +86,7 @@ export {renderLinearTooltipContent, setSingleSeriesActive} from './utilities'; export { useWatchActiveSeries, + setActiveSeriesListener, setHiddenItems, useRenderTooltipContent, } from './hooks';