Cypress测试中如何定位JS创建且不在document.body中的元素
定位JavaScript动态创建的Audio元素(Cypress测试)
用new Audio()创建的音频实例默认不会自动加入DOM树,这就是你用常规cy.get('audio')查不到它的原因——Cypress的元素查询只针对挂载到document.body或其他DOM节点下的元素。下面是几种解决方法:
1. 确认并等待元素挂载到DOM
如果你的应用会在播放音频、加载完成等场景下把audio元素添加到DOM,那你只需要等待对应的触发动作,再执行查询:
// 先触发音频播放(比如点击播放按钮) cy.get('.play-btn').click(); // 等待audio元素出现在DOM中 cy.get('audio').should('exist');
如果应用代码里完全没做挂载操作,你可以在测试中手动将实例添加到DOM(前提是能访问到这个实例):
cy.window().then(win => { // 假设应用将audio实例存在window.myAudio上 const audio = win.myAudio; document.body.appendChild(audio); // 现在就能用cy.get查到了 cy.get('audio').should('have.attr', 'src', 'path/to/your/audio.mp3'); });
2. 直接访问全局的Audio实例
如果你的应用把创建的Audio实例暴露到了全局(比如挂在window对象上),可以通过cy.window()直接获取并操作:
cy.window().then(win => { const audioInstance = win.audioPlayer; // 替换成你实际的全局变量名 // 断言音频源 expect(audioInstance.src).to.include('target-audio.mp3'); // 触发播放操作 audioInstance.play(); // 断言播放状态 expect(audioInstance.paused).to.be.false; });
3. 通过事件监听捕获Audio实例
如果无法直接访问实例,可以监听音频相关的事件(比如play、canplaythrough),在事件触发时捕获对应的audio元素:
cy.window().then(win => { cy.wrap(null).then(() => { return new Cypress.Promise(resolve => { // 监听play事件,捕获触发事件的audio元素 win.addEventListener('play', (e) => { if (e.target instanceof win.Audio) { resolve(e.target); } }, { once: true }); }); }).then(audioElement => { expect(audioElement).to.exist; expect(audioElement.duration).to.be.greaterThan(0); }); // 触发音频播放动作 cy.get('.play-btn').click(); });
注意事项
- 如果应用没有将Audio实例暴露到全局,可能需要临时修改应用代码,在创建实例时添加
window.audioInstance = new Audio(...),方便测试完成后再移除。 - 未挂载到DOM的Audio元素无法通过
cy.get()查询,必须通过cy.window()访问JavaScript上下文才能获取。
内容的提问来源于stack exchange,提问作者Adriano174
相关产品推荐
相关产品推荐

