-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1788 from Shopify/funnel-chart-next-follow-ups
FunnelChartNext follow ups
- Loading branch information
Showing
10 changed files
with
396 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
packages/polaris-viz/src/components/FunnelChartNext/components/FunnelChartLabels/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {FunnelChartLabels} from './FunnelChartLabels'; |
162 changes: 162 additions & 0 deletions
162
.../components/FunnelChartNext/components/FunnelChartLabels/tests/FunnelChartLabels.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
import {mount} from '@shopify/react-testing'; | ||
import {scaleBand} from 'd3-scale'; | ||
import {ChartContext} from '@shopify/polaris-viz-core'; | ||
|
||
import {SingleTextLine} from '../../../../Labels'; | ||
import {ScaleIcon} from '../../ScaleIcon'; | ||
import {ScaleIconTooltip} from '../../ScaleIconTooltip'; | ||
import {FunnelChartLabels} from '../FunnelChartLabels'; | ||
|
||
describe('<FunnelChartLabels />', () => { | ||
const mockContext = { | ||
characterWidths: new Map([['default', 10]]), | ||
containerBounds: { | ||
width: 500, | ||
height: 300, | ||
x: 0, | ||
y: 0, | ||
}, | ||
}; | ||
|
||
const mockProps = { | ||
formattedValues: ['1,000', '750', '500'], | ||
labels: ['Step 1', 'Step 2', 'Step 3'], | ||
labelWidth: 150, | ||
barWidth: 100, | ||
percentages: ['100%', '75%', '50%'], | ||
xScale: scaleBand().domain(['0', '1', '2']).range([0, 300]), | ||
shouldApplyScaling: false, | ||
renderScaleIconTooltipContent: () => <div>Tooltip content</div>, | ||
}; | ||
|
||
const wrapper = (props = mockProps) => { | ||
return mount( | ||
<ChartContext.Provider value={mockContext}> | ||
<FunnelChartLabels {...props} /> | ||
</ChartContext.Provider>, | ||
); | ||
}; | ||
|
||
describe('text elements', () => { | ||
it('renders expected number of text elements', () => { | ||
const component = wrapper(); | ||
const texts = component.findAll(SingleTextLine); | ||
// 3 labels + 3 percentages + 3 values | ||
expect(texts).toHaveLength(9); | ||
}); | ||
|
||
it('renders labels, percentages, and values', () => { | ||
const component = wrapper(); | ||
|
||
expect(component).toContainReactComponent(SingleTextLine, { | ||
text: 'Step 1', | ||
}); | ||
expect(component).toContainReactComponent(SingleTextLine, { | ||
text: '100%', | ||
}); | ||
expect(component).toContainReactComponent(SingleTextLine, { | ||
text: '1,000', | ||
}); | ||
}); | ||
|
||
it('hides formatted values when space is constrained', () => { | ||
const propsWithNarrowWidth = { | ||
...mockProps, | ||
labelWidth: 50, | ||
barWidth: 50, | ||
}; | ||
|
||
const component = wrapper(propsWithNarrowWidth); | ||
const texts = component.findAll(SingleTextLine); | ||
|
||
expect(texts).toHaveLength(6); | ||
|
||
// Verify labels and percentages are still shown | ||
expect(component).toContainReactComponent(SingleTextLine, { | ||
text: 'Step 1', | ||
}); | ||
expect(component).toContainReactComponent(SingleTextLine, { | ||
text: '100%', | ||
}); | ||
}); | ||
}); | ||
|
||
describe('scale icon', () => { | ||
it('renders scale icon when shouldApplyScaling is true', () => { | ||
const component = wrapper({ | ||
...mockProps, | ||
shouldApplyScaling: true, | ||
}); | ||
|
||
expect(component).toContainReactComponent(ScaleIcon); | ||
}); | ||
|
||
it('does not render scale icon when shouldApplyScaling is false', () => { | ||
const component = wrapper({ | ||
...mockProps, | ||
shouldApplyScaling: false, | ||
}); | ||
|
||
expect(component).not.toContainReactComponent(ScaleIcon); | ||
}); | ||
|
||
it('shows tooltip when scale icon is hovered', () => { | ||
const mockTooltipContent = () => <div>Tooltip content</div>; | ||
const component = wrapper({ | ||
...mockProps, | ||
shouldApplyScaling: true, | ||
renderScaleIconTooltipContent: mockTooltipContent, | ||
}); | ||
|
||
// Get the second g element | ||
const iconContainer = component.findAll('g')[1]; | ||
iconContainer.trigger('onMouseEnter'); | ||
|
||
expect(component).toContainReactComponent(ScaleIconTooltip); | ||
}); | ||
|
||
it('hides tooltip when scale icon is unhovered', () => { | ||
const mockTooltipContent = () => <div>Tooltip content</div>; | ||
const component = wrapper({ | ||
...mockProps, | ||
shouldApplyScaling: true, | ||
renderScaleIconTooltipContent: mockTooltipContent, | ||
}); | ||
|
||
const iconContainer = component.findAll('g')[1]; | ||
|
||
iconContainer.trigger('onMouseEnter'); | ||
iconContainer.trigger('onMouseLeave'); | ||
|
||
expect(component).not.toContainReactComponent(ScaleIconTooltip); | ||
}); | ||
}); | ||
|
||
describe('label font size', () => { | ||
it('uses reduced font size when labels are too long', () => { | ||
const propsWithLongLabels = { | ||
...mockProps, | ||
labels: [ | ||
'Very Long Step Name 1', | ||
'Very Long Step Name 2', | ||
'Very Long Step Name 3', | ||
], | ||
labelWidth: 50, | ||
}; | ||
|
||
const component = wrapper(propsWithLongLabels); | ||
|
||
expect(component.findAll(SingleTextLine)[0]).toHaveReactProps({ | ||
fontSize: 11, | ||
}); | ||
}); | ||
|
||
it('uses default font size when labels fit', () => { | ||
const component = wrapper(); | ||
|
||
expect(component.findAll(SingleTextLine)[0]).toHaveReactProps({ | ||
fontSize: 12, | ||
}); | ||
}); | ||
}); | ||
}); |
2 changes: 1 addition & 1 deletion
2
packages/polaris-viz/src/components/FunnelChartNext/components/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
packages/polaris-viz/src/components/SparkFunnelChart/tests/Chart.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import {mount} from '@shopify/react-testing'; | ||
import {ChartContext} from '@shopify/polaris-viz-core'; | ||
import type {DataSeries} from '@shopify/polaris-viz-core'; | ||
import React from 'react'; | ||
|
||
import {Chart} from '../Chart'; | ||
import {FunnelChartConnector, FunnelChartSegment} from '../../shared'; | ||
|
||
const mockData: DataSeries[] = [ | ||
{ | ||
name: 'Group 1', | ||
data: [ | ||
{key: 'Step 1', value: 100}, | ||
{key: 'Step 2', value: 75}, | ||
{key: 'Step 3', value: 50}, | ||
], | ||
}, | ||
]; | ||
|
||
const mockContext = { | ||
containerBounds: { | ||
width: 500, | ||
height: 300, | ||
x: 0, | ||
y: 0, | ||
}, | ||
}; | ||
|
||
const defaultProps = { | ||
data: mockData, | ||
accessibilityLabel: 'Funnel chart showing conversion', | ||
}; | ||
|
||
describe('<Chart />', () => { | ||
it('renders funnel segments for each data point', () => { | ||
const chart = mount( | ||
<ChartContext.Provider value={mockContext}> | ||
<Chart {...defaultProps} /> | ||
</ChartContext.Provider>, | ||
); | ||
|
||
expect(chart).toContainReactComponentTimes( | ||
FunnelChartSegment, | ||
mockData[0].data.length, | ||
); | ||
}); | ||
|
||
it('renders n-1 connectors for n funnel segments, excluding the last segment', () => { | ||
const chart = mount( | ||
<ChartContext.Provider value={mockContext}> | ||
<Chart {...defaultProps} /> | ||
</ChartContext.Provider>, | ||
); | ||
|
||
expect(chart).toContainReactComponentTimes( | ||
FunnelChartConnector, | ||
mockData[0].data.length - 1, | ||
); | ||
}); | ||
|
||
it('renders accessibility label when provided', () => { | ||
const accessibilityLabel = 'Custom accessibility label'; | ||
const chart = mount( | ||
<ChartContext.Provider value={mockContext}> | ||
<Chart {...defaultProps} accessibilityLabel={accessibilityLabel} /> | ||
</ChartContext.Provider>, | ||
); | ||
|
||
expect(chart).toContainReactText(accessibilityLabel); | ||
}); | ||
|
||
it('renders segments with expected aria labels', () => { | ||
const chart = mount( | ||
<ChartContext.Provider value={mockContext}> | ||
<Chart {...defaultProps} /> | ||
</ChartContext.Provider>, | ||
); | ||
|
||
const firstSegment = chart.findAll(FunnelChartSegment)[0]; | ||
expect(firstSegment).toHaveReactProps({ | ||
ariaLabel: 'Step 1: 100', | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.