بنقرة واحدة
locator-replacer
替换占位定位符为真实选择器(六级优先级)。触发:替换定位符、locator、selector、定位失败、元素找不到、DOM 分析。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
替换占位定位符为真实选择器(六级优先级)。触发:替换定位符、locator、selector、定位失败、元素找不到、DOM 分析。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Incrementally add regression test points to an existing PageObject. Trigger: add test point, add regression point, add test point, increase coverage, extend page methods.
POM layering and context sharing decision tree. Trigger: architecture, layering, POM, Page Object, base class design, add new role.
Browser viewport / headless / timeout layered configuration. Trigger: viewport, browser config, navigation timeout, headless, slow_mo, incognito.
Under a shared page, a test case that leaves the start page must return via the UI and assert. Trigger: round-trip closure, case round trip, reset timeout, scope shared page.
AST knowledge graph: change review, exploration, debugging, refactoring. Trigger: knowledge graph, code review, impact analysis, blast radius, refactoring.
One-click generation of PageObject + matching tests. Trigger: new page, generate page, gen page, create page, add page object.
| name | locator-replacer |
| description | 替换占位定位符为真实选择器(六级优先级)。触发:替换定位符、locator、selector、定位失败、元素找不到、DOM 分析。 |
text= 占位定位符替换为真实选择器按优先级从高到低,逐级尝试,选中即停。优先使用页面上已有的语义化信息,避免依赖需要前端额外配合的属性:
# 通过 ARIA role + 可见文本定位
LOGIN_BTN = "role=button[name='登录']"
NAV_LINK = "role=link[name='<功能名>']"
SEARCH_INPUT = "role=textbox[name='搜索']"
# 精确匹配
FEATURE_BTN = "text=<功能名>"
# 包含匹配(文本可能嵌套在子元素中)
FEATURE_TAB = "text=<功能名>"
text= 是当前项目的占位方案,如果分析后发现 text= 已经足够稳定且元素唯一,可以保留并标记 # P1: text(已验证唯一)# placeholder 定位
EMAIL_INPUT = "[placeholder='请输入邮箱']"
# label 关联定位
PASSWORD_INPUT = "css=input[name='password']"
# type 属性
SUBMIT_BTN = "css=button[type='submit']"
name 属性通常由后端约定,相对稳定placeholder 跟随文案,稳定性中等# 业务语义类名 — 稳定
COURSE_CARD = "css=.list-card"
LOGIN_FORM = "css=#login-form"
NAV_MENU = "css=.main-navigation"
# ⚠️ 以下是哈希类名 — 绝对禁止使用
# BAD: "css=.sc-bdVaJa.bVjGWg" (styled-components 哈希)
# BAD: "css=.css-1a2b3c" (CSS Modules 哈希)
# BAD: "css=[class*='_component_']" (Vite CSS Modules)
哈希类名识别规则(必须跳过):
| 构建工具 | 哈希类名特征 | 示例 |
|---|---|---|
| styled-components | 随机字母组合 | .sc-bdVaJa, .bVjGWg |
| CSS Modules | 下划线 + 哈希 | .header_abc123, ._component_1x2y3 |
| Vite | 短哈希后缀 | .module_1a2b3c |
| Tailwind JIT | 动态工具类 | .[\31 /2], .[color:red] |
| Emotion | 前缀 css- | .css-1a2b3c |
可用的类名特征:
.list-card, .login-form, .nav-menu.header__title, .card--active.app-feature-list, .app-headerdata-testid 专用测试属性# Playwright locator 写法
SUBMIT_BTN = "[data-testid='submit-button']"
data-testid,可以直接使用,但不必强求前端为所有元素添加# ✅ 相对路径 — 从稳定祖先节点出发
SUBMIT_BTN = "xpath=//div[@class='login-form']//button[@type='submit']"
FIRST_COURSE = "css=.course-list > .course-item:first-child"
# ❌ 绝对路径 — 绝对禁止
# BAD: "xpath=/html/body/div[1]/div[2]/ul/li[3]/button"
XPath 编写规则:
/html/body 开始)div[3]),除非是列表且确实需要第 N 项使用 agent-browser 打开目标页面,获取交互元素信息(工具选型遵循 agent-behavior P0.4,agent-browser 未安装时降级到 Playwright MCP):
操作步骤:
1. browser_navigate → 访问目标页面(已认证状态)
2. browser_snapshot → 获取页面无障碍树(accessibility tree)
3. browser_evaluate → 执行 JS 提取元素属性:
- document.querySelectorAll('[data-testid]') → 已有 testid
- document.querySelectorAll('[role]') → ARIA role
- document.querySelectorAll('button, a, input') → 交互元素
对照页面对象中的每个占位定位符,按 P0→P5 逐级尝试,命中即停:
| 检查顺序 | 条件 | 使用 |
|---|---|---|
| P0 | 有 role + name | role=button[name='...'] |
| P1 | text= 唯一且稳定 | text=...(标记"已验证唯一") |
| P2 | 表单属性(placeholder/name/type) | [placeholder='...'] |
| P3 | 稳定 CSS class(非哈希) | css=.xxx |
| P4 | 有 data-testid | [data-testid='...'] |
| P5 | 以上均无 | 相对 XPath(≤3 层) |
class <PageName>(BasePage):
# 定位符 — 已替换为真实选择器(<日期>)
<PRIMARY_ACTION_BTN> = "role=button[name='<按钮文案>']" # P0: ARIA role
<SECONDARY_LINK> = "text=<链接文案>" # P1: text(已验证唯一)
PAGE_IDENTIFIER = "role=heading[name='<页面标题>']" # P0: ARIA role
更新规则:
# P0: ARIA role / # P1: text / ... / # P4: testid / # P5: XPath)text= 经验证确实稳定且唯一,注释标记 # P1: text(已验证唯一)# 定位符 — 后续替换为实际选择器 注释# 定位符 — 已替换为真实选择器(日期)# 在对应角色的回归文件中跑指定用例(运行前向用户确认 --env,见 agent-behavior P0.2)
pytest tests/<role>/test_<role>_flow.py --env=<pre|prod> -v -k "test_<story_name>"
更新 docs/regression-points.md 中对应 PageObject 的"关键定位符"段。
替换完成后,逐项确认:
/html/body/...)sc-xxx, css-xxx, _module_xxx)div[3],除非列表取第 N 项)# P0 ~ # P5)text= 不唯一降级到 P3/P5,用父容器 + 文本组合:css=.list-card:first-child >> text=查看详情
向前端团队提出添加 data-testid(P4)需求,附元素清单;临时用 P5 相对 XPath 过渡。
检查是否使用了哈希类名(违反 P3)→ 优先升级到 P0/P1(不受构建影响)→ 文案变更则对照新文案更新。