@civitas-cerebrum/element-repository

中文文档
0.3.4发布于 2026/11/01MITTypeScriptCommonJS零依赖构建来源已验证近 30 天下载 3198

一个轻量级,强壮的软件包 将你的UI选择器从测试代码中解开 通过将定位器外部化成一个中央的JSON寄存器,使你的测试自动化框架更清洁,更方便维护,并方便非开发者访问.

中文使用文档
文档目录18 节
  1. * 安装
  2. - 这有什么用?
  3. 包件合同
  4. QQ 配置
  5. 多平台配置
  6. 支持选择键
  7. 选择器后退链
  8. 条目标记 : provisional 财务报告和审定财务报表 list
  9. 使用量
  10. 初始化
  11. 获取元素
  12. 流利的动作链
  13. API 参考
  14. 元素仓库
  15. 元素接口
  16. QQ 类型安全
  17. · 突破变化(v.1.0)
  18. 许可证

元素仓库

NPM Version

一个轻量级,强壮的软件包 将你的UI选择器从测试代码中解开 通过将定位器外部化成一个中央的JSON寄存器,使你的测试自动化框架更清洁,更方便维护,并方便非开发者访问. 支持两者 剧作家 (网络) 财务报告和审定财务报表 Appium/WebriverIO(移动) 通过统一的API.

* 安装

npm i @civitas-cerebrum/element-repository

同伴依赖关系 : 用于网络测试, 安装 @playwright/test 或者说 playwright。用于移动/平台测试,安装 webdriverio。 。 。 .

- 这有什么用?

  • 0 硬码选择器 : 将您的页面对象和步骤定义完全排除复杂的 DOM 查询.
  • 平台不可知元素 API: 一个统一的 Element 与交互、状态、取出、查询和等待方法进行接口,这些方法在Playwright和WebDriverIO之间同样有效.
  • 流利的动作链 : 对元素的多动作进行排序 element.action().waitForState('visible').click()。 。 。 .
  • 动态解析 : 自动将您的 JSON 配置转换为平台内置选择器 .
  • 智能定位器 : 阵列的内置方法,随机元素选择,文本过滤,属性过滤,和能见度检查.

包件合同

此软件包拥有 元素获取 + 只有原始操作任何带有重试、倒置、选项驱动的变体、组成、匹配树或断言框架的都属于消费者包.

住在这里的是什么:

  • 从 JSON 仓库中查找元素
  • 这个 Element 界面及其两个后端(WebElement 为剧作家, PlatformElement 用于Appium)
  • ElementChain 一个流畅的动作测序器 Element 原始人
  • 紧紧的一通电话包装 Locator / WebdriverIO 元素(单击、填充、盘旋、检查、滚动IntoView等)

消费者的生活:

  • 校验 DSL 、 断言错误格式化、 重试相匹配语义
  • 指向截取自动反射 并击出回击, { withoutScrolling, ifPresent } 修改
  • 所列要素构成(文本/regex/带有Descendant过滤)
  • 火柴树steps.expect(...).text.toBe(...)),可见的Chan,步骤 API 外观

拇指规则——按执行分类,不是按名称分类. 其躯体为单一被包裹的原始呼号的方法是原始的并停留在这里(即使听起来是可验证的-y——例如, ElementChain.isPresent() 刚刚 element.isVisible() 在队列执行后). 一种重述、作曲或格式断言错误的方法是明智的,并会移动到消费者身上.

见 @civitas-cerebrum/element-interactions (网络)和 @civitas-cerebrum/singularity-engine (网络+移动+桌面)用于智能层.

QQ 配置

在您的工程中创建 JSON 文件以持有您的选择器 :

locators.json

{
  "pages": [
    {
      "name": "HomePage",
      "elements": [
        {
          "elementName": "search-input",
          "selector": { "css": "input[name='search']" }
        },
        {
          "elementName": "submit-button",
          "selector": { "id": "btn-submit" }
        }
      ]
    },
    {
      "name": "ProductList",
      "elements": [
        {
          "elementName": "product-cards",
          "selector": { "xpath": "//article[@class='product']" }
        }
      ]
    }
  ]
}

