ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Angular Components 的 Aria Tree 组件测试 Harness 全解析:@angular/aria/tree/testing API 指南

Angular Components 的 Aria Tree 组件测试 Harness 全解析:@angular/aria/tree/testing API 指南 Angular Components 的 Aria Tree 组件测试 Harness 全解析angular/aria/tree/testing API 指南【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components导读本文以 Angular Components 仓库中angular/aria/tree/testing包的官方 API 报告goldens/aria/tree/testing/index.api.md为核心系统讲解 ARIA 树Tree组件在测试中使用的 Component Harness 体系TreeHarness、TreeItemHarness及其过滤器类型。你将掌握如何通过 Harness 在单元测试中定位树与树节点、读取展开/禁用/选中/层级状态、模拟点击与聚焦交互以及如何利用getTreeStructure()断言整棵树的可见结构并了解这些能力背后与 ARIA 属性aria-expanded、aria-selected、aria-level等一一对应的实现原理。一、什么是 Component Harness包的定位Angular Components 为每个组件提供两套面向测试的公共 API组件本身以及配套的 Component Harness。Harness 是对 DOM 交互逻辑的封装测试代码不直接操作原生 DOM 或依赖 CSS 选择器细节而是通过angular/cdk/testing提供的抽象环境如TestbedHarnessEnvironment与组件交互从而让测试同时兼容 TestBed、Protractor、Selenium WebDriver 等多种测试环境。angular/aria/tree/testing就是 ARIA 树组件的测试 Harness 包。从 API 报告可以看到它导出的全部公共符号为符号类型说明TextTreeinterface树结构的纯文本描述对象textchildrenTreeHarnessclass树的测试 Harness宿主选择器[ngTree]TreeHarnessFiltersinterface定位树的过滤器继承BaseHarnessFilters无额外字段TreeItemHarnessclass树节点的测试 Harness宿主选择器[ngTreeItem]TreeItemHarnessFiltersinterface定位树节点的过滤器支持text/disabled/expanded/selected/level这些符号与主组件包src/aria/tree/public-api.ts中的Tree、TreeItem、TreeItemGroup三个指令一一对应其中TreeHarness/TreeItemHarness分别对应[ngTree]与[ngTreeItem]宿主指令。从 testing/BUILD.bazel 可以看出该测试包的源码仅依赖//src/cdk/testing而单元测试同时引入//src/aria/tree与//src/cdk/testing/testbed并通过ng_web_test_suite运行。二、TreeHarness整棵树的测试入口TreeHarness extends ComponentHarness是操作整棵树的入口。其定义位于 src/aria/tree/testing/tree-harness.ts。2.1 宿主选择器与静态方法static hostSelector [ngTree]Harness 通过该选择器定位树指令宿主元素测试环境中每个[ngTree]元素对应一个TreeHarness实例。static with(options?: TreeHarnessFilters): HarnessPredicateTreeHarness返回一个可复用的查找谓词。由于TreeHarnessFilters仅继承BaseHarnessFilters当前版本支持按selector、ancestor等基类条件过滤树上没有额外的专有过滤字段。2.2 getItems获取树节点async getItems(filter: TreeItemHarnessFilters {}): PromiseTreeItemHarness[]返回树内所有满足过滤条件的节点 Harness。实现上调用this.locatorForAll(TreeItemHarness.with(filter))()即基于TreeItemHarness.with()构造的谓词进行全量定位源码见 tree-harness.ts。不传参数时返回树中全部可见节点。在 tree-harness.spec.ts 的测试样例中一棵未展开的树包含 5 个顶层节点public、src、angular.json、package.json、README.md点击展开public后节点总数变为 8——说明getItems返回的是当前展开状态下可见的节点折叠分支内的节点不会出现。2.3 getTreeStructure断言整棵树的结构async getTreeStructure(): PromiseTextTree这是TreeHarness最具特色的能力返回一棵仅包含文本的层级对象便于对树的可见结构做整体断言。TextTree的定义为export interface TextTree { text?: string; children?: TextTree[]; }算法流程见 tree-harness.ts先通过getItems()拿到全部可见节点用parallel()并发读取每个节点的getLevel()层级、getText()文本、isExpanded()展开态三元组递归遍历这些三元组按aria-level的层级关系组装TextTree同级节点依次加入children列表遇到更深层级节点则递归下沉为其子级遇到更浅层级节点则结束当前层级可见性规则只有“父节点处于展开状态”的节点才会进入结果parentExpanded参数控制这一逻辑。测试中的典型断言tree-harness.spec.tsexpect(await tree.getTreeStructure()).toEqual({ children: [ {text: public}, {text: src}, {text: angular.json}, {text: package.json}, {text: README.md}, ], });展开public后结果变为{ children: [ { text: public, children: [{text: index.html}, {text: favicon.ico}, {text: styles.css}], }, {text: src}, // ... ], }这一特性非常适合验证“折叠/展开后树的展示是否符合预期”的交互类测试场景。三、TreeItemHarness树节点级交互TreeItemHarness extends ContentContainerComponentHarnessstring泛型参数表示其查询文本的类型。定义位于 src/aria/tree/testing/item-harness.ts宿主选择器为static hostSelector [ngTreeItem]。3.1 状态查询方法这些方法的核心实现都通过读取宿主元素上的 ARIA 属性完成与组件源码 src/aria/tree/tree-item.ts 中模板绑定的aria-expanded、aria-selected、aria-disabled、aria-level、data-active一一对应方法返回值读取的属性说明isExpanded()Promisebooleanaria-expanded是否展开属性值为字符串true/falseisDisabled()Promisebooleanaria-disabled是否禁用isSelected()Promisebooleanaria-selected是否选中getLevel()Promisenumberaria-level层级1 起始属性缺失时默认返回1isActive()Promisebooleandata-active是否为当前活动项isFocused()Promiseboolean——通过host().isFocused()判断真实焦点不读属性getText()Promisestring——取宿主文本排除嵌套的[ngTreeItem]、[ngTreeItemGroup]内容避免子节点文本混入3.2 交互方法click()点击节点常用于触发折叠/展开切换或选中操作focus()/blur()将焦点移入/移出节点。3.3 与组件属性的对应关系树组件本身对 ARIA 属性的管理见 src/aria/tree/tree-item.tsexpanded由_expanded()信号绑定aria-expandedselected绑定aria-selected禁用态绑定aria-disabled层级绑定aria-level活动态绑定data-active。而 tree.spec.ts 还验证了细节行为无子节点的节点不输出aria-expanded属性有子节点的节点默认输出falsearia-level、aria-setsize、aria-posinset会正确设置。这解释了为什么TreeItemHarness.isExpanded()基于属性字符串比较即可可靠工作。四、过滤器精准定位树与节点4.1 TreeHarnessFiltersexport interface TreeHarnessFilters extends BaseHarnessFilters {}空扩展仅继承 CDK 基类的通用条件如按选择器、祖先、后代等过滤。定义见 tree-harness-filters.ts。4.2 TreeItemHarnessFiltersexport interface TreeItemHarnessFilters extends BaseHarnessFilters { text?: string | RegExp; // 文本匹配支持正则 disabled?: boolean; // 禁用状态匹配 expanded?: boolean; // 展开状态匹配 selected?: boolean; // 选中状态匹配 level?: number; // 层级匹配 }TreeItemHarness.with(options)会把每个字段注册为谓词条件item-harness.tstext使用HarnessPredicate.stringMatches(harness.getText(), text)支持字符串与正则disabled/expanded/selected分别与isDisabled()/isExpanded()/isSelected()的结果比对level与getLevel()的数值比对。测试中的典型用法tree-harness.spec.tsconst items await tree.getItems({text: /\.json$/}); // 文本正则过滤 expect(items.length).toBe(2); const item items[0]; expect(await item.getText()).toBe(angular.json); expect(await item.getLevel()).toBe(1); expect(await item.isDisabled()).toBe(false); expect(await item.isExpanded()).toBe(false);注意过滤条件是叠加生效的例如getItems({level: 1, expanded: true})只会返回展开的顶层节点。五、实战完整的树交互测试示例综合 tree-harness.spec.ts 的完整测试组件其模板展示了[ngTree]、[ngTreeItem]、ngTemplate[ngTreeItemGroup]的标准组合用法配合ngTemplateOutlet递归渲染节点一个典型的测试流程如下import {TestbedHarnessEnvironment} from angular/cdk/testing/testbed; import {TreeHarness} from angular/aria/tree/testing; // 1. 获取 Harness 环境与树 const loader TestbedHarnessEnvironment.loader(fixture); const tree await loader.getHarness(TreeHarness); // 2. 折叠/展开切换 let item (await tree.getItems())[0]; expect(await item.isExpanded()).toBe(false); await item.click(); expect(await item.isExpanded()).toBe(true); // 3. 按状态过滤定位 const disabledItems await tree.getItems({disabled: true}); const topLevelExpanded await tree.getItems({level: 1, expanded: true}); // 4. 焦点管理 const target (await tree.getItems({text: angular.json}))[0]; expect(await target.isFocused()).toBeFalse(); await target.focus(); expect(await target.isFocused()).toBeTrue(); await target.blur(); // 5. 整体结构断言 expect(await tree.getTreeStructure()).toEqual({ children: [{text: public}, {text: src} /* ... */], });前提条件使用前需确保测试环境已引入angular/cdk/testing与对应测试平台TestBed 环境为angular/cdk/testing/testbed并已导入Tree、TreeItem、TreeItemGroup指令见 BUILD.bazel 中的依赖配置。六、使用约束与注意事项可见性语义getItems()与getTreeStructure()都只反映当前可见节点折叠分支内的子节点不会出现断言前需先通过click()展开目标父节点。层级为 1 起始getLevel()直接解析aria-level属性根节点层级为 1与 WAI-ARIA Tree 模式语义一致。无子节点与aria-expanded无子节点的节点不携带aria-expanded属性因此isExpanded()对它返回false属性缺失按false处理。文本排除策略getText()会剔除嵌套的节点与分组元素文本但不会排除普通兄弟元素断言精确文本时应与过滤器{text: ...}配合使用。API 以 golden 报告为准本包公共 API 受 goldens/aria/tree/testing/index.api.md 约束任何公共签名变更都需要同步更新 golden 文件因此该报告是判断 Harness 能力边界的最权威依据。七、深入阅读包入口与导出 src/aria/tree/testing/index.ts、 public-api.ts实现源码 tree-harness.ts、 item-harness.ts、 tree-harness-filters.ts单元测试 tree-harness.spec.ts组件实现与 ARIA 属性绑定 tree-item.ts、 tree.ts、 tree.spec.ts主组件包 API 报告 goldens/aria/tree/index.api.md构建配置 testing/BUILD.bazel【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表