diff --git a/docs/development/ui-testids-CN.md b/docs/development/ui-testids-CN.md index ab6058e286..7db672b04a 100644 --- a/docs/development/ui-testids-CN.md +++ b/docs/development/ui-testids-CN.md @@ -188,7 +188,7 @@ | Chat 模型选择按钮 | `chat-model-selector-btn` | 打开当前会话的模型选择器。 | | Chat 模型选择菜单 | `chat-model-selector-menu` | 模型选择下拉菜单根节点。 | -| Chat 模型选择项 | `chat-model-selector-option` | 重复项。配合 `data-model-id`、`data-model-name` 和 `data-selected` 使用。 | +| Chat 模型选择项 | `chat-model-selector-option` | 重复项。配合 `data-option-kind`、`data-model-role`、`data-model-id`、`data-model-name`、`data-provider-id` 和 `data-selected` 使用。别名入口会继续保留 `data-model-id="auto" / "primary" / "fast"`;其中 `primary-alias` 和 `fast-alias` 还会额外提供 `data-resolved-model-id`、`data-resolved-model-name` 和 `data-resolved-provider-id`。 | | Chat 用户消息 | `chat-user-message` | 重复的用户消息。配合 `data-turn-id`、`data-status` 和 `data-failed` 使用。 | | Chat 用户消息内容 | `chat-user-message-content` | 用户消息文本内容。配合 `data-turn-id` 使用。 | | Chat assistant 消息 | `chat-assistant-message` | 重复的模型轮次容器。配合 `data-turn-id`、`data-round-id`、`data-status`、`data-model-id`、`data-model-alias` 和 `data-streaming` 使用。 | @@ -241,16 +241,21 @@ | 模型请求格式选择器 | `settings-model-request-format-select` | 请求格式选择器,例如 OpenAI-compatible 或 Anthropic。 | | 模型选择按钮 | `settings-model-select-btn` | 打开模型选择下拉框。 | | 模型选择菜单 | `settings-model-select-menu` | 模型选择下拉框根节点。 | -| 模型选择项 | `settings-model-option` | 重复的下拉项。配合 `data-model-id`、`data-model-name` 和 `data-selected` 使用。 | +| 模型选择项 | `settings-model-option` | 重复的下拉项。配合 `data-option-kind="model"`、`data-model-role="normal"`、`data-model-state="selectable"`、`data-model-source`、`data-model-id`、`data-model-name`、`data-provider-id` 和 `data-selected` 使用。 | | 手动模型名称输入框 | `settings-model-manual-name-input` | 手动/自定义模型名称输入字段。 | | 添加自定义模型按钮 | `settings-model-add-custom-btn` | 将手动模型名称加入已选模型列表。 | | 已选模型列表 | `settings-model-selected-list` | 已选模型草稿列表。包含 `data-selected-count`。 | | 已选模型空状态 | `settings-model-selected-list-empty` | 已选模型草稿为空时的状态。包含 `data-selected-count="0"`。 | -| 已选模型行 | `settings-model-selected-row` | 重复的已选模型草稿。配合 `data-model-id`、`data-model-name`、`data-selected` 和 `data-expanded` 使用。 | -| 已选模型移除按钮 | `settings-model-selected-remove-btn` | 移除已选模型草稿。配合 `data-model-id` 和 `data-model-name` 使用。 | +| 已选模型行 | `settings-model-selected-row` | 重复的已选模型草稿。配合 `data-option-kind="selected-draft"`、`data-model-role="normal"`、`data-model-state="draft"`、`data-model-id`、`data-model-name`、`data-provider-id`、`data-config-id`、`data-selected` 和 `data-expanded` 使用。 | +| 已选模型移除按钮 | `settings-model-selected-remove-btn` | 移除已选模型草稿。配合 `data-option-kind="selected-draft"`、`data-model-role="normal"`、`data-model-state="draft"`、`data-model-id`、`data-model-name`、`data-provider-id` 和 `data-config-id` 使用。 | | 模型保存按钮 | `settings-model-save-btn` | 保存模型提供商/模型配置表单。 | -| 模型行 | `settings-model-row` | 重复的已保存模型行。配合 `data-model-id`、`data-model-name` 和 `data-config-id` 使用。 | -| 模型测试状态 | `settings-model-test-status` | 重复的已保存模型测试状态。配合 `data-model-id`、`data-model-name`、`data-config-id` 和 `data-status` 使用,`data-status` 可为 `success` 或 `error`。 | +| 模型行 | `settings-model-row` | 重复的已保存模型行。配合 `data-option-kind="saved-model"`、`data-model-role="normal"`、`data-model-state="saved"`、`data-model-id`、`data-model-name`、`data-provider-id` 和 `data-config-id` 使用。 | +| 模型测试状态 | `settings-model-test-status` | 重复的已保存模型测试状态。配合 `data-option-kind="saved-model-status"`、`data-model-role="normal"`、`data-model-state="saved"`、`data-model-id`、`data-model-name`、`data-provider-id`、`data-config-id` 和 `data-status` 使用,`data-status` 可为 `success` 或 `error`。 | + +模型定位建议: +- 在聊天页里,优先使用 `data-option-kind` 和 `data-model-role` 区分 `auto`、`primary-alias`、`fast-alias`、`acp-model` 与真实 `model`,不要只靠展示文案或 `data-model-name`。 +- `data-model-name` 更适合作为展示元数据,不应单独当作唯一键。需要唯一定位时,应与 `data-model-id`、`data-provider-id`,或别名入口专用的 `data-resolved-model-id` 组合使用。 +- 在设置页里,先用 `data-model-state` 区分“下拉可选项 / 草稿已选项 / 已保存项 / 已保存测试状态”,再按 `data-model-id` 或 `data-provider-id` 进一步过滤。 ## Settings Appearance diff --git a/docs/development/ui-testids.md b/docs/development/ui-testids.md index 5adc253b02..b91d754832 100644 --- a/docs/development/ui-testids.md +++ b/docs/development/ui-testids.md @@ -187,7 +187,7 @@ Avoid adding IDs to these surfaces unless there is a clear automated workflow. | Chat input start BTW button | `chat-input-boost-start-btw` | Starts the BTW flow when present. | | Chat model selector button | `chat-model-selector-btn` | Opens the session model selector. | | Chat model selector menu | `chat-model-selector-menu` | Model selector dropdown root. | -| Chat model selector option | `chat-model-selector-option` | Repeated item. Pair with `data-model-id`, `data-model-name`, and `data-selected`. | +| Chat model selector option | `chat-model-selector-option` | Repeated item. Pair with `data-option-kind`, `data-model-role`, `data-model-id`, `data-model-name`, `data-provider-id`, and `data-selected`. Alias entries keep `data-model-id` as `auto` / `primary` / `fast`; `primary-alias` and `fast-alias` also expose `data-resolved-model-id`, `data-resolved-model-name`, and `data-resolved-provider-id`. | | Chat user message | `chat-user-message` | Repeated user message. Pair with `data-turn-id`, `data-status`, and `data-failed`. | | Chat user message content | `chat-user-message-content` | User message text content. Pair with `data-turn-id`. | | Chat assistant message | `chat-assistant-message` | Repeated model round container. Pair with `data-turn-id`, `data-round-id`, `data-status`, `data-model-id`, `data-model-alias`, and `data-streaming`. | @@ -241,16 +241,21 @@ Avoid adding IDs to these surfaces unless there is a clear automated workflow. | Model request format select | `settings-model-request-format-select` | Request format selector, for example OpenAI-compatible vs Anthropic. | | Model select button | `settings-model-select-btn` | Opens the model selection dropdown. | | Model selection menu | `settings-model-select-menu` | Model selection dropdown root. | -| Model selection option | `settings-model-option` | Repeated dropdown item. Pair with `data-model-id`, `data-model-name`, and `data-selected`. | +| Model selection option | `settings-model-option` | Repeated dropdown item. Pair with `data-option-kind="model"`, `data-model-role="normal"`, `data-model-state="selectable"`, `data-model-source`, `data-model-id`, `data-model-name`, `data-provider-id`, and `data-selected`. | | Manual model name input | `settings-model-manual-name-input` | Manual/custom model name entry field. | | Add custom model button | `settings-model-add-custom-btn` | Adds the manual model name into the selected model list. | | Selected model list | `settings-model-selected-list` | Selected model draft list. Includes `data-selected-count`. | | Selected model empty state | `settings-model-selected-list-empty` | Empty selected model draft state. Includes `data-selected-count="0"`. | -| Selected model row | `settings-model-selected-row` | Repeated selected model draft. Pair with `data-model-id`, `data-model-name`, `data-selected`, and `data-expanded`. | -| Selected model remove button | `settings-model-selected-remove-btn` | Removes a selected model draft. Pair with `data-model-id` and `data-model-name`. | +| Selected model row | `settings-model-selected-row` | Repeated selected model draft. Pair with `data-option-kind="selected-draft"`, `data-model-role="normal"`, `data-model-state="draft"`, `data-model-id`, `data-model-name`, `data-provider-id`, `data-config-id`, `data-selected`, and `data-expanded`. | +| Selected model remove button | `settings-model-selected-remove-btn` | Removes a selected model draft. Pair with `data-option-kind="selected-draft"`, `data-model-role="normal"`, `data-model-state="draft"`, `data-model-id`, `data-model-name`, `data-provider-id`, and `data-config-id`. | | Model save button | `settings-model-save-btn` | Saves the model provider/configuration form. | -| Model row | `settings-model-row` | Repeated saved model row. Pair with `data-model-id`, `data-model-name`, and `data-config-id`. | -| Model test status | `settings-model-test-status` | Repeated saved model test status. Pair with `data-model-id`, `data-model-name`, `data-config-id`, and `data-status` (`success` or `error`). | +| Model row | `settings-model-row` | Repeated saved model row. Pair with `data-option-kind="saved-model"`, `data-model-role="normal"`, `data-model-state="saved"`, `data-model-id`, `data-model-name`, `data-provider-id`, and `data-config-id`. | +| Model test status | `settings-model-test-status` | Repeated saved model test status. Pair with `data-option-kind="saved-model-status"`, `data-model-role="normal"`, `data-model-state="saved"`, `data-model-id`, `data-model-name`, `data-provider-id`, `data-config-id`, and `data-status` (`success` or `error`). | + +Model locator guidance: +- Prefer `data-option-kind` plus `data-model-role` to distinguish alias entries from real model entries. Use `auto`, `primary-alias`, `fast-alias`, `acp-model`, and `model` in chat instead of matching by visible text. +- Treat `data-model-name` as display metadata, not as a unique key by itself. For unique targeting, combine it with `data-model-id`, `data-provider-id`, or the alias-only `data-resolved-model-id`. +- In settings flows, use `data-model-state` to separate selectable dropdown options, selected drafts, saved configs, and saved test-status nodes before filtering by model id or provider. ## Settings Appearance diff --git a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx index 842dc3ad04..0cfa183d1c 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx @@ -1166,6 +1166,8 @@ const SessionsSection: React.FC = ({ ref={openMenuSessionId === session.sessionId ? sessionMenuAnchorRef : undefined} className={`bitfun-nav-panel__inline-item-action-btn${openMenuSessionId === session.sessionId ? ' is-open' : ''}`} onClick={e => handleMenuOpen(e, session.sessionId)} + data-testid="nav-session-menu-btn" + data-session-id={session.sessionId} > @@ -1176,11 +1178,14 @@ const SessionsSection: React.FC = ({ className="bitfun-nav-panel__inline-item-menu-popover" role="menu" style={{ top: `${sessionMenuPosition.top}px`, left: `${sessionMenuPosition.left}px` }} + data-testid="nav-session-menu" + data-session-id={session.sessionId} > @@ -192,7 +196,7 @@ const SkillsScene: React.FC = () => {
{activeTab === 'installed' && ( -
+