多平台配置

使用 platform 字段来定义同一页面的平台特定选择器。 无页 platform 字段默认为 web。 。 。 .

{
  "pages": [
    {
      "name": "LoginPage",
      "platform": "web",
      "elements": [
        { "elementName": "submitButton", "selector": { "css": "button.web-submit" } }
      ]
    },
    {
      "name": "LoginPage",
      "platform": "android",
      "elements": [
        { "elementName": "submitButton", "selector": { "accessibility id": "SubmitBtn" } }
      ]
    },
    {
      "name": "LoginPage",
      "platform": "ios",
      "elements": [
        { "elementName": "submitButton", "selector": { "predicate": "label == \"Submit\"" } }
      ]
    }
  ]
}

支持选择键

这个 platform 每个页面对象的字段决定使用哪种选择器格式。 若为 platform ,默认为 web。 。 。 .

网络( Playwright)

密钥决定:示例
csscss=<value>"css": "button.primary"
xpathxpath=<value>"xpath": "//button[@id='submit']"
id#<value>"id": "btn-submit"
texttext=<value>"text": "Submit"
testid[data-testid='<value>']"testid": "login-btn"
role[role='<value>']"role": "button"
placeholder[placeholder='<value>']"placeholder": "Search..."
label[aria-label='<value>']"label": "Close"

非网络/ 移动( Appium)

密钥骆驼类别名决定:示例
accessibility idaccessibilityId~<value>"accessibility id": "LoginBtn"
xpath—— 说<value> (拉动)"xpath": "//android.widget.Button"
id—— 说#<value>"id": "submit-btn"
uiautomatorandroidUIAutomatorandroid=<value>"uiautomator": "new UiSelector().text(\"Go\")"
predicateiOSNsPredicateString-ios predicate string:<value>"predicate": "label == \"Login\""
class chainiOSClassChain-ios class chain:<value>"class chain": "**/XCUIElementTypeButton"
class nameclassName<value> (拉动)"class name": "android.widget.EditText"

所有包含空格的策略密钥也接受驼峰Case的别名(例如, "accessibilityId" 改为 "accessibility id") (中文(简体) ).

选择器后退链

添加一个嵌入 fallback 选择器处理DOM变体(每个国家,每个品牌,每个渲染器)而无需重复回波条目. 当主线在短时间( 100 ms) 内匹配零元素时, 分辨率会进入 fallback ——递归.

{
  "elementName": "loginButton",
  "selector": {
    "css": "[data-qa='login-button']",
    "fallback": {
      "role": "button",
      "name": { "regex": "Log in|Iniciar sesión|Anmelden|Inloggen", "flags": "i" }
    }
  }
}

规则:

  • 初始附属于雷波 defaultTimeout (15s default) ~ 倒置从未被咨询. waitFor 解决元素出现的时刻,所以普通案件不支付超时费用.
  • 小学不附加于 defaultTimeout 走进去 selector.fallback。 。 。 .
  • 无条目 fallback 键键完全跳过探测器——懒惰定位器像以前一样使用元素交互的动作-时间超时(30-60s).
  • 链为递归: fallback.fallback.fallback 这是合法的.
  • 倒回可以自由混合策略——CSS初级与角色+名倒回,id初级与xpath倒回等.

最坏情况 在节点匹配的N级链上: N × defaultTimeout. 在实务中倒计时涵盖了真实的DOM变体,因此第一或第二关在初级不匹配的页面上相匹配.

常见用途:

  • 多国DOM变体 ——一个条目为每个国家服务,而不是针对具体国家的回购文件.
  • 品牌特异性初级+通用倒置 - 更喜欢特定品牌 data-qa,降解为角色选择器.
  • 严重退化 ——在逐步推出期间对新旧DOM进行测试.

条目标记 : provisional 财务报告和审定财务报表 list

两个可选布尔键坐在旁边 elementName 财务报告和审定财务报表 selector。两个方法都无法改变元素的解决方式;它们记录了输入的内容 表示,所以工具化和消费包 就可以采取行动.

