diff --git a/packages/react-charting/docs/TestPlans/GroupedVerticalBarChart/ComponentTests.md b/packages/react-charting/docs/TestPlans/GroupedVerticalBarChart/ComponentTests.md new file mode 100644 index 00000000000000..904dbbc513eca2 --- /dev/null +++ b/packages/react-charting/docs/TestPlans/GroupedVerticalBarChart/ComponentTests.md @@ -0,0 +1,62 @@ +**Grouped Vertical Bar Chart – Component test plan** + +**Sub-components: Bar, Legends, Callout, Labels** + +1. **Bar: Bar data, Bar color, bar label** +1. **Legends: show/hide legends, highlight the corresponding bar on legend hover** +1. **Callout: Default/custom callout** +1. **Labels: x-Axis labels default/rotated** + +| **Test steps** | **Validation** | **Tool used** | +| :-----------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------: | :-----------: | +| Test 1: [Snapshot testing] | | | +| - With only data prop, string data on x-axis. | Renders GroupedVerticalBar chart correctly | Enzyme | +| - With HideLegend prop set to “true” | Should hide legends | Enzyme | +| - With HideTooltip prop set to “true” | Should hide the tooltip in chart | Enzyme | +| - With EnabledLegendsWrapLines set to “true” | Should enable the legends to wrap lines if there is not enough space to show all legends on a single line | Enzyme | +| - With ShowXAxisLablesTooltip set to “true” | Should truncate x axis labels and show tooltip on x axis labels | Enzyme | +| - With WrapXAxisLables set to “true” | Should wrap x axis label values | Enzyme | +| - With yAxisTickFormat set to “%d” |

Should render the y-axis ticks in the format specified

