From 5c302e95605ab927b1ae5500cc4b98c7646f2f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 23 Aug 2023 15:05:33 +0800 Subject: [PATCH 1/3] test: test driven --- tests/Select.multiple.spec.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/Select.multiple.spec.js b/tests/Select.multiple.spec.js index 93012bd2..ec95f5e5 100644 --- a/tests/Select.multiple.spec.js +++ b/tests/Select.multiple.spec.js @@ -1,7 +1,8 @@ /* eslint-disable no-undef */ -import React from 'react'; +import { render } from '@testing-library/react'; import { mount } from 'enzyme'; import KeyCode from 'rc-util/lib/KeyCode'; +import React from 'react'; import TreeSelect, { TreeNode } from '../src'; import focusTest from './shared/focusTest'; @@ -279,4 +280,34 @@ describe('TreeSelect.multiple', () => { expect(onChange).toHaveBeenCalledWith([], expect.anything(), expect.anything()); expect(onDeselect).toHaveBeenCalledWith('not-exist', undefined); }); + + it('should not omit value', () => { + const { container } = render( + , + ); + + const values = Array.from( + container.querySelectorAll('.rc-tree-select-selection-item-content'), + ).map(ele => ele.textContent); + expect(values).toEqual(['child1', 'child2', 'parent']); + }); }); From 895a328b218387c234a9813598c97058c38e4a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 23 Aug 2023 15:08:11 +0800 Subject: [PATCH 2/3] test: test driven --- src/TreeSelect.tsx | 80 ++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/src/TreeSelect.tsx b/src/TreeSelect.tsx index 139c5ed9..4ced9d50 100644 --- a/src/TreeSelect.tsx +++ b/src/TreeSelect.tsx @@ -1,33 +1,33 @@ -import * as React from 'react'; -import { BaseSelect } from 'rc-select'; -import type { IconType } from 'rc-tree/lib/interface'; -import type { ExpandAction } from 'rc-tree/lib/Tree'; import type { - BaseSelectRef, - BaseSelectPropsWithoutPrivate, BaseSelectProps, + BaseSelectPropsWithoutPrivate, + BaseSelectRef, SelectProps, } from 'rc-select'; -import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; +import { BaseSelect } from 'rc-select'; import useId from 'rc-select/lib/hooks/useId'; +import type { IconType } from 'rc-tree/lib/interface'; +import type { ExpandAction } from 'rc-tree/lib/Tree'; +import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; +import warning from 'rc-util/lib/warning'; +import * as React from 'react'; +import useCache from './hooks/useCache'; +import useCheckedKeys from './hooks/useCheckedKeys'; +import useDataEntities from './hooks/useDataEntities'; +import useFilterTreeData from './hooks/useFilterTreeData'; +import useRefFunc from './hooks/useRefFunc'; +import useTreeData from './hooks/useTreeData'; +import LegacyContext from './LegacyContext'; import OptionList from './OptionList'; import TreeNode from './TreeNode'; -import { formatStrategyValues, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './utils/strategyUtil'; -import type { CheckedStrategy } from './utils/strategyUtil'; -import TreeSelectContext from './TreeSelectContext'; import type { TreeSelectContextProps } from './TreeSelectContext'; -import LegacyContext from './LegacyContext'; -import useTreeData from './hooks/useTreeData'; -import { toArray, fillFieldNames, isNil } from './utils/valueUtil'; -import useCache from './hooks/useCache'; -import useRefFunc from './hooks/useRefFunc'; -import useDataEntities from './hooks/useDataEntities'; +import TreeSelectContext from './TreeSelectContext'; import { fillAdditionalInfo, fillLegacyProps } from './utils/legacyUtil'; -import useCheckedKeys from './hooks/useCheckedKeys'; -import useFilterTreeData from './hooks/useFilterTreeData'; +import type { CheckedStrategy } from './utils/strategyUtil'; +import { formatStrategyValues, SHOW_ALL, SHOW_CHILD, SHOW_PARENT } from './utils/strategyUtil'; +import { fillFieldNames, isNil, toArray } from './utils/valueUtil'; import warningProps from './utils/warningPropsUtil'; -import warning from 'rc-util/lib/warning'; export type OnInternalSelect = (value: RawValueType, info: { selected: boolean }) => void; @@ -105,7 +105,7 @@ export interface LegacyDataNode extends DefaultOptionType { } export interface TreeSelectProps< ValueType = any, - OptionType extends BaseOptionType = DefaultOptionType + OptionType extends BaseOptionType = DefaultOptionType, > extends Omit { prefixCls?: string; id?: string; @@ -194,7 +194,7 @@ const TreeSelect = React.forwardRef((props, ref) treeNodeFilterProp = 'value', // Selector - showCheckedStrategy = SHOW_CHILD, + showCheckedStrategy, treeNodeLabelProp, // Mode @@ -246,6 +246,15 @@ const TreeSelect = React.forwardRef((props, ref) const [internalValue, setInternalValue] = useMergedState(defaultValue, { value }); + // `multiple` && `!treeCheckable` should be show all + const mergedShowCheckedStrategy = React.useMemo(() => { + if (!treeCheckable) { + return SHOW_ALL; + } + + return showCheckedStrategy || SHOW_CHILD; + }, [showCheckedStrategy, treeCheckable]); + // ========================== Warning =========================== if (process.env.NODE_ENV !== 'production') { warningProps(props); @@ -357,7 +366,9 @@ const TreeSelect = React.forwardRef((props, ref) rawDisabled = entity.node.disabled; } else if (rawLabel === undefined) { // We try to find in current `labelInValue` value - const labelInValueItem = toLabeledValues(internalValue).find(labeledItem => labeledItem.value === rawValue); + const labelInValueItem = toLabeledValues(internalValue).find( + labeledItem => labeledItem.value === rawValue, + ); rawLabel = labelInValueItem.label; } @@ -373,10 +384,10 @@ const TreeSelect = React.forwardRef((props, ref) ); // =========================== Values =========================== - const rawMixedLabeledValues = React.useMemo(() => toLabeledValues(internalValue), [ - toLabeledValues, - internalValue, - ]); + const rawMixedLabeledValues = React.useMemo( + () => toLabeledValues(internalValue), + [toLabeledValues, internalValue], + ); // Split value into full check and half check const [rawLabeledValues, rawHalfLabeledValues] = React.useMemo(() => { @@ -395,9 +406,10 @@ const TreeSelect = React.forwardRef((props, ref) }, [rawMixedLabeledValues]); // const [mergedValues] = useCache(rawLabeledValues); - const rawValues = React.useMemo(() => rawLabeledValues.map(item => item.value), [ - rawLabeledValues, - ]); + const rawValues = React.useMemo( + () => rawLabeledValues.map(item => item.value), + [rawLabeledValues], + ); // Convert value to key. Will fill missed keys for conduct check. const [rawCheckedValues, rawHalfCheckedValues] = useCheckedKeys( @@ -412,7 +424,7 @@ const TreeSelect = React.forwardRef((props, ref) // Collect keys which need to show const displayKeys = formatStrategyValues( rawCheckedValues, - showCheckedStrategy, + mergedShowCheckedStrategy, keyEntities, mergedFieldNames, ); @@ -447,7 +459,7 @@ const TreeSelect = React.forwardRef((props, ref) rawCheckedValues, rawLabeledValues, convert2LabelValues, - showCheckedStrategy, + mergedShowCheckedStrategy, keyEntities, ]); @@ -474,7 +486,7 @@ const TreeSelect = React.forwardRef((props, ref) if (treeConduction) { const formattedKeyList = formatStrategyValues( newRawValues, - showCheckedStrategy, + mergedShowCheckedStrategy, keyEntities, mergedFieldNames, ); @@ -743,9 +755,9 @@ if (process.env.NODE_ENV !== 'production') { TreeSelect.displayName = 'TreeSelect'; } -const GenericTreeSelect = (TreeSelect as unknown) as (< +const GenericTreeSelect = TreeSelect as unknown as (< ValueType = any, - OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType + OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, >( props: React.PropsWithChildren> & { ref?: React.Ref; From f43fc2fef10d88d9456a563dc08195d3f8ae28d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 23 Aug 2023 15:10:27 +0800 Subject: [PATCH 3/3] test: update snapshot --- tests/__snapshots__/Select.checkable.spec.tsx.snap | 4 ++++ tests/__snapshots__/Select.multiple.spec.js.snap | 1 + tests/__snapshots__/Select.spec.tsx.snap | 10 ++++++++++ 3 files changed, 15 insertions(+) diff --git a/tests/__snapshots__/Select.checkable.spec.tsx.snap b/tests/__snapshots__/Select.checkable.spec.tsx.snap index 63c51d47..399eea10 100644 --- a/tests/__snapshots__/Select.checkable.spec.tsx.snap +++ b/tests/__snapshots__/Select.checkable.spec.tsx.snap @@ -105,6 +105,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1 aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -297,6 +298,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2 aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -573,6 +575,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -765,6 +768,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" diff --git a/tests/__snapshots__/Select.multiple.spec.js.snap b/tests/__snapshots__/Select.multiple.spec.js.snap index 083a80a8..4a25550b 100644 --- a/tests/__snapshots__/Select.multiple.spec.js.snap +++ b/tests/__snapshots__/Select.multiple.spec.js.snap @@ -23,6 +23,7 @@ exports[`TreeSelect.multiple can hide search box by showSearch = false 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="false" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" diff --git a/tests/__snapshots__/Select.spec.tsx.snap b/tests/__snapshots__/Select.spec.tsx.snap index 91ace01a..32709091 100644 --- a/tests/__snapshots__/Select.spec.tsx.snap +++ b/tests/__snapshots__/Select.spec.tsx.snap @@ -15,6 +15,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -208,6 +209,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`] aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -410,6 +412,7 @@ exports[`TreeSelect.basic render renders correctly 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="false" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="awesome-selection-search-input" @@ -452,6 +455,7 @@ exports[`TreeSelect.basic render renders disabled correctly 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="false" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -495,6 +499,7 @@ exports[`TreeSelect.basic render renders tree correctly 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="false" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -538,6 +543,7 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -677,6 +683,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -784,6 +791,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -917,6 +925,7 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input" @@ -1049,6 +1058,7 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = ` aria-controls="rc_select_TEST_OR_SSR_list" aria-expanded="true" aria-haspopup="listbox" + aria-label="Search" aria-owns="rc_select_TEST_OR_SSR_list" autocomplete="off" class="rc-tree-select-selection-search-input"