{
  "elementName": "basketRows",
  "list": true,
  "selector": { "css": "[data-testid='basket-row']" }
},
{
  "elementName": "discountLine",
  "provisional": true,
  "selector": { "role": "row", "name": { "regex": "discount", "flags": "i" } }
}
  • list ——该条目为收录:其合同为"至少一对"(QQ 1),而非"确切为一元素". 消费者读它与 getElementMeta(); 元素交互使用它 verifyPresence 编号 : getAll默认 false。 。 。 .
  • provisional ——该条目尚未根据运行中的应用程序得到确认(例如从源代码或文档推断出). getProvisional() 列出这些条目,以便管道能够确认或拒绝运送这些条目。 默认 false。 。 。 .

当寄存器构建时(和静态),两个密钥都会被验证 ElementRepository.validate(data): 一个值,但不包括 true 编号 : false -比如绳子 "true" ——错误地点出每个违法者的名字 Page.element。 。 。 .

使用量

初始化

建筑师拿走 驱动程序 (打字笔) Page 或网络驱动程序 Browser作为第一个论点:

import { ElementRepository } from '@civitas-cerebrum/element-repository';

// Option A: Pass a file path (relative to project root)
const repo = new ElementRepository(page, 'tests/data/locators.json');

// Option B: Pass parsed JSON data directly
import locatorData from '../data/locators.json';
const repo = new ElementRepository(page, locatorData);

// Option C: With a custom timeout (default: 15000ms)
const repo = new ElementRepository(page, locatorData, 30000);

// Access the bound driver
const driver = repo.driver; // returns the Page/Browser passed to the constructor

获取元素

所有方法的使用 (elementName, pageName) 统一命令和返回 Element 对象 :

test('Search and select random product', async ({ page }) => {
  const repo = new ElementRepository(page, 'tests/data/locators.json');

  // Get a single element (defaults to first match)
  const searchInput = await repo.get('search-input', 'HomePage');
  await searchInput.fill('Trousers');

  // Get with a specific strategy
  const thirdCard = await repo.get('product-cards', 'ProductList', {
    strategy: SelectionStrategy.INDEX, index: 2
  });

  // Select a random element from a list
  const randomProduct = await repo.getRandom('product-cards', 'ProductList');
  await randomProduct?.click();

  // Find by text
  const specificProduct = await repo.getByText('product-cards', 'ProductList', 'Blue Chinos');
  await specificProduct?.click();

  // Find by HTML attribute
  const activeCard = await repo.getByAttribute('product-cards', 'ProductList', 'data-status', 'active');

  // Get by index
  const secondCard = await repo.getByIndex('product-cards', 'ProductList', 1);

  // Get the first visible element
  const visibleModal = await repo.getVisible('modal', 'HomePage');

  // Filter by ARIA role
  const navLink = await repo.getByRole('nav-links', 'HomePage', 'link');
});

流利的动作链

每个 Element 暴露一个 action(timeout?) 返回可导的方法 ElementChain 建会者. 队列多个动作并用单个执行它们 await数字 :

const element = await repo.get('submitButton', 'LoginPage');

// Interaction chain
await element.action(5000)
  .waitForState('visible')
  .click()

// Click without scrolling (for dropdown/flyout items)
await element.action()
  .waitForState('attached')
  .click({ withoutScrolling: true })

// Fill and verify
await element.action()
  .fill('[email protected]')
  .verifyText('[email protected]')

// Verification chain
await element.action(5000)
  .verifyPresence()
  .verifyText('Submit')
  .verifyAttribute('type', 'submit')

// Extraction (terminal — returns value)
const text = await element.action().getText()
const href = await element.action().getAttribute('href')
const count = await element.action().getCount()

可用链式方法

相互作用: click(options?), (中文(简体) ), clickIfPresent(options?), (中文(简体) ), hover(), (中文(简体) ), fill(text), (中文(简体) ), clear(), (中文(简体) ), check(), (中文(简体) ), uncheck(), (中文(简体) ), doubleClick(), (中文(简体) ), scrollIntoView(), (中文(简体) ), pressSequentially(text, delay?), (中文(简体) ), dispatchEvent(event)

