WebDriver.io使用wdio-intercept-service遇TypeError错误求助
问题描述
我尝试用WebDriver.io搭配wdio-intercept-service执行测试,运行npm run test时出现TypeError: WebdriverAjax is not a function错误。此前尝试用Nock拦截并修改请求响应也未成功,以下是相关代码及完整报错信息,希望解决这两个问题:
package.json
{ "name": "my-new-project", "type": "module", "devDependencies": { "@wdio/cli": "^8.8.8", "@wdio/local-runner": "^8.8.8", "@wdio/mocha-framework": "^8.8.7", "@wdio/spec-reporter": "^8.8.7", "chromedriver": "^112.0.0", "geckodriver": "^3.2.0", "msedgedriver": "^91.0.0", "nock": "^13.3.1", "wdio-chromedriver-service": "^8.1.1", "wdio-edgedriver-service": "^2.1.2", "wdio-geckodriver-service": "^4.1.1", "wdio-intercept-service": "^4.4.0" }, "scripts": { "wdio": "wdio run ./wdio.conf.js", "test": "wdio run ./wdio.conf.js --spec test/specs/test1.js" }, "dependencies": { "webdriverio": "^8.8.8" } }
test1.js
import { remote } from 'webdriverio'; import WebdriverAjax from 'wdio-intercept-service' const WDIO_OPTIONS = { port: 9515, path: '/', capabilities: { browserName: 'chrome' }, } let browser; const interceptServiceLauncher = WebdriverAjax(); beforeAll(async () => { browser = await remote(WDIO_OPTIONS) interceptServiceLauncher.before(null, null, browser) }) beforeEach(async () => { interceptServiceLauncher.beforeTest() }) afterAll(async () => { await client.deleteSession() }); async function time(pause = 1000) { const starttime = new Date().getTime(); await browser.pause(pause); const endtime = new Date().getTime(); console.log("-------------------------------->", pause, endtime - starttime); // outputs: 3000 } describe('Test Case Name', () => { it('should intercept and modify a request with Nock', async () => { await time(1000); browser.url('https://jsonplaceholder.typicode.com'); browser.setupInterceptor(); // capture ajax calls browser.expectRequest('GET', '/posts/1', 200); // expect GET request to /api/foo with 200 statusCode browser.expectRequest('POST', '/posts/1', 400); // expect POST request to /api/foo with 400 statusCode browser.expectRequest('GET', /\/posts\/1/, 200); // can validate a URL with regex, too browser.click('#button'); // button that initiates ajax request browser.pause(1000); // maybe wait a bit until request is finished browser.assertRequests(); // validate the requests await time(5000); }); });
报错信息
DevTools listening on ws://127.0.0.1:55425/devtools/browser/0d726522-6a04-4054-820c-b9805dde997a [0-0] 2023-05-01T08:58:50.200Z ERROR @wdio/runner: Error: Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised. [0-0] `browser` object has only `capabilities` and some flags like `isMobile`. [0-0] Helper files that use other `browser` commands have to be moved to `before` hook. [0-0] Spec file(s): file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js [0-0] Error: TypeError: WebdriverAjax is not a function [0-0] at file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js:13:34 [0-0] at ModuleJob.run (node:internal/modules/esm/module_job:193:25) [0-0] at async Promise.all (index 0) [0-0] at async ESMLoader.import (node:internal/modules/esm/loader:533:24) [0-0] at async importModuleDynamicallyWrapper (node:internal/vm/module:438:15) [0-0] at async formattedImport (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:9:14) [0-0] at async Object.exports.requireOrImport (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:42:28) [0-0] at async Object.exports.loadFilesAsync (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:100:20) [0-0] at async MochaAdapter._loadFiles (file:///C:/Users/lbott/node-project/webdriver.io/node_modules/@wdio/mocha-framework/build/index.js:67:13) [0-0] at async MochaAdapter.init (file:///C:/Users/lbott/node-project/webdriver.io/node_modules/@wdio/mocha-framework/build/index.js:62:9) [0-0] Error: Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised. `browser` object has only `capabilities` and some flags like `isMobile`. Helper files that use other `browser` commands have to be moved to `before` hook. Spec file(s): file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js Error: TypeError: WebdriverAjax is not a function at file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js:13:34 at ModuleJob.run (node:internal/modules/esm/module_job:193:25) [0-0] FAILED in chrome - file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js
之前的Nock测试代码
describe('Test Case Name', () => { it('should intercept and modify a request with Nock', async () => { await time(1000); nock('https://jsonplaceholder.typicode.com') .get('/posts/1') .reply(200, { body: 'hello world' }); await browser.url('https://jsonplaceholder.typicode.com/posts/1'); await browser.waitUntil(() => { return browser.$('body').getText().includes('hello world'); }, { timeout: 5000, timeoutMsg: 'expected body to contain "hello world" after 5s', }); await time(5000); }); });
解决方案
1. 修复TypeError: WebdriverAjax is not a function错误
wdio-intercept-service不需要手动导入和初始化,正确做法是在WDIO配置文件中注册服务,由WDIO自动注入功能到全局browser对象:
步骤1:修改wdio.conf.js
将intercept服务添加到services数组:
export const config = { // 其他配置(端口、capabilities等) services: ['chromedriver', 'intercept'], framework: 'mocha', // 其他配置 }
步骤2:修改test1.js
删除手动初始化浏览器和WebdriverAjax的代码,使用WDIO自动提供的全局browser,同时修正afterAll中的错误变量:
let browser; afterAll(async () => { await browser.deleteSession() // 将client改为browser }); async function time(pause = 1000) { const starttime = new Date().getTime(); await browser.pause(pause); const endtime = new Date().getTime(); console.log("-------------------------------->", pause, endtime - starttime); } describe('Test Case Name', () => { it('should intercept requests', async () => { await time(1000); await browser.url('https://jsonplaceholder.typicode.com'); await browser.setupInterceptor(); await browser.expectRequest('GET', '/posts/1', 200); // 原页面无#button,改为直接触发请求的操作 await browser.url('https://jsonplaceholder.typicode.com/posts/1'); await browser.pause(1000); await browser.assertRequests(); await time(5000); }); });
2. 修复Nock无法拦截浏览器请求的问题
Nock仅能拦截Node.js环境发出的HTTP请求,浏览器的请求独立于Node.js进程,因此无法被Nock捕获。要修改浏览器请求的响应,直接使用wdio-intercept-service的mock方法:
describe('Test Case Name', () => { it('should modify request response', async () => { await browser.url('https://jsonplaceholder.typicode.com'); // 拦截目标请求并修改响应内容 const mock = await browser.mock('https://jsonplaceholder.typicode.com/posts/1', { method: 'GET' }); mock.respond({ body: 'hello world' }, { statusCode: 200 }); await browser.url('https://jsonplaceholder.typicode.com/posts/1'); await browser.waitUntil(async () => { const bodyText = await browser.$('body').getText(); return bodyText.includes('hello world'); }, { timeout: 5000, timeoutMsg: 'expected body to contain "hello world" after 5s', }); }); });
内容的提问来源于stack exchange,提问作者Luca Bottoni
相关产品推荐
相关产品推荐

