From d3af988a18adbb285269955dfef3c44df78043bf Mon Sep 17 00:00:00 2001 From: "Mr.Dr.Professor Patrick" Date: Wed, 20 Sep 2023 13:39:31 +0200 Subject: [PATCH] feat(Select): add onClear argument to renderControl method (#1022) --- .../Select/__tests__/Select.clear.test.tsx | 19 +++++++++++- src/components/Select/__tests__/utils.tsx | 30 ++++++++++++++----- .../SelectControl/SelectControl.tsx | 5 ++-- src/components/Select/types.ts | 3 +- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/components/Select/__tests__/Select.clear.test.tsx b/src/components/Select/__tests__/Select.clear.test.tsx index 16e8dd9758..7204220a05 100644 --- a/src/components/Select/__tests__/Select.clear.test.tsx +++ b/src/components/Select/__tests__/Select.clear.test.tsx @@ -4,7 +4,7 @@ import userEvent from '@testing-library/user-event'; import {SelectQa} from '../constants'; import type {SelectProps} from '../types'; -import {DEFAULT_OPTIONS, setup} from './utils'; +import {DEFAULT_OPTIONS, renderControl, setup} from './utils'; afterEach(() => { cleanup(); @@ -73,4 +73,21 @@ describe('Select clear', () => { await user.keyboard('[Enter]'); expect(onUpdate).toHaveBeenCalledWith([]); }); + + test.each([[{multiple: false}], [{multiple: true}]])( + 'check for correct onClear invocation in case of using renderControl without basic clear button (args: %j)', + async (props) => { + const {getByText} = setup({ + ...props, + options: DEFAULT_OPTIONS, + value: [DEFAULT_OPTIONS[0].value], + renderControl, + onUpdate, + }); + const user = userEvent.setup(); + const clearButton = getByText('Clear'); + await user.click(clearButton); + expect(onUpdate).toHaveBeenCalledWith([]); + }, + ); }); diff --git a/src/components/Select/__tests__/utils.tsx b/src/components/Select/__tests__/utils.tsx index ec92d9529f..7542fbbc22 100644 --- a/src/components/Select/__tests__/utils.tsx +++ b/src/components/Select/__tests__/utils.tsx @@ -4,7 +4,7 @@ import {act, render} from '@testing-library/react'; import range from 'lodash/range'; import {Select} from '..'; -import type {SelectOption, SelectOptionGroup, SelectProps} from '..'; +import type {SelectOption, SelectOptionGroup, SelectProps, SelectRenderControlProps} from '..'; import {MobileProvider} from '../../mobile'; import {selectControlBlock, selectControlButtonBlock, selectListBlock} from '../constants'; @@ -51,16 +51,16 @@ export const ControlledSelect = (props: Partial) => { ); }; -export function setup(props: Partial = {}, mobile?: boolean) { +export const setup = (props: Partial = {}, mobile?: boolean) => { const utils = render( , ); return utils; -} +}; -export function timeout(ms: number) { +export const timeout = (ms: number) => { // https://testing-library.com/docs/react-testing-library/api/#act // https://reactjs.org/docs/test-utils.html#act return act(async () => { @@ -68,7 +68,7 @@ export function timeout(ms: number) { setTimeout(resolve, ms); }); }); -} +}; export function generateOptions(args: number | [string, string][]): SelectOption[] { if (typeof args === 'number') { @@ -81,12 +81,26 @@ export function generateOptions(args: number | [string, string][]): SelectOption return args.map(([value, content]) => ({value, content})); } -export function generateOptionsGroups( +export const generateOptionsGroups = ( groupsCount: number, optionsCount: number, -): SelectOptionGroup[] { +): SelectOptionGroup[] => { return range(0, groupsCount).map((i) => ({ label: `Group ${i + 1}`, options: generateOptions(optionsCount), })); -} +}; + +export const renderControl = (args: SelectRenderControlProps) => { + const {onClear, onClick, onKeyDown, ref} = args; + return ( +
+ + +
+ ); +}; diff --git a/src/components/Select/components/SelectControl/SelectControl.tsx b/src/components/Select/components/SelectControl/SelectControl.tsx index dbbb2d73d1..10a372ed76 100644 --- a/src/components/Select/components/SelectControl/SelectControl.tsx +++ b/src/components/Select/components/SelectControl/SelectControl.tsx @@ -33,7 +33,7 @@ type ControlProps = { value: SelectProps['value']; clearValue: () => void; hasClear?: boolean; -} & Omit; +} & Omit; export const SelectControl = React.forwardRef((props, ref) => { const { @@ -117,10 +117,11 @@ export const SelectControl = React.forwardRef(( return renderControl( { onKeyDown, + onClear: clearValue, onClick: toggleOpen, + renderClear: (arg) => renderClearIcon(arg), ref, open: Boolean(open), - renderClear: (arg) => renderClearIcon(arg), popupId, selectId, activeIndex, diff --git a/src/components/Select/types.ts b/src/components/Select/types.ts index e0ef0d81a8..8e5360b62e 100644 --- a/src/components/Select/types.ts +++ b/src/components/Select/types.ts @@ -11,11 +11,12 @@ export type SelectRenderClearArgs = { }; export type SelectRenderControlProps = { + onClear: () => void; onClick: (e: React.MouseEvent) => void; onKeyDown: (e: React.KeyboardEvent) => void; + renderClear?: (args: SelectRenderClearArgs) => React.ReactNode; ref: React.Ref; open: boolean; - renderClear?: (args: SelectRenderClearArgs) => React.ReactNode; popupId: string; selectId: string; activeIndex?: number;