From b526690b4fd88a4dfe06fdcfa74418e3dabfecd0 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Tue, 6 Oct 2020 19:52:37 -0700 Subject: [PATCH 1/2] test(xychart): add more Tooltip tests --- .../test/components/Tooltip.test.tsx | 119 +++++++++++++++--- 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/packages/visx-xychart/test/components/Tooltip.test.tsx b/packages/visx-xychart/test/components/Tooltip.test.tsx index 4fdb32fcf..f51550e39 100644 --- a/packages/visx-xychart/test/components/Tooltip.test.tsx +++ b/packages/visx-xychart/test/components/Tooltip.test.tsx @@ -2,29 +2,42 @@ import React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; import { mount } from 'enzyme'; import { Tooltip as BaseTooltip } from '@visx/tooltip'; -import { Tooltip, TooltipContext, TooltipContextType } from '../../src'; +import { DataContext, Tooltip, TooltipContext, TooltipContextType } from '../../src'; import { TooltipProps } from '../../src/components/Tooltip'; +import getDataContext from '../mocks/getDataContext'; describe('', () => { type SetupProps = | { props?: Partial>; context?: Partial>; + Parent?: ({ children }: { children: React.ReactElement }) => React.ReactElement; } | undefined; - function setup({ props, context }: SetupProps = {}) { + + function setup({ + props, + context, + Parent = ({ children }: { children: React.ReactElement }) => children, + }: SetupProps = {}) { const wrapper = mount( - - null} {...props} /> - , + + +
} + {...props} + /> + + , ); return wrapper; } @@ -38,13 +51,13 @@ describe('', () => { }); it('should not render a BaseTooltip when TooltipContext.tooltipOpen=true and renderTooltip returns false', () => { - const wrapper = setup({ context: { tooltipOpen: true } }); + const wrapper = setup({ context: { tooltipOpen: true }, props: { renderTooltip: () => null } }); expect(wrapper.find(BaseTooltip)).toHaveLength(0); }); it('should render a BaseTooltip when TooltipContext.tooltipOpen=true and renderTooltip returns non-null', () => { const wrapper = setup({ - props: { renderTooltip: () =>
}, + props: { renderTooltip: () =>
, snapTooltipToDatumX: true }, context: { tooltipOpen: true }, }); expect(wrapper.find(BaseTooltip)).toHaveLength(1); @@ -66,4 +79,80 @@ describe('', () => { }); expect(renderTooltip).toHaveBeenCalledTimes(1); }); + + it('should render a vertical crosshair if showVerticalCrossHair=true', () => { + const wrapper = setup({ + props: { showVerticalCrosshair: true }, + context: { tooltipOpen: true }, + }); + expect(wrapper.find('div.visx-crosshair-vertical')).toHaveLength(1); + }); + + it('should render a horizontal crosshair if showVerticalCrossHair=true', () => { + const wrapper = setup({ + props: { showHorizontalCrosshair: true }, + context: { tooltipOpen: true }, + }); + expect(wrapper.find('div.visx-crosshair-horizontal')).toHaveLength(1); + }); + + it('should not render a glyph if showDatumGlyph=true and there is no nearestDatum', () => { + const wrapper = setup({ + props: { showDatumGlyph: true }, + context: { tooltipOpen: true }, + }); + expect(wrapper.find('div.visx-tooltip-glyph')).toHaveLength(0); + }); + it('should render a glyph if showDatumGlyph=true if there is a nearestDatum', () => { + const wrapper = setup({ + props: { showDatumGlyph: true }, + context: { + tooltipOpen: true, + tooltipData: { + nearestDatum: { distance: 1, key: '', index: 0, datum: {} }, + datumByKey: {}, + }, + }, + }); + expect(wrapper.find('div.visx-tooltip-glyph')).toHaveLength(1); + }); + it('should render a glyph for each series if showSeriesGlyphs=true', () => { + const wrapper = setup({ + props: { showSeriesGlyphs: true }, + context: { + tooltipOpen: true, + tooltipData: { + datumByKey: { + d1: { key: 'd1', index: 0, datum: {} }, + d2: { key: 'd2', index: 1, datum: {} }, + }, + }, + }, + Parent: ( + { children }, // glyphs snap to data points, so scales/accessors must exist + ) => ( + 3, + yAccessor: () => 7, + data: [{}], + }, + { + key: 'd2', + xAccessor: () => 3, + yAccessor: () => 7, + data: [{}], + }, + ]), + }} + > + {children} + + ), + }); + expect(wrapper.find('div.visx-tooltip-glyph')).toHaveLength(2); + }); }); From 8d01a95dd1bff4f7126fa45c52c92d5e9968cf55 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Tue, 6 Oct 2020 19:52:51 -0700 Subject: [PATCH 2/2] test(xychart): add more TooltipProvider tests --- .../test/providers/TooltipProvider.test.tsx | 60 +++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/visx-xychart/test/providers/TooltipProvider.test.tsx b/packages/visx-xychart/test/providers/TooltipProvider.test.tsx index b9244a4c2..2d92fbed6 100644 --- a/packages/visx-xychart/test/providers/TooltipProvider.test.tsx +++ b/packages/visx-xychart/test/providers/TooltipProvider.test.tsx @@ -1,18 +1,70 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import { mount } from 'enzyme'; -import { TooltipProvider, TooltipContext } from '../../src'; +import { TooltipProvider, TooltipContext, TooltipData } from '../../src'; describe('', () => { it('should be defined', () => { expect(TooltipProvider).toBeDefined(); }); - it('should provide an emitter for subscribing and emitting events', () => { + it('should provide tooltip state', () => { expect.assertions(1); const TooltipConsumer = () => { const tooltipContext = useContext(TooltipContext); - expect(tooltipContext).toBeDefined(); + expect(tooltipContext).toMatchObject({ + tooltipOpen: expect.any(Boolean), + showTooltip: expect.any(Function), + updateTooltip: expect.any(Function), + hideTooltip: expect.any(Function), + }); + + return null; + }; + + mount( + + + , + ); + }); + + it('showTooltip should update tooltipData.nearestDatum/datumByKey', () => { + expect.assertions(1); + + const TooltipConsumer = () => { + const tooltipContext = useContext(TooltipContext); + const tooltipOpen = tooltipContext?.tooltipOpen; + const showTooltip = tooltipContext?.showTooltip; + + useEffect(() => { + // this triggers a re-render of the component which triggers the assertion block + if (!tooltipOpen && showTooltip) { + showTooltip({ + key: 'near', + index: 0, + distanceX: 0, + distanceY: 0, + datum: { hi: 'hello' }, + }); + showTooltip({ + key: 'far', + index: 1, + datum: { good: 'bye' }, + // no distance = Infinity + }); + } + }, [tooltipOpen, showTooltip]); + + if (tooltipOpen) { + expect(tooltipContext?.tooltipData).toMatchObject({ + nearestDatum: { key: 'near', index: 0, distance: 0, datum: { hi: 'hello' } }, + datumByKey: { + near: { key: 'near', index: 0, datum: { hi: 'hello' } }, + far: { key: 'far', index: 1, datum: { good: 'bye' } }, + }, + } as TooltipData); + } return null; };