如何在WCT测试中禁用ready事件或dom-change事件?
解决Polymer 1.x测试中阻止ready处理器执行dom-change逻辑的问题
我来帮你搞定这个测试里的麻烦事——你的元素在ready阶段给#fields绑定了一次性的dom-change事件,元素一stamp就触发执行_setRadioDefaults,导致WCT根本来不及stub相关逻辑。下面给你几个可行的解决方案,结合你的代码来具体说明:
方法1:在元素实例化前拦截事件绑定
核心思路是修改元素原型的ready方法,拦截对dom-change事件的绑定操作,让原逻辑里的事件监听根本不会生效。
在测试的setup阶段这么写:
suite('sp-non-cash-benefits-form-edit tests', function() { let element; setup(function() { // 获取元素原型,保存原ready方法 const elementProto = customElements.get('sp-non-cash-benefits-form-edit').prototype; const originalReady = elementProto.ready; // 覆盖ready方法 elementProto.ready = function() { // 先拦截#fields的addEventListener const fieldsEl = this.$$('#fields'); const originalAddListener = fieldsEl.addEventListener; fieldsEl.addEventListener = (eventName, handler, options) => { // 只放行非dom-change的事件绑定 if (eventName !== 'dom-change') { originalAddListener.call(fieldsEl, eventName, handler, options); } }; // 调用原ready方法(此时dom-change绑定会被拦截) originalReady.call(this); // 恢复原addEventListener方法 fieldsEl.addEventListener = originalAddListener; }; // 再实例化元素 element = fixture('sp-non-cash-benefits-form-edit'); }); // 你的测试用例... });
方法2:提前Stub目标方法(不用阻止事件,而是替换逻辑)
如果你不想完全禁用事件,只是想让触发时执行的是stub逻辑,可以在元素stamp前就把_setRadioDefaults方法stub掉。因为fixture()才会触发元素的stamp和生命周期,所以提前修改原型就行:
setup(function() { // 获取元素原型,直接stub目标方法 const elementProto = customElements.get('sp-non-cash-benefits-form-edit').prototype; sinon.stub(elementProto, '_setRadioDefaults'); // 实例化元素,此时触发dom-change也只会执行stub的空方法 element = fixture('sp-non-cash-benefits-form-edit'); // 后续可以断言stub是否被调用,比如: // expect(element._setRadioDefaults.calledOnce).to.be.true; });
方法3:在事件捕获阶段阻止触发
这个方法适合你之前尝试过suppressDomChange但无效的场景——在事件传播的捕获阶段就阻止它,让原ready里绑定的处理器根本收不到事件:
setup(function() { // 先拿到测试模板里的#fields元素 const fixtureTemplate = document.getElementById('sp-non-cash-benefits-form-edit').querySelector('template'); const fieldsEl = fixtureTemplate.content.querySelector('#fields'); // 添加捕获阶段的事件处理器,阻止事件继续传播 fieldsEl.addEventListener('dom-change', (e) => { e.stopImmediatePropagation(); }, {capture: true}); // 实例化元素 element = fixture('sp-non-cash-benefits-form-edit'); });
长期优化建议:重构元素逻辑
如果这类测试问题经常出现,建议调整元素的逻辑结构,减少对dom-change事件的依赖。比如把依赖的answers属性改成带观察者的方式:
properties: { answers: { type: Object, notify: true, observer: '_onAnswersChanged' } }, _onAnswersChanged: function(newAnswers) { if (newAnswers?.answers) { this._setRadioDefaults(); } }, // 移除ready里的dom-change绑定逻辑 ready: function() { // 这里只保留其他必要的初始化逻辑 }
这样在测试中你可以先设置stub后的answers属性,再实例化元素,观察者会在属性就绪后触发,完全由你控制时机,测试会更灵活。
内容的提问来源于stack exchange,提问作者dman
相关产品推荐
相关产品推荐

