Skip to content

Commit

Permalink
test(xychart): add refined Tooltip, TooltipProvider tests (#852)
Browse files Browse the repository at this point in the history
* test(xychart): add more Tooltip tests

* test(xychart): add more TooltipProvider tests
  • Loading branch information
williaster authored Oct 7, 2020
1 parent c630c11 commit 12f4819
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 19 deletions.
119 changes: 104 additions & 15 deletions packages/visx-xychart/test/components/Tooltip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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('<Tooltip />', () => {
type SetupProps =
| {
props?: Partial<TooltipProps<object>>;
context?: Partial<TooltipContextType<object>>;
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(
<TooltipContext.Provider
value={{
tooltipOpen: false,
showTooltip: jest.fn(),
updateTooltip: jest.fn(),
hideTooltip: jest.fn(),
...context,
}}
>
<Tooltip resizeObserverPolyfill={ResizeObserver} renderTooltip={() => null} {...props} />
</TooltipContext.Provider>,
<Parent>
<TooltipContext.Provider
value={{
tooltipOpen: false,
showTooltip: jest.fn(),
updateTooltip: jest.fn(),
hideTooltip: jest.fn(),
...context,
}}
>
<Tooltip
resizeObserverPolyfill={ResizeObserver}
renderTooltip={() => <div />}
{...props}
/>
</TooltipContext.Provider>
</Parent>,
);
return wrapper;
}
Expand All @@ -38,13 +51,13 @@ describe('<Tooltip />', () => {
});

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: () => <div /> },
props: { renderTooltip: () => <div />, snapTooltipToDatumX: true },
context: { tooltipOpen: true },
});
expect(wrapper.find(BaseTooltip)).toHaveLength(1);
Expand All @@ -66,4 +79,80 @@ describe('<Tooltip />', () => {
});
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
) => (
<DataContext.Provider
value={{
...getDataContext([
{
key: 'd1',
xAccessor: () => 3,
yAccessor: () => 7,
data: [{}],
},
{
key: 'd2',
xAccessor: () => 3,
yAccessor: () => 7,
data: [{}],
},
]),
}}
>
{children}
</DataContext.Provider>
),
});
expect(wrapper.find('div.visx-tooltip-glyph')).toHaveLength(2);
});
});
60 changes: 56 additions & 4 deletions packages/visx-xychart/test/providers/TooltipProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -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('<TooltipProvider />', () => {
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(
<TooltipProvider>
<TooltipConsumer />
</TooltipProvider>,
);
});

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<object>);
}

return null;
};
Expand Down

0 comments on commit 12f4819

Please sign in to comment.