Protractor无法访问自定义Locator,报错Failed: by.shadowRoot is not a function
解决Protractor自定义shadowRoot定位器无法访问的问题
你遇到的Failed: by.shadowRoot is not a function错误,大概率是代码细节问题或者加载顺序不对导致的,咱们一步步来修复:
1. 先修复定位器代码里的变量笔误
你的代码片段里,参数是selector,但内部却用了未定义的cssSelector,这会直接导致定位器注册失败。先把变量名统一,同时补全你截断的findAllMatches逻辑:
"use strict"; module.exports = function() { By.addLocator('shadowRoot', function(selector, using) { // 把未定义的cssSelector改成传入的selector参数 var selectors = selector.split('::sr'); if (selectors.length === 0) { return []; } var shadowDomInUse = !!(document.head.createShadowRoot || document.head.attachShadow); var getShadowRoot = function (el) { return ((el && shadowDomInUse) ? el.shadowRoot : el); }; // 补全节点查询的核心逻辑 var findAllMatches = function(el, selector) { var nodes = el.querySelectorAll(selector); return Array.prototype.slice.call(nodes); }; var currentElements = using ? [using] : findAllMatches(document, selectors[0]); for (var i = 1; i < selectors.length; i++) { var tempElements = []; for (var j = 0; j < currentElements.length; j++) { var shadowRoot = getShadowRoot(currentElements[j]); tempElements = tempElements.concat(findAllMatches(shadowRoot, selectors[i])); } currentElements = tempElements; } return currentElements; }); };
2. 确保定位器在测试代码前正确加载
Protractor需要在初始化阶段就完成自定义定位器的注册,最稳妥的方式是在配置文件的onPrepare钩子中加载:
// conf.js 配置示例 exports.config = { // 其他配置项(比如specs、capabilities等)... onPrepare: function() { // 替换成你的定位器文件路径 require('./shadow-root-locator.js')(); } };
如果只是单个测试文件需要使用,也可以直接在测试文件最顶部引入:
require('./shadow-root-locator.js')(); describe('Shadow DOM测试', function() { // 测试逻辑... });
3. 验证调用方式是否正确
注册成功后,你可以这样使用自定义定位器:
// 示例:定位外层元素shadowRoot内的子元素 element(by.shadowRoot('outer-container::sr .inner-shadow-element'));
常见排查点总结
- 检查变量名是否一致(比如你之前的
cssSelector笔误) - 确认定位器模块在测试代码执行前被加载(
onPrepare是最可靠的时机) - 确保内部函数逻辑完整,没有代码截断导致的语法错误
内容的提问来源于stack exchange,提问作者Abbas Ali Husain
相关产品推荐
相关产品推荐

