From de1211f9a5df249fd62758ef637f45702db59bd0 Mon Sep 17 00:00:00 2001 From: Arjun Date: Fri, 12 Jan 2024 12:53:53 +0530 Subject: [PATCH] fix: unit tests and pr comments resolved --- package.json | 2 +- src/tests/waterfallChart.test.tsx | 184 +++++++++++++++++++++---- src/waterfall-chart/WaterFallChart.tsx | 2 +- 3 files changed, 160 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index b90d78d..07cef3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@keyvaluesystems/react-waterfall-chart", - "version": "1.0.0", + "version": "0.1.5", "description": "A customizable and responsive svg waterfall chart component", "main": "build/index.js", "source": "src/index.tsx", diff --git a/src/tests/waterfallChart.test.tsx b/src/tests/waterfallChart.test.tsx index 610b36f..7b7fbda 100644 --- a/src/tests/waterfallChart.test.tsx +++ b/src/tests/waterfallChart.test.tsx @@ -3,17 +3,40 @@ import { render, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; import WaterFallChart from '../waterfall-chart'; -// Mock data for transactions +// Mock data for dataPoints const dataPoints = [ { label: 'data 1', value: 100 }, { label: 'data 2', value: -50 }, { label: 'data 3', value: 200 } ]; +const mockOnMouseClick = jest.fn(); +const mockOnMouseEnter = jest.fn(); +const mockOnMouseLeave = jest.fn(); + +const props = { + dataPoints, + barWidth: 20, + showBridgeLines: true, + showYAxisScaleLines: false, + yAxisPixelsPerUnit: 30, + showFinalSummary: true, + summaryXLabel: 'summary', + styles: { + positiveBar: { fill: 'blue' }, + negativeBar: { fill: 'red' }, + }, + onChartClick: mockOnMouseClick, + onMouseEnter: mockOnMouseEnter, + onMouseLeave: mockOnMouseLeave +} + describe('WaterFallChart component', () => { it('renders the chart with correct bars and labels', () => { - // Render the WaterFallChart component with transactions as props - const { container, getByText } = render(); + // Render the WaterFallChart component with dataPoints as props + const { container, getByText } = render(); // Assert that the chart bars are rendered with correct heights const positiveBar = container.querySelector('#chartBar-0'); @@ -29,6 +52,31 @@ describe('WaterFallChart component', () => { expect(xAxisLine).toBeInTheDocument(); expect(yAxisLine).toBeInTheDocument(); + // Assert that the summary label is rendered + const summaryLabel = getByText('summary'); + expect(summaryLabel).toBeInTheDocument(); + }); + + it('does not render the chart with correct bars and labels when data points is empty', () => { + // Render the WaterFallChart component with dataPoints as props + const { container, getByText } = render(); + + // Assert that the chart bars are rendered with correct heights + const positiveBar = container.querySelector('#chartBar-0'); + const negativeBar = container.querySelector('#chartBar-1'); + const summaryBar = container.querySelector('#summaryBar'); + expect(positiveBar).toBeNull(); + expect(negativeBar).toBeNull(); + expect(summaryBar).toBeNull(); + + // Assert that the x-axis and y-axis lines are rendered + const xAxisLine = container.querySelector('#xAxisLine'); + const yAxisLine = container.querySelector('#yAxisLine'); + expect(xAxisLine).toBeInTheDocument(); + expect(yAxisLine).toBeInTheDocument(); + // Assert that the summary label is rendered const summaryLabel = getByText('Total'); expect(summaryLabel).toBeInTheDocument(); @@ -36,11 +84,10 @@ describe('WaterFallChart component', () => { it('calls onChartClick callback when a bar is clicked', () => { // Mock callback function - const mockOnClick = jest.fn(); - // Render the WaterFallChart component with transactions and onChartClick callback as props + // Render the WaterFallChart component with dataPoints and onChartClick callback as props const { container } = render( - mockOnClick(e)} /> + ); // Click on a chart bar @@ -48,7 +95,58 @@ describe('WaterFallChart component', () => { if (barZero) { fireEvent.click(barZero); // Assert that the mock callback function is called with the correct chart element - expect(mockOnClick).toHaveBeenCalledTimes(1); + expect(mockOnMouseClick).toHaveBeenCalledTimes(1); + } + }); + + it('calls onMouseEnter and onMouseLeavecallback when a bar is hovered', () => { + // Mock callback function + const mockOnMounseEnter = jest.fn(); + const mockOnMounseLeave = jest.fn(); + + // Render the WaterFallChart component with dataPoints and onChartClick callback as props + const { container } = render( + mockOnMounseEnter(e, chartElement)} + onMouseLeave={(e: any, chartElement) => mockOnMounseLeave(e, chartElement)} + /> + ); + + // Click on a chart bar + const barZero = container.querySelector('#chartBar-0'); + if (barZero) { + fireEvent.mouseEnter(barZero); + // Assert that the mock callback function is called with the correct chart element + expect(mockOnMounseEnter).toHaveBeenCalledTimes(1); + fireEvent.mouseLeave(barZero); + // Assert that the mock callback function is called with the correct chart element + expect(mockOnMounseLeave).toHaveBeenCalledTimes(1); + } + }); + + it('calls onMouseEnter and onMouseLeave callback when a bar is hovered', () => { + // Mock callback functions + const mockOnMouseEnter = jest.fn(); + const mockOnMouseLeave = jest.fn(); + + // Render the WaterFallChart component with dataPoints and callback props + const { container } = render( + mockOnMouseEnter(e, chartElement)} + onMouseLeave={(e, chartElement) => mockOnMouseLeave(e, chartElement)} + /> + ); + + // Simulate mouse events + const barZero = container.querySelector('#chartBar-0'); + if (barZero) { + fireEvent.mouseEnter(barZero); + fireEvent.mouseLeave(barZero); + + // Assert that the mock callback functions are called + expect(mockOnMouseEnter).toHaveBeenCalledTimes(1); + expect(mockOnMouseLeave).toHaveBeenCalledTimes(1); } }); @@ -79,28 +177,62 @@ describe('WaterFallChart component', () => { expect(summaryBar).toBeNull(); }); - it('calls onMouseEnter and onMouseLeavecallback when a bar is hovered', () => { + it('sets barWidth based on calculateBarWidth when initialBarWidth is 0 or not defined', () => { + // Render the WaterFallChart component with initialBarWidth as 0 or undefined + const { container } = render(); + const barZero = container.querySelector('#chartBar-0'); + + if (barZero) { + expect(barZero).toHaveAttribute('width', '100'); + } + }); + + it('handles resize event and recalculates barWidth when initialBarWidth is 0', () => { + // Render the WaterFallChart component with initialBarWidth as 0 + const { container } = render(); + const barZero = container.querySelector('#chartBar-0'); + + if (barZero) { + fireEvent(window, new Event('resize')); + expect(barZero).toHaveAttribute('width', '100'); + } + }); + + it('handles resize event and recalculates barWidth when initialBarWidth is less than or equal to 0', () => { + // Render the WaterFallChart component with initialBarWidth as -10 + const { container } = render(); + const barZero = container.querySelector('#chartBar-0'); + + if (barZero) { + fireEvent(window, new Event('resize')); + expect(barZero).toHaveAttribute('width', '100'); + } + }); + + it('does not set barWidth based on calculateBarWidth when initialBarWidth is greater than 0', () => { + // Render the WaterFallChart component with initialBarWidth as 50 + const { container } = render(); + const barZero = container.querySelector('#chartBar-0'); + + if (barZero) { + expect(barZero).toHaveAttribute('width', '50'); + } + }); + + it('calls onChartClick callback when clicking summary bar', () => { // Mock callback function - const mockOnMounseEnter = jest.fn(); - const mockOnMounseLeave = jest.fn(); - - // Render the WaterFallChart component with transactions and onChartClick callback as props + const mockOnClick = jest.fn(); + + // Render the WaterFallChart component with onChartClick callback as props const { container } = render( - mockOnMounseEnter(e, chartElement)} - onMouseLeave={(e: any, chartElement) => mockOnMounseLeave(e, chartElement)} - /> + mockOnClick(e)} /> ); - - // Click on a chart bar - const barZero = container.querySelector('#chartBar-0'); - if (barZero) { - fireEvent.mouseEnter(barZero); - // Assert that the mock callback function is called with the correct chart element - expect(mockOnMounseEnter).toHaveBeenCalledTimes(1); - fireEvent.mouseLeave(barZero); - // Assert that the mock callback function is called with the correct chart element - expect(mockOnMounseLeave).toHaveBeenCalledTimes(1); + + // Click on the summary bar + const summaryBar = container.querySelector('#summaryBar'); + if (summaryBar) { + fireEvent.click(summaryBar); + expect(mockOnClick).toHaveBeenCalledTimes(1); } }); }); diff --git a/src/waterfall-chart/WaterFallChart.tsx b/src/waterfall-chart/WaterFallChart.tsx index eaaba5d..451d2da 100644 --- a/src/waterfall-chart/WaterFallChart.tsx +++ b/src/waterfall-chart/WaterFallChart.tsx @@ -27,7 +27,7 @@ const WaterFallChart: FC = (props) => { } = props; const wrapperRef = useRef(null); - const [wrapperHeight, setWrapperHeight] = useState(0); + const [wrapperHeight, setWrapperHeight] = useState(wrapperRef?.current?.offsetHeight || 0); const [barWidth, setBarWidth] = useState(initialBarWidth); const yAxisPixelsPerUnit = initialYAxisPixelsPerUnit ? initialYAxisPixelsPerUnit : DEFAULT_PIXELS_PER_Y_UNIT;