Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions src/TreeSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { BaseSelectPropsWithoutPrivate, BaseSelectRef } from '@rc-component/select';
import type { BaseSelectSemanticName } from '@rc-component/select/lib/BaseSelect';
import { BaseSelect } from '@rc-component/select';
import useId from '@rc-component/util/lib/hooks/useId';
import type { IconType } from '@rc-component/tree/lib/interface';
Expand Down Expand Up @@ -36,7 +37,7 @@ import type {
} from './interface';
import useSearchConfig from './hooks/useSearchConfig';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This change updates the SemanticName type to use BaseSelectSemanticName from @rc-component/select. This ensures that the TreeSelect component's semantic names are consistent with the base select component, promoting code reuse and reducing the risk of inconsistencies. This is a good change that improves maintainability and reduces redundancy.

Consider adding a comment explaining why this change was made, and where BaseSelectSemanticName is defined.

export type SemanticName = 'input' | 'prefix' | 'suffix';
export type SemanticName = BaseSelectSemanticName;
export type PopupSemantic = 'item' | 'itemTitle';
export interface SearchConfig {
searchValue?: string;
Expand Down Expand Up @@ -736,16 +737,8 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
<BaseSelect
ref={ref}
{...restProps}
classNames={{
prefix: treeSelectClassNames?.prefix,
suffix: treeSelectClassNames?.suffix,
input: treeSelectClassNames?.input,
}}
styles={{
prefix: styles?.prefix,
suffix: styles?.suffix,
input: styles?.input,
}}
classNames={treeSelectClassNames}
styles={styles}
// >>> MISC
id={mergedId}
prefixCls={prefixCls}
Expand Down
151 changes: 151 additions & 0 deletions tests/Select.semantic.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React from 'react';
import { render } from '@testing-library/react';
import TreeSelect, { TreeNode } from '../src';

describe('TreeSelect.semantic', () => {
const createSingleSelect = (props = {}) => (
<TreeSelect {...props}>
<TreeNode value="0" title="Node 0" key="0">
<TreeNode value="0-0" title="Node 0-0" key="0-0" />
<TreeNode value="0-1" title="Node 0-1" key="0-1" />
</TreeNode>
<TreeNode value="1" title="Node 1" key="1" />
</TreeSelect>
);

const createMultipleSelect = (props = {}) => (
<TreeSelect multiple {...props}>
<TreeNode value="0" title="Node 0" key="0">
<TreeNode value="0-0" title="Node 0-0" key="0-0" />
<TreeNode value="0-1" title="Node 0-1" key="0-1" />
</TreeNode>
<TreeNode value="1" title="Node 1" key="1" />
</TreeSelect>
);

it('should support semantic classNames and styles in single mode', () => {
const classNames = {
prefix: 'custom-prefix',
suffix: 'custom-suffix',
input: 'custom-input',
clear: 'custom-clear',
placeholder: 'custom-placeholder',
content: 'custom-content',
};

const styles = {
prefix: { color: 'red' },
suffix: { color: 'blue' },
input: { backgroundColor: 'yellow' },
clear: { fontSize: '14px' },
placeholder: { fontStyle: 'italic' },
content: { fontWeight: 'bold' },
};

const { container } = render(
createSingleSelect({
value: '0',
prefix: <span>Prefix</span>,
suffix: <span>Suffix</span>,
allowClear: true,
placeholder: 'Please select',
classNames,
styles,
}),
);

// Test prefix
const prefixElement = container.querySelector(`.${classNames.prefix}`);
expect(prefixElement).toBeTruthy();
expect(prefixElement).toHaveStyle(styles.prefix);

// Test suffix
const suffixElement = container.querySelector(`.${classNames.suffix}`);
expect(suffixElement).toBeTruthy();
expect(suffixElement).toHaveStyle(styles.suffix);

// Test content
const contentElement = container.querySelector(`.${classNames.content}`);
expect(contentElement).toBeTruthy();
expect(contentElement).toHaveStyle(styles.content);

// Test clear
const clearElement = container.querySelector(`.${classNames.clear}`);
expect(clearElement).toBeTruthy();
expect(clearElement).toHaveStyle(styles.clear);
});

it('should support semantic classNames and styles in multiple mode', () => {
const classNames = {
prefix: 'custom-prefix',
suffix: 'custom-suffix',
content: 'custom-content',
clear: 'custom-clear',
item: 'custom-item',
itemContent: 'custom-item-content',
itemRemove: 'custom-item-remove',
};

const styles = {
prefix: { color: 'red' },
suffix: { color: 'blue' },
content: { fontWeight: 'bold' },
clear: { fontSize: '14px' },
item: { border: '1px solid green' },
itemContent: { padding: '4px' },
itemRemove: { color: 'orange' },
};

const { container } = render(
createMultipleSelect({
value: ['0', '1'],
prefix: <span>Prefix</span>,
suffix: <span>Suffix</span>,
allowClear: true,
classNames,
styles,
}),
);

// Test prefix
const prefixElement = container.querySelector(`.${classNames.prefix}`);
expect(prefixElement).toBeTruthy();
expect(prefixElement).toHaveStyle(styles.prefix);

// Test suffix
const suffixElement = container.querySelector(`.${classNames.suffix}`);
expect(suffixElement).toBeTruthy();
expect(suffixElement).toHaveStyle(styles.suffix);

// Test content
const contentElement = container.querySelector(`.${classNames.content}`);
expect(contentElement).toBeTruthy();
expect(contentElement).toHaveStyle(styles.content);

// Test clear
const clearElement = container.querySelector(`.${classNames.clear}`);
expect(clearElement).toBeTruthy();
expect(clearElement).toHaveStyle(styles.clear);

// Test items (multiple mode specific)
const items = container.querySelectorAll(`.${classNames.item}`);
expect(items.length).toBeGreaterThan(0);
items.forEach(item => {
expect(item).toHaveStyle(styles.item);
});

// Test item contents (multiple mode specific)
const itemContents = container.querySelectorAll(`.${classNames.itemContent}`);
expect(itemContents.length).toBeGreaterThan(0);
itemContents.forEach(content => {
expect(content).toHaveStyle(styles.itemContent);
});

// Test item remove buttons (multiple mode specific)
const removeButtons = container.querySelectorAll(`.${classNames.itemRemove}`);
expect(removeButtons.length).toBeGreaterThan(0);
removeButtons.forEach(button => {
expect(button).toHaveStyle(styles.itemRemove);
});
});
});
Comment on lines +1 to +151

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The addition of Select.semantic.spec.tsx provides valuable tests for ensuring the correct application of semantic class names and styles. The tests cover both single and multiple select modes, which is comprehensive. However, consider adding more test cases to cover edge cases and different scenarios, such as when certain class names or styles are not provided.