跳至主要內容

攔截服務

wdio-intercept-service 是一個第三方套件,如需更多資訊,請參閱 GitHub | npm

🕸 在 webdriver.io 中捕獲並斷言 HTTP ajax 呼叫

Tests Join the chat on Discord

這是 webdriver.io 的一個外掛程式。 如果你還不認識它,請看看,它相當酷。

雖然 selenium 和 webdriver 用於 e2e 和特別是 UI 測試,你可能想要評估用戶端程式碼所執行的 HTTP 請求(例如,當你沒有立即的 UI 回饋時,如在指標或追蹤呼叫中)。 使用 wdio-intercept-service,你可以攔截由某些使用者動作啟動的 ajax HTTP 呼叫(例如,按鈕按下等),並稍後對請求和相應的回應進行斷言。

但有一個問題:你無法攔截在頁面載入時啟動的 HTTP 呼叫(如在大多數 SPA 中),因為它需要一些設定工作,這些設定只能在頁面載入後完成(由於 selenium 的限制)。 **這表示你只能捕獲在測試內部啟動的請求。** 如果你對此沒有問題,這個外掛程式可能適合你,所以請繼續閱讀。

先決條件

  • webdriver.io v5.x 或更新版本。

注意!如果你仍然使用 webdriver.io v4,請使用此外掛程式的 v2.x 分支!

安裝

npm install wdio-intercept-service -D

使用方式

搭配 WebDriver CLI 使用

它應該像將 wdio-intercept-service 新增到你的 wdio.conf.js 一樣容易

exports.config = {
// ...
services: ['intercept']
// ...
};

你就可以開始使用。

搭配 WebDriver 獨立版使用

當使用 WebdriverIO 獨立版時,需要手動呼叫 beforebeforeTest / beforeScenario 函式。

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()
});

describe('', async () => {
... // See example usage
});

初始化後,一些相關函式會新增到你的瀏覽器命令鏈中(請參閱 API)。

快速入門

使用範例

