WCT无法存根私有元素求助(Polymer1+Chrome Shady DOM环境)
解决Polymer 1 + WCT测试中存根
<sp-toast> display方法的问题 看起来你遇到的问题核心是没有正确获取到<sp-toast>的实例,或者在元素初始化完成前就尝试存根方法,再加上Shady DOM的环境细节影响,导致找不到display方法。下面一步步拆解问题和解决办法:
为什么会报错?
你的两个错误提示指向同一个根源:
Attempted to wrap undefined property display as function:你传给stub的对象(这里是'sp-toast'标签名)上根本没有display这个属性spToast.display is not a function:运行时你调用的spToast对象(不管是实例还是全局对象)上也找不到这个方法
在Polymer 1和WCT的组合环境里,存根元素方法必须满足两个前提:元素已经完成初始化,你操作的是元素的实例对象,而不是标签名或者未初始化的元素。
正确的解决步骤
1. 确保获取到<sp-toast>的正确实例
首先,你需要拿到<sp-toast>的真实DOM实例:
- 如果
<sp-toast>是测试元素(比如my-element)内部的子元素,用Polymer的$$方法获取(Shady DOM下推荐用这个,避免选择器问题):const spToast = myElement.$$('sp-toast'); - 如果是全局挂载的
<sp-toast>,用document.querySelector('sp-toast'),但要确保它已经被添加到DOM中。
2. 等待Polymer元素初始化完成
Polymer元素的初始化是异步的,WCT测试中必须等待元素ready后再操作。你可以用WCT提供的flush()方法强制完成DOM更新和元素初始化:
setup(function(done) { myElement = fixture('my-element-fixture'); // 刷新DOM,确保所有Polymer元素完成初始化 flush(() => { spToast = myElement.$$('sp-toast'); // 这里可以先检查实例是否存在,避免后续报错 if (!spToast) { done(new Error('找不到sp-toast元素,请检查fixture定义')); return; } done(); }); });
3. 正确存根display方法
现在你有了初始化完成的元素实例,就可以存根它的display方法了。如果display是异步方法(比如返回Promise),最好存根时返回一个resolved的Promise,避免测试异步问题:
setup(function(done) { myElement = fixture('my-element-fixture'); flush(() => { spToast = myElement.$$('sp-toast'); // 存根display方法,返回resolved Promise stub(spToast, 'display').returns(Promise.resolve()); done(); }); });
4. 特殊情况:如果spToast是全局对象
如果你的业务代码里是调用全局的spToast.display()(而不是DOM元素实例的方法),那你需要存根全局对象的方法:
// 存根全局的spToast.display stub(window.spToast, 'display').returns(Promise.resolve());
但这种情况要确保window.spToast已经在测试环境中被正确定义。
完整测试代码示例
suite('my-element 测试', function() { let myElement; let spToast; setup(function(done) { // 加载测试用的fixture myElement = fixture('my-element-fixture'); // 强制刷新DOM,完成元素初始化 flush(() => { spToast = myElement.$$('sp-toast'); if (!spToast) { done(new Error('fixture中未找到sp-toast元素')); return; } // 存根display方法 stub(spToast, 'display').returns(Promise.resolve()); done(); }); }); test('触发动作时应该调用sp-toast的display方法', function() { // 触发元素的某个动作(比如点击按钮、触发事件) myElement.fire('show-toast'); // 断言display方法被调用 expect(spToast.display).to.have.been.called; }); });
排查技巧
- 在存根前加
console.log(spToast)和console.log(spToast.display),确认实例和方法是否存在 - 检查你的fixture模板中是否确实包含了
<sp-toast>元素 - 确保测试文件中已经导入了
sp-toast元素的定义(比如通过import '../sp-toast.html';)
内容的提问来源于stack exchange,提问作者dman
相关产品推荐
相关产品推荐