核查: verifyPresence(), (中文(简体) ), verifyAbsence(), (中文(简体) ), verifyText(expected?), (中文(简体) ), verifyTextContains(text), (中文(简体) ), verifyAttribute(name, value), (中文(简体) ), verifyEnabled(), (中文(简体) ), verifyDisabled(), (中文(简体) ), verifyChecked(), (中文(简体) ), verifyCount(options)

摘录( 直线): getText(), (中文(简体) ), getAttribute(name), (中文(简体) ), getInputValue(), (中文(简体) ), getCount(), (中文(简体) ), getRaw(), (中文(简体) ), isPresent()

正在等待中 : waitForState(state)

API 参考

元素仓库

constructor(driver, dataOrPath, defaultTimeout?)

参数类型说明
driverany剧作家 Page 或网络驱动程序 Browser编号 :Driver 实例
dataOrPathstring | PageRepositoryJSON 文件或解析的 JSON 对象的路径
defaultTimeoutnumber默认等待超时 ms( 默认 ): 15000(中文(简体) )

get(elementName, pageName, options?)

返回单个 Element。默认为第一个匹配。 过 ElementResolutionOptions 来控制选择 :

import { SelectionStrategy } from '@civitas-cerebrum/element-repository';

await repo.get('button', 'Page')                                                    // first (default)
await repo.get('button', 'Page', { strategy: SelectionStrategy.INDEX, index: 2 })   // by index
await repo.get('button', 'Page', { strategy: SelectionStrategy.RANDOM })             // random
await repo.get('button', 'Page', { strategy: SelectionStrategy.TEXT, value: 'Sub' }) // by text
await repo.get('button', 'Page', { strategy: SelectionStrategy.ATTRIBUTE,
                                   attribute: 'data-id', value: 'row-2' })           // by attribute value
await repo.get('button', 'Page', { strategy: SelectionStrategy.ALL })                // un-narrowed (for counts)

一个未处理的战略值会丢出一个描述性错误 — 分辨率永远不会 当一个策略被请求时,悄悄地回到第一个匹配元素.

getAll(elementName, pageName)

返回所有匹配的数组 Element 对象.

getRandom(elementName, pageName, strict?)

随机从所有匹配中选择一个元素 .

getByText(elementName, pageName, desiredText, strict?)

返回包含指定文本的第一个元素。 先试一试,再回试.

getByAttribute(elementName, pageName, attribute, value, options?)

返回 HTML 属性符合给定值的第一个元素.

选项 : exact (布尔), strict (布尔)

getByIndex(elementName, pageName, index, strict?)

在指定的零基索引中返回元素.

getVisible(elementName, pageName, strict?)

返回第一个可见元素,过滤出隐藏的重复.

getByRole(elementName, pageName, role, strict?)

按元素过滤 role HTML属性.

getSelector(elementName, pageName)

返回一个平台格式的选择器字符串(同步).

getSelectorRaw(elementName, pageName)

回返 { strategy, value } ——原始选择器没有平台格式化.

getElementMeta(elementName, pageName)

回返 { provisional, list } 对条目,适用默认值(false。同步;只读存储器数据.

getProvisional()

回返 [{ pageName, elementName }] 每个标记条目 "provisional": true,按照仓库顺序.

ElementRepository.validate(data) (静态)

验证没有驱动程序(构造者也称它)的条目级密钥 。 掷出何时 provisional 或者说 list 以非布尔值存在.

getPagePlatform(pageName)

返回页面的平台字符串( E)'web', (中文(简体) ), 'android', (中文(简体) ), 'ios') (中文(简体) ).

严格模式

全体 get* 返回的方法 Element | null 接受选项 strict 参数 :

  • strict: false (默认)——返回 null 当找不到匹配时.
  • strict: true 抛出一个 Error 当找不到匹配时.

元素接口

全体 get* 方法返回一个 Element 一个平台不可知的界面, 包入一个 Playwright Locator (单位:千美元)WebElement或 WebDriverIO 元素(PlatformElement) (中文(简体) ).

相互作用方法

