版本號 ^11.2.0#
前提準備與說明#
- 安裝
cypress
的客戶端軟體作為執行環境. - 在專案根目錄下安裝
cypress
- 配置啟動腳本
{
"e2e": "cypress open", // 打開客戶端手動選擇性執行
"test": "cypress run && cypress run --component" // 在命令行裡,執行所有的測試用例
}
Tip
cypress 的 api ,都是以同步的寫法,來異步執行的。比如 async await 那樣,它不需要顯示聲明,直接調用。比如在獲取元素的時候,它會有相應的等待時間來異步處理。
使用場景#
前往某個頁面#
cy.visit(url);
獲取元素#
選擇器匹配#
// 這種匹配方式,可以參考 querySelector 的行為
cy.get(selector);
內容匹配#
// 內容匹配,下列語句將會匹配包含了 hello 文本的元素
cy.contain('hello');
事件調用#
基本事件#
// 以調用點擊事件為例,其它事件也可以同樣如此
cy.get(selector).click();
複雜事件#
// 這種方式,除了觸發基本事件,還可以觸發 mousedown、mouseup 這類的事件,來模擬複雜的用戶操作
cy.get(selector).trigger(eventName);
內容校驗#
// 該語法是在判斷選中的元素,應該有 hello 的內容
cy.get(selector).should('have.value', 'hello');
// 判斷元素的 top 值,是否為 10 px;
cy.get(selector).should('have.css', 'top').and('eq', '10px');
結合 ts 的語法提示,should 的第一個參數,還有很多其它的行為來進行校驗
模擬按鍵#
// 按住 ctrl
cy.get('body').type('{ctrl}', { release: false });
// 抬起 ctrl
cy.get('body').type('{ctrl}', { release: true });
接口請求#
獲取接口的調用結果#
// 開始監聽某個接口
cy.intercept({
method: 'GET',
// 比如監聽 /api/login?account=xxx,寫法為:/api/login*
url: `接口的path部分`,
}).as('test');
// 此處注意。在監聽的代碼開始執行時,後面的請求行為如果不是該接口,就會報錯。也就是說,在開始監聽後,需要確保接下來的請求一定是這個監聽的請求。所以不能一開始就去監聽。推薦做法就是在監聽後,確定後續行為馬上可以監聽到該接口來處理,比如在這裡觸發某個按鈕的點擊行為,來調用接口
// 獲取接口的請求結果
cy.wait('@test')
.its('response.body')
.then(data => {
cy.log(JSON.stringify(data));
});
根據上述描述,可以封裝如下方法使用
export const watchRequest = <T>(url: string, trigger: () => void, callback: (data: T) => void) => {
cy.intercept({
method: 'GET',
url: `${url}*`,
}).as(url);
trigger();
cy.wait(`@${url}`)
.its('response.body')
.then(data) => {
callback(data);
});
};
是否正常訪問某個頁面#
在上述場景情況下,做如下調整,即可大致確認某個頁面是否屬於正常訪問。
/**
* 某個頁面可以正常訪問
* @param url 頁面地址
* @param requestCount 判定頁面發起了多少個請求都是正常的
*/
export const normalVisit = (url: string, requestCount = 30) => {
cy.intercept({
url: '*',
}).as('apiCheck')
cy.visit(url);
Array(requestCount).fill('').forEach(() => {
cy.wait('@apiCheck').then((interception) => {
expect(Boolean(interception.response)).equal(true);
assert.isNotNull(interception.response!.body);
expect(interception.response!.statusCode).to.be.oneOf([200, 304])
});
});
}
修改請求參數#
// 修改 get 請求的參數
cy.intercept('/api/test*', (req) => {
const request = JSON.parse(req.query as string);
req.query.account = 2;
});
注意:修改的請求參數,在控制台裡面看請求時,參數沒有發生顯示變化,實際上已經改變了。
強制等待#
cy.wait(1000); // 等待1s
自定義指令#
元素是否存在#
声明类型#
/// <reference types="cypress" />
/// <reference types="cypress-wait-until" />
declare namespace Cypress {
interface Chainable<Subject> {
/**
* 檢查元素是否存在
*
* @param selector 選擇器
* @return Chainable<Subject>
*/
isElementExist(selector: string): Chainable<Subject>;
}
}
定義指令#
/// <reference types="cypress" />
/// <reference types="cypress-wait-until" />
require("cypress-wait-until");
export function isElementExist(selector: string) {
return cy
.window()
.then(($window) => $window.document.querySelector(selector));
}
Cypress.Commands.add("isElementExist", isElementExist);
使用指令#
cy.isElementExist(".shoe-id").then((value) => {
if (value) {
// ...
} else {
// ...
}
}
測試數據#
cypress/fixtures
目錄下的 json
文件可以當作測試數據來用,例如: user.json
:
{
"username": "hello world"
}
那麼在使用的時候就可以這麼獲取
cy.fixture('user').then(res => {
console.log(res.username);
})