ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WebdriverIO Bidi 实战指南:实时浏览器日志捕获与预加载脚本注入

WebdriverIO Bidi 实战指南:实时浏览器日志捕获与预加载脚本注入 WebdriverIO Bidi 实战指南实时浏览器日志捕获与预加载脚本注入【免费下载链接】webdriverioNext-gen browser and mobile automation test framework for Node.js项目地址: https://gitcode.com/GitHub_Trending/we/webdriverio本文基于 WebdriverIO 仓库自带的 examples/bidi 示例讲解如何通过 WebDriver Bidi 协议在浏览器自动化中实时订阅控制台日志log.entryAdded与网络响应事件network.responseCompleted并向页面注入预加载脚本scriptAddPreloadScript。读完本文你将掌握webSocketUrl: true的启用原理、sessionSubscribe/browser.on()的事件订阅模式以及如何把这些能力复用到自己的测试或脚本中。什么是 WebDriver Bidi为什么用webSocketUrl传统 WebDriver 协议基于 HTTP 请求/响应客户端与浏览器之间只能一问一答无法实时获取浏览器内部事件如控制台输出、网络请求状态。WebDriver Bidi双向协议则在浏览器与客户端之间建立一条 WebSocket 长连接让浏览器可以主动把事件推送给客户端从而实现真正的实时监听与双向控制。在 WebdriverIO 中开启 Bidi 非常简单——只需要在创建会话时把webSocketUrl置为trueconst browser await remote({ logLevel: error, capabilities: { webSocketUrl: true, browserName: firefox } })从源码层面看webSocketUrl是否生效直接决定了 WebdriverIO 是否注册整套 Bidi 会话管理能力。在 packages/webdriverio/src/session/index.ts 中registerSessionManager只有在typeof instance.capabilities.webSocketUrl string时才会初始化 Polyfill、ShadowRoot、Network、Dialog 等基于 Bidi 的会话管理器/** * only register session manager for sessions that appear to support * WebDriver Bidi */ if (typeof instance.capabilities.webSocketUrl string) { initializationPromises.push( getPolyfillManager(instance).initialize(), getShadowRootManager(instance).initialize(), getNetworkManager(instance).initialize(), getDialogManager(instance).initialize() ) }也就是说webSocketUrl一旦开启WebdriverIO 会自动通过 Bidi 事件来驱动内部的网络拦截mock命令、Shadow DOM 穿透等功能——示例中的事件订阅只是你能够直接使用的一小部分能力。环境准备与运行方式examples/bidi目录下的示例脚本可以直接用 Node 运行示例脚本均为 ESM 格式且依赖仓库内的webdriverio包。示例包 examples/bidi/package.json 声明了type: module并在依赖中引入webdriverio: workspace:*。根据仓库根目录 examples/README.md 的说明运行这些示例的标准流程是先克隆仓库、安装依赖并完成构建然后进入对应目录用 Node 执行脚本git clone gitgithub.com:webdriverio/webdriverio.git cd ./webdriverio pnpm install pnpm run setup # 进入 Bidi 示例目录运行 cd ./examples/bidi node logging.js node scripting.js示例脚本 examples/bidi/logging.js 与 examples/bidi/scripting.js 都要求本机存在对应的浏览器logging.js中第一个会话用 Firefox、第二个会话与scripting.js用 Chrome运行时浏览器会真实弹出。提示仓库自带的示例不包含dev-dependencies如果你要在自己的工程里复刻这些能力建议基于 website/docs/GettingStarted.md 搭建一个标准 WebdriverIO 项目再把示例中的remote调用集成进去。实时捕获浏览器日志示例的第一种典型场景是实时监听浏览器产生的日志事件包含两类控制台日志与网络事件。订阅控制台日志log.entryAddedimport { remote } from webdriverio const browser await remote({ logLevel: error, capabilities: { webSocketUrl: true, browserName: firefox } }) await browser.sessionSubscribe({ events: [log.entryAdded] }) browser.on(log.entryAdded, (entryAdded) console.log(JSON.stringify(entryAdded, null, 4))) await browser.execute(() console.log(Hello Bidi)) await browser.deleteSession()这段代码的关键步骤开启 Bidicapabilities.webSocketUrl: true让 WebdriverIO 通过 WebSocket 连接浏览器订阅事件sessionSubscribe({ events: [log.entryAdded] })告诉浏览器只推送日志新增类事件log.entryAdded对应 Bidi 协议中的Log.entryAdded监听事件browser.on(log.entryAdded, ...)为事件注册回调回调参数是结构化的日志条目对象包含日志来源、级别、文本等字段触发日志browser.execute(() console.log(Hello Bidi))在页面上下文执行一段脚本触发console.log随后该日志事件会通过 WebSocket 推送到客户端并打印出来清理会话browser.deleteSession()关闭会话避免残留浏览器进程。订阅网络响应事件network.responseCompleted网络事件的订阅方式与日志完全一致只是事件名不同import { remote } from webdriverio const browser await remote({ logLevel: error, capabilities: { webSocketUrl: true, browserName: chrome } }) await browser.sessionSubscribe({ events: [network.responseCompleted] }) browser.on(network.responseCompleted, (networkResponse) console.log(JSON.stringify(networkResponse, null, 4))) await browser.url(https://webdriver.io) await browser.deleteSession()这里在sessionSubscribe中订阅network.responseCompleted然后用browser.on(network.responseCompleted, ...)监听。回调中拿到的networkResponse对象包含响应状态、URL、响应体、时间戳等字段。随后browser.url(https://webdriver.io)导航到页面页面加载过程中的每一个已完成响应都会实时推送并打印。注意sessionSubscribe是可以多次调用的examples/bidi/logging.js 中就把日志与网络两类事件放在同一个会话里先后订阅互不冲突await browser.sessionSubscribe({ events: [log.entryAdded] }) browser.on(log.entryAdded, (logEntry) console.log(JSON.stringify(logEntry, null, 4))) await browser.sessionSubscribe({ events: [network.responseCompleted] }) browser.on(network.responseCompleted, (networkResponse) console.log(JSON.stringify(networkResponse, null, 4)))事件订阅的底层实现sessionSubscribe是 WebdriverIO 通过 Bidi 协议暴露出来的标准命令其协议定义位于 packages/wdio-protocols/src/protocols/webdriverBidi.ts。WebdriverIO 内部自己也在使用同样的机制在 packages/webdriverio/src/session/networkManager.ts 中网络管理器初始化时会一次性订阅network.responseCompleted、network.beforeRequestSent、network.fetchError、browsingContext.navigationStarted等事件并把这些事件关联到内部监听器进而支撑起 WebdriverIO 的mock网络拦截能力this.#initialize this.#browser.sessionSubscribe({ events: [ browsingContext.navigationStarted, network.beforeRequestSent, network.responseCompleted, ... ] }) this.#browser.on(network.responseCompleted, this.#responseCompletedListener) this.#browser.on(network.beforeRequestSent, this.#beforeRequestSentListener)可以推断sessionSubscribe本质上就是向浏览器发送 Bidi 命令并返回订阅确认而browser.on()则是 WebdriverIO 对 WebSocket 事件流的封装。你在示例中使用的 API 与 WebdriverIO 内部使用的完全是同一套通道因此它既稳定又具备完整的协议能力。通过预加载脚本注入页面逻辑Bidi 的另一个实用能力是在任意页面加载前注入脚本。所谓“预加载脚本”preload script是指注册到浏览器会话中、在目标页面脚本执行之前就被注入并运行的脚本适用于注入全局变量、拦截 API、埋点等场景。import { remote } from webdriverio const browser await remote({ logLevel: error, capabilities: { webSocketUrl: true, browserName: chrome } }) await browser.scriptAddPreloadScript({ functionDeclaration: () { window.barfoo; } }) await browser.url(https://webdriver.io) await browser.pause(2000) console.log(await browser.execute(() window.bar)) await browser.deleteSession()这段代码的执行流程用scriptAddPreloadScript注册一个匿名函数其函数体window.barfoo会在每个新页面的脚本环境初始化时执行browser.url(...)打开目标页面预加载脚本自动注入browser.pause(2000)等待页面完成加载browser.execute(() window.bar)在页面上下文读取window.bar打印出foo从而验证预加载脚本确实在页面加载前生效browser.deleteSession()结束会话。scriptAddPreloadScript同样定义在 packages/wdio-protocols/src/protocols/webdriverBidi.ts。除了functionDeclaration函数体声明之外它还支持通过arguments参数向脚本传入额外的值默认是空数组这对于注入可配置的初始化数据非常有用。WebdriverIO 官方的addInitScript命令见 packages/webdriverio/src/commands/browser/addInitScript.ts底层也是基于scriptAddPreloadScript封装的可以理解为 Bidi 预加载脚本能力的命令化入口。注意事项与最佳实践浏览器支持Bidi 协议要求浏览器具备相应的 WebDriver BiDi 实现。示例中 Firefox 与 Chrome 均可用若使用不支持 Bidi 的浏览器或驱动版本sessionSubscribe等命令可能不可用。从 packages/webdriverio/src/session/index.ts 的实现看会话管理器仅在capabilities.webSocketUrl为字符串时才注册说明该能力由浏览器端能力决定。事件名与回调sessionSubscribe订阅的事件名与browser.on监听的事件名必须完全一致如log.entryAdded、network.responseCompleted回调参数是结构化的 Bidi 事件对象建议用JSON.stringify(entry, null, 4)打印观察其字段。会话生命周期示例中都显式调用browser.deleteSession()清理会话在真实测试框架中应把订阅放在before/after钩子中避免事件泄漏或浏览器进程残留。订阅尽量精准只订阅自己关心的事件示例中为log.entryAdded/network.responseCompleted减少不必要的事件流量保持回调逻辑轻量以免阻塞 WebSocket 事件处理。借助 WebdriverIO 的 Bidi 支持你可以在不额外安装 Chrome DevTools 相关依赖的前提下用统一的remoteAPI 完成实时日志采集、网络监听与脚本注入。如需进一步探索可继续阅读 packages/webdriverio/src/session/networkManager.ts 了解网络拦截的完整实现或直接运行仓库中的 examples/bidi/logging.js 与 examples/bidi/scripting.js 体验真实效果。【免费下载链接】webdriverioNext-gen browser and mobile automation test framework for Node.js项目地址: https://gitcode.com/GitHub_Trending/we/webdriverio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表