browser.url('http://foo.bar');
browser.setupInterceptor(); // capture ajax calls
browser.expectRequest('GET', '/api/foo', 200); // expect GET request to /api/foo with 200 statusCode
browser.expectRequest('POST', '/api/foo', 400); // expect POST request to /api/foo with 400 statusCode
browser.expectRequest('GET', /\/api\/foo/, 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

取得關於請求的詳細資訊

browser.url('http://foo.bar')
browser.setupInterceptor();
browser.click('#button')
browser.pause(1000);

var request = browser.getRequest(0);
assert.equal(request.method, 'GET');
assert.equal(request.response.headers['content-length'], '42');

支援的瀏覽器

它應該適用於所有瀏覽器較新的版本。 如果它似乎不適用於你的瀏覽器,請回報問題。

API

請參閱 TypeScript 宣告檔案,了解新增到 WebdriverIO 瀏覽器物件的自訂命令的完整語法。 一般來說,任何將「options」物件作為參數的方法,都可以不用該參數呼叫,以取得預設行為。 這些「可選選項」物件後接 ?: = {},並且會針對每個方法描述推斷的預設值。

選項說明

此程式庫在發出命令時提供少量組態。 此處描述由多個方法使用的組態選項(請參閱每個方法定義以判斷特定支援)。

  • orderBy ('START' | 'END'): 此選項控制攔截器捕獲的請求的排序,當傳回給你的測試時。 為了與此程式庫的現有版本向後相容,預設排序為 'END',這對應於請求完成的時間。 如果你將 orderBy 選項設定為 'START',則請求將根據它們開始的時間排序。
  • includePending (boolean): 此選項控制是否將傳回尚未完成的請求。 為了與此程式庫的現有版本向後相容,預設值為 false,並且只會傳回已完成的請求。

browser.setupInterceptor()

捕獲瀏覽器中的 ajax 呼叫。 你必須始終呼叫設定函式,才能稍後評估請求。

browser.disableInterceptor()

防止進一步捕獲瀏覽器中的 ajax 呼叫。 所有捕獲的請求資訊都會被移除。 大多數使用者不需要停用攔截器,但如果測試執行時間特別長或超出工作階段儲存容量,則停用攔截器可能會有所幫助。

browser.excludeUrls(urlRegexes: (string | RegExp)[])

排除特定 url 的請求被記錄。 它會採用字串或規則運算式的陣列。 在寫入儲存之前,會根據每個字串或規則運算式測試請求的 url。 如果是,則不會將請求寫入儲存。 就像 disableInterceptor 一樣,如果遇到工作階段儲存超出容量的問題,這可能會有所幫助。

browser.expectRequest(method: string, url: string, statusCode: number)

對測試期間將要啟動的 ajax 請求進行預期。 可以(也應該)進行鏈式呼叫。 預期的順序應對應於發出請求的順序。

  • method (String):預期的 http 方法。 可以是 xhr.open() 接受作為第一個引數的任何內容。
  • url (String|RegExp):在請求中呼叫的確切 URL,作為字串或規則運算式來比對
  • statusCode (Number):回應的預期狀態碼

browser.getExpectations()

輔助方法。 傳回你到目前為止所做的所有預期

browser.resetExpectations()

輔助方法。 重設你到目前為止所做的所有預期

browser.assertRequests({ orderBy?: 'START' | 'END' }?: = {})

當所有預期的 ajax 請求完成時,呼叫此方法。 它會將預期與實際發出的請求進行比較,並斷言以下內容

  • 發出請求的計數
  • 請求的順序
  • 對於每個發出的請求,方法、URL 和狀態碼都應該符合
  • 選項物件預設為 { orderBy: 'END' },也就是請求完成時,以與 v4.1.10 和更早版本的行為保持一致。 當 orderBy 選項設定為 'START' 時,請求將按照頁面啟動它們的時間排序。

browser.assertExpectedRequestsOnly({ inOrder?: boolean, orderBy?: 'START' | 'END' }?: = {})

browser.assertRequests 類似,但只驗證你在 expectRequest 指令中指定的請求,而無需映射可能發生在其周圍的所有網路請求。 如果 inOrder 選項為 true(預設值),則預期會在與使用 expectRequest 設定的相同順序中找到請求。

browser.getRequest(index: number, { includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})

為了對特定請求做出更精細的斷言,您可以取得特定請求的詳細資訊。您必須提供要存取的請求的從 0 開始的索引,依照請求完成的順序(預設),或依照起始的順序(傳遞 orderBy: 'START' 選項)。

  • index (number):您要存取的請求的編號
  • options (object):設定選項
  • options.includePending (boolean):是否應返回尚未完成的請求。預設值為 false,以符合 v4.1.10 及更早版本中程式庫的行為。
  • options.orderBy ('START' | 'END'):請求應如何排序。預設值為 'END',以符合 v4.1.10 及更早版本中程式庫的行為。如果為 'START',則請求將按起始時間排序,而不是按請求完成時間排序。(由於待處理的請求尚未完成,當按 'END' 排序時,所有待處理的請求都將在所有已完成的請求之後。)

返回 request 物件

  • request.url:請求的 URL
  • request.method:使用的 HTTP 方法
  • request.body:請求中使用的有效負載/主體資料
  • request.headers:請求 HTTP 標頭,以 JS 物件表示
  • request.pending:布林旗標,表示此請求是否已完成(即具有 response 屬性)或正在處理中。
  • request.response:一個 JS 物件,僅在請求完成時存在(即 request.pending === false),其中包含有關回應的資料。
  • request.response?.headers:回應 HTTP 標頭,以 JS 物件表示
  • request.response?.body:回應主體(如果可能,將解析為 JSON)
  • request.response?.statusCode:回應狀態碼

關於 request.body 的注意事項: wdio-intercept-service 將嘗試按以下方式解析請求主體

  • 字串:僅返回字串 ('value')
  • JSON:使用 JSON.parse() 解析 JSON 物件 (({ key: value }))
  • FormData:將以 { key: [value1, value2, ...] } 格式輸出 FormData
  • ArrayBuffer:將嘗試將緩衝區轉換為字串(實驗性)
  • 其他任何內容:將對您的資料使用殘酷的 JSON.stringify()。祝您好運!

對於 fetch API,我們僅支援字串和 JSON 資料!

browser.getRequests({ includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})

以陣列形式取得所有捕獲的請求,支援與 getRequest 相同的可選選項。

返回 request 物件的陣列。

browser.hasPendingRequests()

一個實用方法,用於檢查是否有任何 HTTP 請求仍在處理中。測試可以使用此方法來確保所有請求在合理的時間內完成,或驗證對 getRequests()assertRequests() 的調用將包含所有所需的 HTTP 請求。

返回 布林值

TypeScript 支援

此外掛程式提供其自身的 TS 類型。只需將您的 tsconfig 指向類型擴展,如這裡所述

"compilerOptions": {
// ..
"types": ["node", "webdriverio", "wdio-intercept-service"]
},

執行測試

需要最新版本的 Chrome 和 Firefox 才能在本地執行測試。您可能需要更新 chromedrivergeckodriver 依賴項,以符合系統上安裝的版本。

npm test

貢獻

我樂於接受每一項貢獻。只需打開一個問題或直接提交 PR 即可。
請注意,此攔截器程式庫是為了與 Internet Explorer 等舊版瀏覽器一起使用而編寫的。因此,lib/interceptor.js 中使用的任何程式碼都必須至少可由 Internet Explorer 的 JavaScript 執行階段解析。

許可證

MIT

歡迎!我能幫上什麼忙?

WebdriverIO AI Copilot