方法说明
click(options?)单击元素。 回返 Promise<Element>。 。 。 .
fill(text, options?)清取并取满文. 回返 Promise<Element>。 。 。 .
clear(options?)清除元素的值。 回返 Promise<Element>。 。 。 .
check(options?)检查复选框/收音机。 回返 Promise<Element>。 。 。 .
uncheck(options?)取消检查复选框。 回返 Promise<Element>。 。 。 .
hover(options?)绕过元素 回返 Promise<Element>。 。 。 .
doubleClick(options?)双击. 回返 Promise<Element>。 。 。 .
scrollIntoView(options?)卷入观想. 回返 Promise<Element>。 。 。 .
pressSequentially(text, delay?, options?)按角色分类 回返 Promise<Element>。 。 。 .
setInputFiles(filePath, options?)设置文件输入值 . 只有网络.
dispatchEvent(event)发布DOM活动. 只有网络.

所有交互方法都接受可选 { timeout?: number } 并返回元素用于简单的链条.

状态、采掘、查询和等待

方法说明
isVisible()回返 true 如果可见.
isEnabled()回返 true 如果启用的话.
isChecked()回返 true 如果选中的话.
raw()返回选择器字符串.
textContent()返回文本内容或 null。 。 。 .
getAttribute(name)返回属性值或 null。 。 。 .
inputValue()返回当前输入值.
count()返回匹配元素计数 .
all()返回所有匹配元素的数组 .
first()返回第一个匹配 .
nth(index)在索引中返回元素.
filter({ hasText })按文本内容过滤.
locateChild(selector)找到一个后人.
waitFor(options?)等待状态 : "visible", (中文(简体) ), "hidden", (中文(简体) ), "attached", (中文(简体) ), "detached"。 。 。 .
action(timeout?)返回流畅 ElementChain 建会者.

QQ 类型安全

import { Element, isWeb, isPlatform } from '@civitas-cerebrum/element-repository';

const el = await repo.get('submitButton', 'LoginPage');

if (isWeb(el)) {
  // Access the underlying Playwright Locator
  await (el as WebElement).locator.click();
}

if (isPlatform(el)) {
  // Access the WebDriverIO selector
  console.log((el as PlatformElement).selector);
}

· 突破变化(v.1.0)

变动移徙
需要构造器 driver 作为第一个参数new ElementRepository(data) → new ElementRepository(page, data)
方法减少 driver编号 :page 第1个段落repo.get(page, 'Page', 'el') → repo.get('el', 'Page')
参数顺序被翻转到 (elementName, pageName)在所有呼叫中交换参数
元素方法返回 Promise<Element>曾经 Promise<void> - 无需采取行动,除非你依赖 void
raw() 返回实际选择符字符串曾经 locator.toString() - 可能有所改进

许可证

麻省理工学院

版本与发布记录

@civitas-cerebrum/element-repository 共发布 22 个版本,首次发布于 2026/03/23;过去 12 个月发布了 22 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.3.4latest2026/11/018 天前
0.3.32026/11/018 天前
0.3.22026/08/122 个月前
0.3.12026/06/174 个月前
0.3.02026/06/174 个月前
0.2.12026/05/195 个月前

关于 @civitas-cerebrum/element-repository 的常见问题

@civitas-cerebrum/element-repository 是什么?

一个轻量级,强壮的软件包 将你的UI选择器从测试代码中解开 通过将定位器外部化成一个中央的JSON寄存器,使你的测试自动化框架更清洁,更方便维护,并方便非开发者访问.

如何安装 @civitas-cerebrum/element-repository?

在项目目录运行 npm install @civitas-cerebrum/element-repository,或使用 pnpm add / yarn add / bun add。

@civitas-cerebrum/element-repository 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@civitas-cerebrum/element-repository 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@civitas-cerebrum/element-repository 可以商用吗?

@civitas-cerebrum/element-repository 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@civitas-cerebrum/element-repository 的下载量有多少?

根据 npm 官方下载统计,@civitas-cerebrum/element-repository 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,198 次,日均约 107 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@civitas-cerebrum/element-repository 还在维护吗?

最新版本 0.3.4 发布于 2026/11/01(8 天前);至今共发布 22 个版本,其中过去 12 个月发布了 22 个;首次发布于 2026/03/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。