攔截服務
🕸 在 webdriver.io 中捕獲並斷言 HTTP ajax 呼叫
這是 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 獨立版時,需要手動呼叫 before
和 beforeTest
/ 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
:請求的 URLrequest.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 才能在本地執行測試。您可能需要更新 chromedriver
和 geckodriver
依賴項,以符合系統上安裝的版本。
npm test
貢獻
我樂於接受每一項貢獻。只需打開一個問題或直接提交 PR 即可。
請注意,此攔截器程式庫是為了與 Internet Explorer 等舊版瀏覽器一起使用而編寫的。因此,lib/interceptor.js
中使用的任何程式碼都必須至少可由 Internet Explorer 的 JavaScript 執行階段解析。
許可證
MIT