From 37ff9480e14b70e4368ea7b29645d67c82209393 Mon Sep 17 00:00:00 2001 From: Palash Gupta Date: Tue, 2 May 2023 18:51:24 +0530 Subject: [PATCH] test: dashboard variable is updated (#2640) Co-authored-by: Vishal Sharma --- .../VariableItem.test.tsx | 168 ++++++++++++++++++ .../VariableItem.tsx | 60 ++++--- .../DashboardVariablesSelection/utils.test.ts | 33 ++++ 3 files changed, 234 insertions(+), 27 deletions(-) create mode 100644 frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx create mode 100644 frontend/src/container/NewDashboard/DashboardVariablesSelection/utils.test.ts diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx new file mode 100644 index 0000000000..148591c568 --- /dev/null +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx @@ -0,0 +1,168 @@ +import '@testing-library/jest-dom/extend-expect'; + +import { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; +import { IDashboardVariable } from 'types/api/dashboard/getAll'; + +import VariableItem from './VariableItem'; + +const mockVariableData: IDashboardVariable = { + description: 'Test Variable', + type: 'TEXTBOX', + textboxValue: 'defaultValue', + sort: 'DISABLED', + multiSelect: false, + showALLOption: false, + name: 'testVariable', +}; + +// New mock data for a custom variable +const mockCustomVariableData: IDashboardVariable = { + ...mockVariableData, + name: 'customVariable', + type: 'CUSTOM', + customValue: 'option1,option2,option3', +}; + +const mockOnValueUpdate = jest.fn(); +const mockOnAllSelectedUpdate = jest.fn(); + +describe('VariableItem', () => { + let useEffectSpy: jest.SpyInstance; + + beforeEach(() => { + useEffectSpy = jest.spyOn(React, 'useEffect'); + }); + + afterEach(() => { + jest.clearAllMocks(); + useEffectSpy.mockRestore(); + }); + + test('renders component with default props', () => { + render( + , + ); + + expect(screen.getByText('$testVariable')).toBeInTheDocument(); + }); + + test('renders Input when the variable type is TEXTBOX', () => { + render( + , + ); + expect(screen.getByPlaceholderText('Enter value')).toBeInTheDocument(); + }); + + test('calls onChange event handler when Input value changes', () => { + render( + , + ); + const inputElement = screen.getByPlaceholderText('Enter value'); + fireEvent.change(inputElement, { target: { value: 'newValue' } }); + + expect(mockOnValueUpdate).toHaveBeenCalledTimes(1); + expect(mockOnValueUpdate).toHaveBeenCalledWith('testVariable', 'newValue'); + expect(mockOnAllSelectedUpdate).toHaveBeenCalledTimes(1); + expect(mockOnAllSelectedUpdate).toHaveBeenCalledWith('testVariable', false); + }); + + test('renders a Select element when variable type is CUSTOM', () => { + render( + , + ); + + expect(screen.getByText('$customVariable')).toBeInTheDocument(); + expect(screen.getByTestId('variable-select')).toBeInTheDocument(); + }); + + test('renders a Select element with all selected', async () => { + const customVariableData = { + ...mockCustomVariableData, + allSelected: true, + }; + + render( + , + ); + + expect(screen.getByTitle('ALL')).toBeInTheDocument(); + }); + + test('calls useEffect when the component mounts', () => { + render( + , + ); + + expect(React.useEffect).toHaveBeenCalled(); + }); + + test('calls useEffect only once when the component mounts', () => { + // Render the component + const { rerender } = render( + , + ); + + // Create an updated version of the mock data + const updatedMockCustomVariableData = { + ...mockCustomVariableData, + selectedValue: 'option1', + }; + + // Re-render the component with the updated data + rerender( + , + ); + + // Check if the useEffect is called with the correct arguments + expect(useEffectSpy).toHaveBeenCalledTimes(4); + }); +}); diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx index 0aa6e61b90..a20e60f1a5 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx @@ -4,7 +4,7 @@ import { Input, Popover, Select, Typography } from 'antd'; import query from 'api/dashboard/variables/query'; import { commaValuesParser } from 'lib/dashbaordVariables/customCommaValuesParser'; import sortValues from 'lib/dashbaordVariables/sortVariableValues'; -import { map } from 'lodash-es'; +import map from 'lodash-es/map'; import React, { memo, useCallback, useEffect, useState } from 'react'; import { IDashboardVariable } from 'types/api/dashboard/getAll'; @@ -12,24 +12,16 @@ import { variablePropsToPayloadVariables } from '../utils'; import { SelectItemStyle, VariableContainer, VariableName } from './styles'; import { areArraysEqual } from './util'; -const { Option } = Select; - const ALL_SELECT_VALUE = '__ALL__'; interface VariableItemProps { variableData: IDashboardVariable; existingVariables: Record; onValueUpdate: ( - name: string | undefined, - arg1: - | string - | number - | boolean - | (string | number | boolean)[] - | null - | undefined, + name: string, + arg1: IDashboardVariable['selectedValue'], ) => void; - onAllSelectedUpdate: (name: string | undefined, arg1: boolean) => void; + onAllSelectedUpdate: (name: string, arg1: boolean) => void; lastUpdatedVar: string; } function VariableItem({ @@ -101,8 +93,10 @@ function VariableItem({ } else { [value] = newOptionsData; } - onValueUpdate(variableData.name, value); - onAllSelectedUpdate(variableData.name, allSelected); + if (variableData.name) { + onValueUpdate(variableData.name, value); + onAllSelectedUpdate(variableData.name, allSelected); + } } setOptionsData(newOptionsData); } @@ -133,17 +127,18 @@ function VariableItem({ }, [variableData, existingVariables]); const handleChange = (value: string | string[]): void => { - if ( - value === ALL_SELECT_VALUE || - (Array.isArray(value) && value.includes(ALL_SELECT_VALUE)) || - (Array.isArray(value) && value.length === 0) - ) { - onValueUpdate(variableData.name, optionsData); - onAllSelectedUpdate(variableData.name, true); - } else { - onValueUpdate(variableData.name, value); - onAllSelectedUpdate(variableData.name, false); - } + if (variableData.name) + if ( + value === ALL_SELECT_VALUE || + (Array.isArray(value) && value.includes(ALL_SELECT_VALUE)) || + (Array.isArray(value) && value.length === 0) + ) { + onValueUpdate(variableData.name, optionsData); + onAllSelectedUpdate(variableData.name, true); + } else { + onValueUpdate(variableData.name, value); + onAllSelectedUpdate(variableData.name, false); + } }; const selectValue = variableData.allSelected @@ -182,10 +177,21 @@ function VariableItem({ style={SelectItemStyle} loading={isLoading} showArrow + data-testid="variable-select" > - {enableSelectAll && } + {enableSelectAll && ( + + ALL + + )} {map(optionsData, (option) => ( - + + {option.toString()} + ))} ) diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/utils.test.ts b/frontend/src/container/NewDashboard/DashboardVariablesSelection/utils.test.ts new file mode 100644 index 0000000000..c258849a74 --- /dev/null +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/utils.test.ts @@ -0,0 +1,33 @@ +import { areArraysEqual } from './util'; + +describe('areArraysEqual', () => { + it('should return true for equal arrays with same order', () => { + const array1 = [1, 'a', true, 5, 'hello']; + const array2 = [1, 'a', true, 5, 'hello']; + expect(areArraysEqual(array1, array2)).toBe(true); + }); + + it('should return false for equal arrays with different order', () => { + const array1 = [1, 'a', true, 5, 'hello']; + const array2 = ['hello', 1, true, 'a', 5]; + expect(areArraysEqual(array1, array2)).toBe(false); + }); + + it('should return false for arrays with different lengths', () => { + const array1 = [1, 'a', true, 5, 'hello']; + const array2 = [1, 'a', true, 5]; + expect(areArraysEqual(array1, array2)).toBe(false); + }); + + it('should return false for arrays with different elements', () => { + const array1 = [1, 'a', true, 5, 'hello']; + const array2 = [1, 'a', true, 5, 'world']; + expect(areArraysEqual(array1, array2)).toBe(false); + }); + + it('should return true for empty arrays', () => { + const array1: string[] = []; + const array2: string[] = []; + expect(areArraysEqual(array1, array2)).toBe(true); + }); +});