Skip to content

Conversation

@zombieJ
Copy link
Member

@zombieJ zombieJ commented Oct 22, 2025

Summary by CodeRabbit

发布说明

  • 新功能

    • 扩展了样式自定义语义钩子,新增占位符、内容、项、项内容与项移除等可定制样式点。
  • 依赖更新

    • 更新了 @rc-component/select 版本。
  • 测试

    • 将测试由旧的查询方式迁移为基于 DOM 的测试工具与辅助函数,新增测试工具与 MessageChannel 测试模拟,提升测试稳定性。

@vercel
Copy link

vercel bot commented Oct 22, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
cascader Error Error Oct 22, 2025 3:22am

@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

更新依赖 @rc-component/select 版本,扩展 Cascader 的语义命名(新增 placeholder、content、item、itemContent、itemRemove),并将测试套件从 Enzyme 迁移到 React Testing Library,新增测试工具与 MessageChannel 测试 mock。

Changes

群组 / 文件 变更总结
依赖更新
package.json
@rc-component/select~1.2.0-alpha.2 升级至 ~1.2.0-alpha.3
语义命名扩展
src/Cascader.tsx
扩展 SemanticName 类型,新增 placeholdercontentitemitemContentitemRemove;更新 CascaderPropsstylesclassNames 支持这些键,渲染时直接透传 classNames/styles
测试工具
tests/util.ts
新增 expectOpen(dom, open?)selectOption(container, menuIndex, optionIndex, eventType?) 两个测试辅助函数
测试环境配置
tests/setup.js
添加 window.MessageChannel 的 mock 实现(互联的两个 port,异步 postMessage)
测试套件迁移
tests/*.spec.tsx
tests/fieldNames.spec.tsx, tests/index.spec.tsx, tests/search.spec.tsx, tests/selector.spec.tsx, tests/semantic.spec.tsx
将测试由 Enzyme 改为 React Testing Library(render/fireEvent/act),更新 DOM 选择器、交互和断言;语义测试扩展以覆盖 placeholder、content、item、itemContent、itemRemove 等元素

Sequence Diagram(s)

(本次变更主要为类型扩展、依赖升级与测试迁移,不涉及运行时控制流变更,故无序列图。)

Estimated code review effort

🎯 3 (中等) | ⏱️ ~25 分钟

Possibly related PRs

Suggested reviewers

  • afc163

诗歌

🐰 新语义五小簇,
占位内容项相连,
测试酶体化为羽,
信道通达消息传,
级联轻跃入新天。

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive PR标题"chore: by pass rc-select semantic structure"涉及真实的变更内容,即扩展Cascader组件的语义化支持。然而,标题措辞不清晰,"by pass"一词在中文语境中可能被理解为"绕过"或"传递",存在歧义。标题未能明确传达主要变更内容:扩展SemanticName类型以支持更多语义元素(placeholder、content、item等),以及更新测试框架从Enzyme迁移到React Testing Library。虽然涉及真实变更,但表述过于模糊,无法让扫一眼历史的开发者快速理解核心改动。 建议改进标题为更具体的表述,例如"chore: extend semantic support in Cascader for additional elements"或"chore: support semantic customization for placeholder, content and item elements",这样能更清晰地表达变更的本质,即扩展而非绕过语义结构。
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-test

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c80a9b and 570e0a8.

📒 Files selected for processing (1)
  • src/Cascader.tsx (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test / react component workflow
  • GitHub Check: Analyze (javascript)
  • GitHub Check: test / react component workflow
🔇 Additional comments (2)
src/Cascader.tsx (2)

462-463: 代码改动正确,支持新的语义定制能力

直接传递 classNamesstylesBaseSelect 是合理的做法,这样可以让 BaseSelect 组件处理所有语义键(包括新增的 placeholdercontentitemitemContentitemRemove),实现更细粒度的样式定制。


155-163: 验证 BaseSelect 对新增语义键的支持

代码中已正确定义并传递了新增的语义键(placeholdercontentitemitemContentitemRemove)至 BaseSelect。但鉴于 @rc-component/select@1.2.0-alpha.3 为 alpha 版本,请确认该版本的 BaseSelect 确实支持这些语义键,以避免运行时配置被忽略。建议查阅库的发行说明或源代码以确保兼容性。


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @zombieJ, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on enhancing the Cascader component by exposing more detailed control over its internal semantic structure, allowing for finer-grained styling and class customization. Concurrently, it includes a substantial refactoring of the component's test suite, migrating tests from Enzyme to React Testing Library. This modernization effort aims to improve the reliability and maintainability of the tests, ensuring the component's stability and future extensibility.

Highlights

  • Semantic Structure Enhancement: The Cascader component now provides more granular control over its internal semantic elements, such as placeholder, content, item, itemContent, and itemRemove, through new classNames and styles props. This allows for finer-grained styling and class customization.
  • Testing Framework Migration: A significant portion of the test suite has been refactored from Enzyme to React Testing Library. This includes updating test interactions, assertions, and introducing new utility functions (expectOpen, selectOption) to improve test robustness and maintainability.
  • Dependency Update: The @rc-component/select dependency has been updated to version ~1.2.0-alpha.3.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@socket-security
Copy link

socket-security bot commented Oct 22, 2025

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
safer-buffer@2.1.2 has Obfuscated code.

Confidence: 0.94

Location: Package overview

From: ?npm/@rc-component/np@1.0.4npm/safer-buffer@2.1.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/safer-buffer@2.1.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces semantic class names and styles for the Cascader component, enhancing its customizability. It also updates the rc-select dependency and includes corresponding test updates. The review focuses on ensuring the correctness and completeness of the new semantic elements and the accuracy of the updated tests.

optionRender={option => `${option.label} - test`}
/>,
);
const input = container.querySelector('.rc-cascader-selection-search-input');
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The query selector is using .rc-cascader-selection-search-input which is a class name that was removed. This test will fail. Please update the query selector to use the correct class name.

    const input = container.querySelector('.rc-cascader-input');
Suggested change
const input = container.querySelector('.rc-cascader-selection-search-input');
const input = container.querySelector('.rc-cascader-input');


// Click
fireEvent.click(document.querySelector('.rc-cascader-menu-item-content') as HTMLElement);
expect(document.querySelector('.rc-cascader-dropdown-hidden')).toBeTruthy();
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The query selector is using .rc-cascader-dropdown-hidden which is a class name that was removed. This test will fail. Please update the query selector to use the correct class name.

Consider using the expectOpen utility function that was added to keep the tests consistent.

<Cascader value={['not', 'exist']} allowClear onChange={onChange} />,
);

fireEvent.mouseDown(container.querySelector('.rc-cascader-clear-icon') as HTMLElement);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The query selector is using .rc-cascader-clear-icon which is a class name that was removed. This test will fail. Please update the query selector to use the correct class name.

      fireEvent.mouseDown(container.querySelector('.rc-cascader-clear') as HTMLElement);
Suggested change
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear-icon') as HTMLElement);
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear') as HTMLElement);

);

// Open and select
fireEvent.mouseDown(container.querySelector('.rc-cascader-selector') as HTMLElement);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The query selector is using .rc-cascader-selector which is a class name that was removed. This test will fail. Please update the query selector to use the correct class name.

      fireEvent.mouseDown(container.querySelector('.rc-cascader') as HTMLElement);
Suggested change
fireEvent.mouseDown(container.querySelector('.rc-cascader-selector') as HTMLElement);
fireEvent.mouseDown(container.querySelector('.rc-cascader') as HTMLElement);

<Cascader checkable value={[['not'], ['exist']]} allowClear onChange={onChange} />,
);

wrapper.find('.rc-cascader-selection-item-remove-icon').first().simulate('click');
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The query selector is using .rc-cascader-selection-item-remove-icon which is a class name that was removed. This test will fail. Please update the query selector to use the correct class name.

    wrapper.find('.rc-cascader-selection-item-remove').first().simulate('click');
Suggested change
wrapper.find('.rc-cascader-selection-item-remove-icon').first().simulate('click');
wrapper.find('.rc-cascader-selection-item-remove').first().simulate('click');

Comment on lines +155 to +163
type SemanticName =
| 'input'
| 'prefix'
| 'suffix'
| 'placeholder'
| 'content'
| 'item'
| 'itemContent'
| 'itemRemove';
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The SemanticName type definition has been expanded to include new semantic names. Ensure that all these names are consistently used throughout the component and that they cover all customizable elements. Also, consider adding documentation or comments to explain the purpose of each semantic name.

Missing documentation can lead to confusion and inconsistent usage.

src/Cascader.tsx Outdated
Comment on lines 472 to 481
styles={{
prefix: styles?.prefix,
suffix: styles?.suffix,
input: styles?.input,
placeholder: styles?.placeholder,
content: styles?.content,
item: styles?.item,
itemContent: styles?.itemContent,
itemRemove: styles?.itemRemove,
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the classNames prop, the styles prop is being used to apply semantic styles. Ensure that all the new semantic styles (placeholder, content, item, itemContent, itemRemove) are actually applied to the corresponding elements in the component's JSX.

Unused styles can lead to dead code and confusion.

import { fireEvent, render } from '@testing-library/react';
import { act, fireEvent, render } from '@testing-library/react';
import KeyCode from '@rc-component/util/lib/KeyCode';
import { expectOpen, selectOption } from './util';
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Adding a new utility function expectOpen and selectOption from ./util.ts. Ensure that these utility functions are well-documented and tested to avoid regressions.

@codecov
Copy link

codecov bot commented Oct 22, 2025

Codecov Report

❌ Patch coverage is 90.47619% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.52%. Comparing base (eeb39e5) to head (570e0a8).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
tests/util.ts 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #630      +/-   ##
==========================================
- Coverage   99.83%   99.52%   -0.31%     
==========================================
  Files          23       24       +1     
  Lines         614      635      +21     
  Branches      186      183       -3     
==========================================
+ Hits          613      632      +19     
- Misses          1        3       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/util.ts (1)

3-12: 考虑减少定时器推进时间。

jest.advanceTimersByTime(100000) 推进了 100 秒,这个值似乎过大。除非有特定原因(如某些动画或延迟需要这么长时间),建议评估是否可以使用更小的值(如 1000-5000ms)来提高测试执行效率。

tests/index.spec.tsx (1)

99-654: 建议考虑完成测试迁移或添加说明。

当前文件中混合使用 Enzyme 和 React Testing Library 两种测试方法。虽然部分迁移可能是有意为之(如 PR 标题所示,针对特定的 rc-select 语义结构问题),但这会降低代码的可维护性:

  • 开发者需要同时理解两个测试库
  • 新增测试时可能不清楚应使用哪种方法
  • 代码审查时需要关注两种不同的模式

建议考虑以下选项之一:

  1. 完成迁移:将剩余的 Enzyme 测试迁移到 RTL,保持测试方法的一致性
  2. 添加文档说明:在文件顶部添加注释,说明为什么采用混合方法,以及何时使用哪种测试方法

如需帮助完成迁移,我可以协助生成迁移代码。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 44ac86b and 5c80a9b.

⛔ Files ignored due to path filters (1)
  • tests/__snapshots__/search.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (9)
  • package.json (1 hunks)
  • src/Cascader.tsx (2 hunks)
  • tests/fieldNames.spec.tsx (3 hunks)
  • tests/index.spec.tsx (10 hunks)
  • tests/search.spec.tsx (6 hunks)
  • tests/selector.spec.tsx (4 hunks)
  • tests/semantic.spec.tsx (3 hunks)
  • tests/setup.js (1 hunks)
  • tests/util.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
tests/util.ts (1)
tests/setup.js (1)
  • menu (17-17)
tests/selector.spec.tsx (1)
tests/util.ts (1)
  • expectOpen (3-12)
tests/search.spec.tsx (1)
tests/util.ts (1)
  • expectOpen (3-12)
tests/index.spec.tsx (2)
tests/demoOptions.ts (1)
  • addressOptions (38-99)
tests/util.ts (2)
  • expectOpen (3-12)
  • selectOption (14-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test / react component workflow
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (25)
tests/setup.js (1)

31-55: LGTM!

MessageChannel mock 实现正确,通过 _target 属性实现了双向端口通信,并使用 setTimeout 模拟异步消息传递。这为测试环境提供了合适的 postMessage 通信模拟。

tests/fieldNames.spec.tsx (2)

42-42: LGTM!

更新打开 cascader 的触发元素选择器,从 .rc-cascader-selector 改为 .rc-cascader,与新的语义结构保持一致。


79-79: LGTM!

更新断言选择器从 .rc-cascader-selection-item 改为 .rc-cascader-content-value,正确反映了新的 DOM 结构。

Also applies to: 100-100

tests/util.ts (1)

14-34: LGTM!

selectOption 函数实现良好:

  • 提供了清晰的错误消息来帮助调试
  • 支持多种事件类型(click、doubleClick、mouseEnter)
  • 使用标准的 DOM 查询方法
tests/selector.spec.tsx (3)

27-27: LGTM!

更新清除操作的选择器从 .rc-cascader-clear-icon 改为 .rc-cascader-clear,与新的语义结构一致。

Also applies to: 53-53, 63-63


45-46: LGTM!

正确更新为使用新的 .rc-cascader 选择器和 expectOpen 工具函数来验证打开状态,这与测试套件的现代化改造相符。

Also applies to: 50-50


74-74: LGTM!

更新移除操作的选择器从 .rc-cascader-selection-item-remove-icon 改为 .rc-cascader-selection-item-remove,与新的语义结构保持一致。

tests/semantic.spec.tsx (2)

12-13: LGTM!

为新的语义键(placeholder、content)添加了完整的测试覆盖,包括样式和类名验证。代码包含了适当的空值检查(针对可选的 placeholder 元素)。

Also applies to: 23-24, 42-71


73-156: LGTM!

为多选模式添加了全面的语义测试,覆盖了所有新增的语义键(item、itemContent、itemRemove)。测试结构清晰,验证了样式和类名的正确应用。

tests/search.spec.tsx (4)

49-55: LGTM!

添加了假定时器的设置和清理,这对于测试异步行为和动画是必要的。使用 beforeEachafterEach 确保了每个测试的隔离性。


285-296: LGTM!

将测试从 Enzyme 迁移到 React Testing Library,使用 fireEventcontainer.querySelector 进行 DOM 交互,并使用 expectOpen 工具函数验证下拉框状态。这与测试套件的现代化方向一致。


366-389: LGTM!

成功将此测试用例迁移到 React Testing Library 模式:

  • 使用 fireEvent.change 代替 Enzyme 的 simulate
  • 使用 querySelectorAlltextContent 进行断言
  • 与其他已迁移的测试保持一致

391-412: LGTM!

这些测试用例正确地使用了 React Testing Library 的模式:

  • 使用 toHaveValue matcher 进行输入值断言
  • 通过 querySelector 获取 DOM 元素
  • 与新的测试工具集成良好

Also applies to: 414-440

src/Cascader.tsx (2)

155-163: LGTM!

正确扩展了 SemanticName 类型以包含新的语义键:placeholdercontentitemitemContentitemRemove。这些新增项为组件提供了更细粒度的样式定制能力。


466-470: LGTM!

新的语义键被正确地传递给 BaseSelect 组件,使得自定义样式和类名能够应用到相应的 DOM 元素上。实现与类型定义保持一致。

Also applies to: 476-480

package.json (1)

46-46: 依赖版本验证完成,无需更改。

根据验证结果:

  • @rc-component/select 版本 1.2.0-alpha.3 存在于 npm 上
  • ✓ 该包没有已知的安全漏洞

该依赖版本的选择是有效且安全的。

tests/index.spec.tsx (9)

8-10: 导入语句正确!

新增的 React Testing Library 导入和测试工具函数导入正确,支持从 Enzyme 到 RTL 的迁移。


30-48: RTL 迁移实现正确!

测试已成功从 Enzyme 迁移到 React Testing Library,使用完整的事件序列(mouseDown → mouseUp → click)来准确模拟点击交互,并通过 expectOpen 工具函数验证面板状态。


50-97: 选项选择测试迁移正确!

测试正确使用了 selectOption 工具函数和原生 DOM 查询方法,替换了 Enzyme 的 wrapper 方法。活动状态验证使用 classList.contains 是合适的。


170-226: 悬停触发测试迁移正确!

测试正确使用 selectOptionmouseEnter 事件类型,并在 act() 中包装 jest.runAllTimers() 以确保在断言前刷新定时器触发的状态更新。这是处理异步行为的最佳实践。


228-270: 状态重置测试迁移正确!

两个测试(清除活动选择和恢复默认值)已正确迁移到 RTL,一致使用 fireEvent.clickselectOptionexpectOpen 工具函数。


272-327: 受控组件测试迁移正确!

测试正确验证了 changeOnSelect 和受控组件行为,RTL 迁移实现准确。


483-499: 悬停触发与 changeOnSelect 组合测试迁移正确!

测试正确验证了当 expandTrigger="hover"changeOnSelect 启用时,点击仍会触发 onChange 的行为。


541-553: 双击关闭弹窗测试迁移正确!

测试正确使用 selectOptiondoubleClick 事件类型,验证在 changeOnSelect 模式下双击关闭弹窗的行为。


1162-1186: ARIA 和 data 属性增强了可访问性!

添加 aria-labelaria-labelledbydata-type 属性是提升组件可访问性的良好实践。类型注解的引号风格变更也与 JavaScript 约定保持一致。

@zombieJ zombieJ merged commit 9bff633 into master Oct 22, 2025
8 of 12 checks passed
@zombieJ zombieJ deleted the fix-test branch October 22, 2025 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants