Cypress
是一個非常流行的測試工具,然而實際使用過程中發現一些問題,這裡做些記錄。
在 Cypress
下 click
是非常常用的指令,然而在一些特殊場景下 click
並不能如想象中那般正常工作。
比如現在有一個彈窗,我們需要測試在點選遮罩層時是否可以正常關閉彈窗。
測試程式碼比較簡單:
/// <reference types="cypress" />
context('Actions', () => {
beforeEach(() => {
cy.visit('http://localhost:3300/Modal');
});
it('Override', () => {
cy.get('.mantine-Button-root').click();
cy.get('.mantine-Modal-root').should('exist');
cy.get('.mantine-Modal-overlay').click();
});
});
然後執行 Cypress
,發現一切如想象中那般簡單,很順利就通過了。
然而當往 Model
中填充了一些內容後,卻發現突然這裡就報錯了。
當然,報錯是沒問題,遮罩層確實被內容遮擋了。問題是剛剛明明也是一樣被遮擋,為何就不報錯,只是因為內容多了一點就報錯,這就很不合適了。
檢視檔案會發現 click
還支援座標或位置引數。
然而,並沒有什麼用,也就是說這個點選位置無關,應該是和 Cypress
判斷元素遮擋有關係,看起來 Cypress
遮擋計算還需要優化。
排查原始碼可以發現 Cypress
的 click
會經過一些判定:
if (force !== true) {
// now that we know our element isn't animating its time
// to figure out if it's being covered by another element.
// this calculation is relative from the viewport so we
// only care about fromElViewport coords
$elAtCoords =
options.ensure.notCovered && ensureElIsNotCovered(cy, win, $el, coords.fromElViewport, options, _log, onScroll);
Cypress.ensure.isNotHiddenByAncestors($el, name, _log);
}
其中比較重要的引數是 coords.fromElViewport
,其數值長這樣:
{
"top": 0,
"left": 0,
"right": 1000,
"bottom": 660,
"topCenter": 330,
"leftCenter": 500,
"x": 500,
"y": 330
}
注意其中的 x
和 y
,可以認為就是中心點的座標。
然後 Cypress
會使用該座標獲取該位置最頂層的元素:
const getElementAtPointFromViewport = function (fromElViewport) {
// get the element at point from the viewport based
// on the desired x/y normalized coordinations
let elAtCoords;
elAtCoords = $dom.getElementAtPointFromViewport(win.document, fromElViewport.x, fromElViewport.y);
if (elAtCoords) {
$elAtCoords = $dom.wrap(elAtCoords);
return $elAtCoords;
}
return null;
};
const ensureDescendents = function (fromElViewport) {
// figure out the deepest element we are about to interact
// with at these coordinates
$elAtCoords = getElementAtPointFromViewport(fromElViewport);
debug('elAtCoords', $elAtCoords);
debug('el has pointer-events none?');
ensureElDoesNotHaveCSS($el, 'pointer-events', 'none', name, log);
debug('is descendent of elAtCoords?');
ensureIsDescendent($el, $elAtCoords, name, log);
return $elAtCoords;
};
可以發現這裡直接使用 x
和 y
去獲取元素,然後和當前目標元素去做了對比。
這也就是為什麼 click
有時候可以點,有時候不可以的原因了,簡單說就是中心點被遮了就可以點,沒被遮就不可以點,還真是簡單粗暴