如何让WebDriverIO等待React Native Web页面完全加载完成
问题核心原因与解决方案
React Native Web应用渲染时会内置过渡动画、动态样式修改逻辑,普通的WebdriverIO元素等待方法无法适配这类场景,结合你当前代码的问题,优化方案如下:
现有代码问题
- 代码中直接使用
document.querySelector("#View")属于浏览器端原生API,无法在Node环境运行的WebdriverIO测试脚本中执行,会直接抛出未定义错误,需删除 - waitFor系列方法传参不规范,WebdriverIO v7及以上版本需统一使用对象格式传参,否则超时配置不生效
- 未做iframe上下文切换,仅识别到iframe元素存在无法操作内部元素,必须切换上下文后才可访问iframe内DOM
- 未处理RN Web的过渡动画等待逻辑,页面切换过程中元素DOM已存在但处于动画中,点击、可见性判断都会失效
- Appium移动端环境未校验当前处于WEBVIEW上下文,可能会错误识别原生控件导致元素查找失败
优化后代码
describe('My Login application', async () => { beforeEach(async () => { // 先确认当前在WEBVIEW上下文,适配Appium移动端浏览器环境 const contexts = await browser.getContexts(); const webContext = contexts.find(ctx => ctx.includes('WEBVIEW')); if (webContext) await browser.switchContext(webContext); await browser.url('./'); // 等待页面加载完成、网络空闲 await browser.waitUntil(async () => { return await browser.execute(() => { return window.performance.timing.loadEventEnd > 0 && window.performance.getEntriesByType('resource').every(r => r.responseEnd > 0) }) }, { timeout: 30000, interval: 500 }); await browser.setTimeout({'script': 30000}) }); it('turn pages', async function () { const view = $('#View') // 同时校验存在+可见,适配RN Web渲染逻辑 await view.waitForExist({ timeout: 25000 }); await view.waitForDisplayed({ timeout: 10000 }); const isview = await view.isDisplayed(); console.log('isview:' + isview) if(isview) { const header = $('.header__wrapper') await header.waitForClickable({ timeout: 30000 }); await header.click(); // 等待页面跳转动画完成 await browser.pause(1000); const orderView = $('.OrderView'); await orderView.waitForDisplayed({ timeout: 30000 }); console.log('order value:' + await orderView.getHTML()); console.log('checking title:') const title1 = await $('.chapter-title') await title1.waitForExist({timeout: 50000}); await title1.waitForDisplayed({timeout: 10000}); console.log('checking html:') console.log('html value:' + await title1.getHTML()) const form = await $('iframe') await form.waitForExist({ timeout: 15000 }); // 切换到iframe上下文 await browser.switchToFrame(form); console.log('已切换到iframe上下文') await browser.setTimeout({'script': 20000}) // 激活页面焦点,避免移动端按键不生效 await browser.execute(() => document.body.focus()); await browser.keys("ArrowLeft") await browser.keys("Enter") const container = await $('.container'); await container.waitForExist({timeout: 50000}); await container.waitForDisplayed({timeout: 10000}); // 测试完成后可切回主上下文 // await browser.switchToParentFrame(); await browser.pause(3000); } }); });
额外适配RN Web的等待优化
可以封装自定义等待方法,适配RN Web的动态样式逻辑:
async function waitForRnElementDisplayed(selector, timeout = 30000) { await browser.waitUntil(async () => { const el = await $(selector); const isDisplayed = await el.isDisplayed(); if (!isDisplayed) return false; // 额外校验元素透明度、transform动画状态 const styles = await el.getCSSProperties(['opacity', 'transform']); return styles.opacity > 0.9 && styles.transform === 'matrix(1, 0, 0, 1, 0, 0)'; }, { timeout, interval: 500 }); }
后续查找RN Web元素时直接调用该方法即可,避免动画过程中的误判。
内容的提问来源于stack exchange,提问作者brocheppu
相关产品推荐
相关产品推荐