| Enzyme | +| - With hideLabels set to “true” | Should hide bar labels | RTL | +| - With yAxisTickCount | Should render y axis with specific tick count | RTL | +| Test 2: Basic props testing | | | +| - HideLegend prop set to “true” | Should not mount legend when hideLegend is true | Enzyme | +| - HideLegend prop set to “false” | Should mount legend when hideLegend is false | Enzyme | +| - HideTooltip prop set to “true” | Should not mount callout when hideTootip is true | Enzyme | +| - HideTooltip prop set to “false” | Should mount callout when hideTootip is false | Enzyme | +| - onRenderCalloutPerDataPoint is given | Should render onRenderCalloutPerDataPoint | Enzyme | +| - onRenderCalloutPerDataPoint is not given | Should not render onRenderCalloutPerDataPoint | Enzyme | +| Test 3: Render calling with respective to props | | | +| - No prop changes: Mount grouped vertical bar chart and then set the same props again | Render function should have been called twice | Enzyme | +| - Prop changes: Mount grouped vertical bar chart and then set some other prop | Render function should have been called twice | Enzyme | +| Test 4: Mouse events | | | +| - Mouse over on a bar | Should render callout correctly on mouseover | Enzyme | +| - Mouse move from one bar to other bar | Should render callout correctly on mouse move | Enzyme | +| - Mouse over on a bar with customized callout | Should render customized callout on mouseover | Enzyme | +| Test 6: [Sub-Component]: Bar | | | +| - Specify bar color | Should render bar with the specified color | RTL | +| - with custom accessibility data | Should render bars with custom accessibility data | RTL | +| Test 7: [Sub-Component]: Legends | | | +| - Hide legends | Should not show any rendered legends | RTL | +| - Hover mouse over bar legends | Should reduce the opacity of the other bars | RTL | +| - Mouse move from one Legend to another Legend | Should reset the opacity of the lines on mouse leave a bar legend | RTL | +| - Single mouse click on bar legends | Should select legend on single mouse click on respective legend | RTL | +| - Double mouse click on bar legends | Should deselect legend on double mouse click on respective legend | RTL | +| Test 8: [Sub-Component]: Callout | | | +| - Hover mouse over a bar | Should show the default callout over that bar | RTL | +| - Set isCalloutForStack is “true” and mouse over on a bar | Should show the default stacked callout over that bar | RTL | +| - Set isCalloutForStack is “false” and mouse over on a bar | Should show the single callout over that bar | RTL | +| - Specify custom callout and hover mouse over a bar | Should show the custom callout over that bar | RTL | +| Test 9: [Sub-Component]: x-axis labels | | | +| - Truncate x-axis labels | Should show the x-axis labels tooltip when hovered | RTL | +| - Rotate x-axis labels | Should rotate the x-axis labels by 45 degrees | RTL | +| - Set showXAxisLablestoolTip to “true” and mouse over on label | Should show XAxis labels tooltip when mouse over on label | RTL | +| Test 10: [Sub-Component]: Screen resolution | | | +| - Increase the screen resolution (zoom in) | Should remain unchanged on zoom in | RTL | +| - Decrease the screen resolution (zoom out) | Should remain unchanged on zoom out | RTL | +| Test 11: Theme changed to Dark Theme | Should reflect theme change | RTL | +| Test 10: Grouped vertical bar chart re-rendering | | | +| - Update chart data | Should re-render chart when data is updated | RTL | +| Test 11: Grouped vertical bar chart with empty/proper data | | | +| - Chart with Empty data | Should render chart with Empty chart are label | Enzyme | +| - Chart with proper data | Should not render chart with empty chart are label | Enzyme | diff --git a/packages/react-charting/src/components/GroupedVerticalBarChart/GroupedVerticalBarChartRTL.test.tsx b/packages/react-charting/src/components/GroupedVerticalBarChart/GroupedVerticalBarChartRTL.test.tsx index 60911e280ad241..4a10f9807d9d0d 100644 --- a/packages/react-charting/src/components/GroupedVerticalBarChart/GroupedVerticalBarChartRTL.test.tsx +++ b/packages/react-charting/src/components/GroupedVerticalBarChart/GroupedVerticalBarChartRTL.test.tsx @@ -1,13 +1,459 @@ import * as React from 'react'; -import { queryAllByAttribute, render, waitFor } from '@testing-library/react'; -import { chartPoints, emptyChartPoints } from './GroupedVerticalBarChart.test'; +import { screen, fireEvent, act } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; +import { emptyChartPoints } from './GroupedVerticalBarChart.test'; import { GroupedVerticalBarChart } from './index'; +import { DefaultPalette } from '@fluentui/react/lib/Styling'; +import { getByClass, getById, testWithWait, testWithoutWait } from '../../utilities/TestUtility.test'; +import { IGroupedVerticalBarChartData, IVSChartDataPoint } from '../../index'; +import { DarkTheme } from '@fluentui/theme-samples'; +import { ThemeProvider } from '@fluentui/react'; + +const accessibilityDataPoints: IGroupedVerticalBarChartData[] = [ + { + name: 'Metadata info multi lines text Completed', + series: [ + { + key: 'series1', + data: 33000, + color: DefaultPalette.blueLight, + legend: 'MetaData1', + xAxisCalloutData: '2020/04/30', + yAxisCalloutData: '33%', + callOutAccessibilityData: { + ariaLabel: 'Group series 1 of 4, Bar series 1 of 2 x-Axis 2020/04/30 MetaData1 33%', + }, + }, + { + key: 'series2', + data: 44000, + color: DefaultPalette.blue, + legend: 'MetaData4', + xAxisCalloutData: '2020/04/30', + yAxisCalloutData: '44%', + callOutAccessibilityData: { + ariaLabel: 'Bar series 2 of 2 x-Axis 2020/04/30 MetaData4 44%', + }, + }, + ], + stackCallOutAccessibilityData: { + ariaLabel: 'Group series 1 of 4 x-Axis 2020/04/30 MetaData1 33% MetaData4 44%', + }, + }, +]; + +const chartPoints = [ + { + name: 'Metadata info multi lines text Completed', + series: [ + { + key: 'series1', + data: 33000, + color: DefaultPalette.blueLight, + legend: 'MetaData1', + xAxisCalloutData: '2020/04/30', + yAxisCalloutData: '33%', + }, + { + key: 'series2', + data: 44000, + color: DefaultPalette.blue, + legend: 'MetaData4', + xAxisCalloutData: '2020/04/30', + yAxisCalloutData: '44%', + }, + ], + }, + { + name: 'Meta Data2', + series: [ + { + key: 'series1', + data: 33000, + color: DefaultPalette.blueLight, + legend: 'MetaData1', + xAxisCalloutData: '2020/05/30', + yAxisCalloutData: '33%', + }, + { + key: 'series2', + data: 3000, + color: DefaultPalette.blue, + legend: 'MetaData4', + xAxisCalloutData: '2020/05/30', + yAxisCalloutData: '3%', + }, + ], + }, + + { + name: 'Single line text ', + series: [ + { + key: 'series1', + data: 14000, + color: DefaultPalette.blueLight, + legend: 'MetaData1', + xAxisCalloutData: '2020/06/30', + yAxisCalloutData: '14%', + }, + { + key: 'series2', + data: 50000, + color: DefaultPalette.blue, + legend: 'MetaData4', + xAxisCalloutData: '2020/06/30', + yAxisCalloutData: '50%', + }, + ], + }, +]; + +describe('Grouped Vertical bar chart rendering', () => { + testWithoutWait( + 'Should render the grouped vertical bar chart with string x-axis data', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + // Assert + expect(container).toMatchSnapshot(); + }, + ); + + testWithWait( + 'Should render the vertical bar chart with string x-axis data with given container width and bar width', + GroupedVerticalBarChart, + { data: chartPoints, width: 1000, barWidth: 16 }, + container => { + // Assert + expect(container).toMatchSnapshot(); + }, + ); +}); + +describe('Grouped vertical bar chart - Subcomponent bar', () => { + testWithWait( + 'Should render the bars with the specified colors', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + // colors mentioned in the data points itself + // Assert + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + expect(bars[0].getAttribute('fill')).toEqual(DefaultPalette.blueLight); + expect(bars[1].getAttribute('fill')).toEqual(DefaultPalette.blue); + expect(bars[2].getAttribute('fill')).toEqual(DefaultPalette.blueLight); + expect(bars[3].getAttribute('fill')).toEqual(DefaultPalette.blue); + expect(bars[4].getAttribute('fill')).toEqual(DefaultPalette.blueLight); + expect(bars[5].getAttribute('fill')).toEqual(DefaultPalette.blue); + }, + ); + + testWithWait( + 'Should render the bars with labels hidden', + GroupedVerticalBarChart, + { data: chartPoints, hideLabels: true }, + container => { + // Assert + expect(getByClass(container, /barLabel/i)).toHaveLength(0); + }, + ); + + testWithWait( + 'Should render the with custom accessibility data', + GroupedVerticalBarChart, + { data: accessibilityDataPoints }, + container => { + // Assert + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + expect(bars[0]).toHaveAttribute( + 'aria-label', + 'Group series 1 of 4, Bar series 1 of 2 x-Axis 2020/04/30 MetaData1 33%', + ); + }, + ); +}); + +describe('Grouped vertical bar chart - Subcomponent Legends', () => { + testWithoutWait( + 'Should not show any rendered legends when hideLegend is true', + GroupedVerticalBarChart, + { data: chartPoints, hideLegend: true }, + container => { + // Assert + // Legends have 'rect' as a part of their classname + const legends = getByClass(container, /legend-/i); + expect(legends).toHaveLength(0); + }, + ); + + testWithoutWait( + 'Should reduce the opacity of the other bars on mouse over a bar legend', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + const legends = getByClass(container, /legend-/i); + fireEvent.mouseOver(legends[0]); + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + // Assert + expect(bars[0]).toHaveAttribute('opacity', ''); + expect(bars[1]).toHaveAttribute('opacity', '0.1'); + expect(bars[2]).toHaveAttribute('opacity', ''); + expect(bars[3]).toHaveAttribute('opacity', '0.1'); + expect(bars[4]).toHaveAttribute('opacity', ''); + expect(bars[5]).toHaveAttribute('opacity', '0.1'); + }, + ); + + testWithoutWait( + 'Should update the opacity of the other bars on mouse move from one bar legend to another bar legend', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + const legends = getByClass(container, /legend-/i); + fireEvent.mouseOver(legends[0]); + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + // Assert + expect(bars[0]).toHaveAttribute('opacity', ''); + expect(bars[1]).toHaveAttribute('opacity', '0.1'); + expect(bars[2]).toHaveAttribute('opacity', ''); + expect(bars[3]).toHaveAttribute('opacity', '0.1'); + expect(bars[4]).toHaveAttribute('opacity', ''); + expect(bars[5]).toHaveAttribute('opacity', '0.1'); + fireEvent.mouseOver(legends[1]); + const updatedBars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + // Assert + expect(updatedBars[0]).toHaveAttribute('opacity', '0.1'); + expect(updatedBars[1]).toHaveAttribute('opacity', ''); + expect(updatedBars[2]).toHaveAttribute('opacity', '0.1'); + expect(updatedBars[3]).toHaveAttribute('opacity', ''); + expect(updatedBars[4]).toHaveAttribute('opacity', '0.1'); + expect(updatedBars[5]).toHaveAttribute('opacity', ''); + }, + ); + + testWithWait( + 'Should select legend on single mouse click on legends', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + const legends = getByClass(container, /legend-/i); + fireEvent.click(legends![0]); + const legendsAfterClickEvent = screen.getAllByText( + (content, element) => element!.tagName.toLowerCase() === 'button', + ); + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + // Assert + expect(legendsAfterClickEvent[0]).toHaveAttribute('aria-selected', 'true'); + expect(legendsAfterClickEvent[1]).toHaveAttribute('aria-selected', 'false'); + expect(bars[0]).toHaveAttribute('opacity', ''); + expect(bars[1]).toHaveAttribute('opacity', '0.1'); + expect(bars[2]).toHaveAttribute('opacity', ''); + expect(bars[3]).toHaveAttribute('opacity', '0.1'); + expect(bars[4]).toHaveAttribute('opacity', ''); + expect(bars[5]).toHaveAttribute('opacity', '0.1'); + }, + ); + + testWithWait( + 'Should deselect legend on double mouse click on legends', + GroupedVerticalBarChart, + { data: chartPoints }, + container => { + const legends = getByClass(container, /legend-/i); + fireEvent.click(legends![0]); + fireEvent.click(legends![0]); + const legendsAfterClickEvent = screen.getAllByText( + (content, element) => element!.tagName.toLowerCase() === 'button', + ); + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + // Assert + expect(legendsAfterClickEvent[0]).toHaveAttribute('aria-selected', 'false'); + expect(legendsAfterClickEvent[1]).toHaveAttribute('aria-selected', 'false'); + expect(bars[0]).toHaveAttribute('opacity', ''); + expect(bars[1]).toHaveAttribute('opacity', ''); + expect(bars[2]).toHaveAttribute('opacity', ''); + expect(bars[3]).toHaveAttribute('opacity', ''); + expect(bars[4]).toHaveAttribute('opacity', ''); + expect(bars[5]).toHaveAttribute('opacity', ''); + }, + ); +}); + +describe('Grouped vertical bar chart - Subcomponent callout', () => { + testWithWait( + 'Should show the callout over the bar on mouse over', + GroupedVerticalBarChart, + { data: chartPoints, calloutProps: { doNotLayer: true } }, + container => { + // Arrange + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + fireEvent.mouseOver(bars[0]); + // Assert + expect(getById(container, /toolTipcallout/i)).toBeDefined(); + }, + ); + + testWithWait( + 'Should show the stacked callout over the bar on mouse over', + GroupedVerticalBarChart, + { data: chartPoints, isCalloutForStack: true, calloutProps: { doNotLayer: true } }, + container => { + // Arrange + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + expect(bars).toHaveLength(6); + fireEvent.mouseOver(bars[0]); + // Assert + expect(getByClass(container, /calloutlegendText/i)).toBeDefined(); + expect(getByClass(container, /calloutlegendText/i)).toHaveLength(2); + }, + ); + + testWithWait( + 'Should show the single callout over the bar on mouse over', + GroupedVerticalBarChart, + { data: chartPoints, isCalloutForStack: false, calloutProps: { doNotLayer: true } }, + container => { + // Arrange + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + expect(bars).toHaveLength(6); + fireEvent.mouseOver(bars[0]); + // Assert + expect(getByClass(container, /calloutlegendText/i)).toBeDefined(); + expect(getByClass(container, /calloutlegendText/i)).toHaveLength(1); + }, + ); + + testWithWait( + 'Should show the custom callout over the bar on mouse over', + GroupedVerticalBarChart, + { + data: chartPoints, + calloutProps: { doNotLayer: true }, + onRenderCalloutPerDataPoint: (props: IVSChartDataPoint) => + props ? ( +
+

Custom Callout Content

+
+ ) : null, + }, + container => { + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + fireEvent.mouseOver(bars[0]); + // Assert + expect(getById(container, /toolTipcallout/i)).toBeDefined(); + expect(screen.queryByText('Custom Callout Content')).toBeDefined(); + }, + ); +}); + +describe('Grouped vertical bar chart - Subcomponent Labels', () => { + testWithWait( + 'Should render the xAxis label based on noOfCharsToTruncate', + GroupedVerticalBarChart, + { data: chartPoints, showXAxisLablesTooltip: true, noOfCharsToTruncate: 3 }, + container => { + // Assert + expect(getById(container, /showDots/i)).toHaveLength(3); + expect(getById(container, /showDots/i)[0]!.textContent!).toEqual('Met...'); + }, + ); + + testWithWait( + 'Should show rotated x-axis labels', + GroupedVerticalBarChart, + { data: chartPoints, rotateXAxisLables: true }, + container => { + // Assert + expect(getByClass(container, /tick/i)[0].getAttribute('transform')).toContain('rotate(-45)'); + }, + ); + + testWithWait( + 'Should show the x-axis labels tooltip when hovered', + GroupedVerticalBarChart, + { data: chartPoints, showXAxisLablesTooltip: true }, + container => { + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + expect(bars).toHaveLength(6); + fireEvent.mouseOver(bars[0]); + // Assert + expect(getById(container, /showDots/i)).toHaveLength(3); + expect(getById(container, /showDots/i)[0]!.textContent!).toEqual('Meta...'); + }, + ); + + testWithWait( + 'Should render the xAxis and yAxis with specified tick count', + GroupedVerticalBarChart, + { data: chartPoints, yAxisTickCount: 5 }, + container => { + // total tick count = x tick count + y tick count + // Assert + expect(getByClass(container, /tick/i)).toHaveLength(9); + }, + ); +}); + +describe('Grouped vertical bar chart - Screen resolution', () => { + const originalInnerWidth = global.innerWidth; + const originalInnerHeight = global.innerHeight; + afterEach(() => { + global.innerWidth = originalInnerWidth; + global.innerHeight = originalInnerHeight; + act(() => { + global.dispatchEvent(new Event('resize')); + }); + }); + + testWithWait( + 'Should remain unchanged on zoom in', + GroupedVerticalBarChart, + { data: chartPoints, width: 300, height: 300 }, + container => { + global.innerWidth = window.innerWidth / 2; + global.innerHeight = window.innerHeight / 2; + act(() => { + global.dispatchEvent(new Event('resize')); + }); + // Assert + expect(container).toMatchSnapshot(); + }, + ); + + testWithWait( + 'Should remain unchanged on zoom out', + GroupedVerticalBarChart, + { data: chartPoints, width: 300, height: 300 }, + container => { + global.innerWidth = window.innerWidth * 2; + global.innerHeight = window.innerHeight * 2; + act(() => { + global.dispatchEvent(new Event('resize')); + }); + // Assert + expect(container).toMatchSnapshot(); + }, + ); +}); + +describe('Vertical stacked bar chart - Theme', () => { + test('Should reflect theme change', () => { + // Arrange + const { container } = render( + + + , + ); + // Assert + expect(container).toMatchSnapshot(); + }); +}); describe('Grouped Vertical Bar chart rendering', () => { test('Should re-render the Grouped Vertical Bar chart with data', async () => { // Arrange const { container, rerender } = render(); - const getById = queryAllByAttribute.bind(null, 'id'); // Assert expect(container).toMatchSnapshot(); expect(getById(container, /_GVBC_empty/i)).toHaveLength(1); @@ -20,3 +466,18 @@ describe('Grouped Vertical Bar chart rendering', () => { }); }); }); + +testWithWait( + 'Should render the bar with the given width', + GroupedVerticalBarChart, + { data: accessibilityDataPoints, barwidth: 16 }, + async container => { + // bar width not working as expected in the test so logged bug for same: Bug 9158 + // Assert + // await new Promise((r) => setTimeout(r, 2000)); + const bars = screen.getAllByText((content, element) => element!.tagName.toLowerCase() === 'rect'); + await new Promise(r => setTimeout(r, 5000)); + expect(bars[0].getAttribute('width')).toEqual('16'); + expect(bars[1].getAttribute('width')).toEqual('16'); + }, +); diff --git a/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChartRTL.test.tsx.snap b/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChartRTL.test.tsx.snap index 39f54c66b255f1..49952a99907e67 100644 --- a/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChartRTL.test.tsx.snap +++ b/packages/react-charting/src/components/GroupedVerticalBarChart/__snapshots__/GroupedVerticalBarChartRTL.test.tsx.snap @@ -4,7 +4,7 @@ exports[`Grouped Vertical Bar chart rendering Should re-render the Grouped Verti
+
+`; + +exports[`Grouped Vertical bar chart rendering Should render the grouped vertical bar chart with string x-axis data 1`] = ` +
+ +
+`; + +exports[`Grouped Vertical bar chart rendering Should render the vertical bar chart with string x-axis data with given container width and bar width 1`] = ` +
+ +
+`; + +exports[`Grouped vertical bar chart - Screen resolution Should remain unchanged on zoom in 1`] = ` +
+ +
+`; + +exports[`Grouped vertical bar chart - Screen resolution Should remain unchanged on zoom out 1`] = ` +
+
`; + +exports[`Vertical stacked bar chart - Theme Should reflect theme change 1`] = ` +
+
+ +
+
+`;