觸控事件(舊版)
簡介
處理舊版 觸控事件 以回應滑動、縮放和點擊等手勢的網頁應用程式,可以透過手動分派 TouchEvent 到頁面來進行測試。以下範例說明如何使用 locator.dispatchEvent()
並將 Touch 點作為引數傳遞。
請注意,locator.dispatchEvent()
不會設定 Event.isTrusted
屬性。如果您的網頁依賴此屬性,請確保在測試期間停用 isTrusted
檢查。
模擬平移手勢
在以下範例中,我們模擬預期會移動地圖的平移手勢。受測試的應用程式只使用觸控點的 clientX/clientY
座標,因此我們只初始化這些項目。在更複雜的情況下,如果您的應用程式需要的話,您可能還需要設定 pageX/pageY/screenX/screenY
。
import { test, expect, devices, type Locator } from '@playwright/test';
test.use({ ...devices['Pixel 7'] });
async function pan(locator: Locator, deltaX?: number, deltaY?: number, steps?: number) {
const { centerX, centerY } = await locator.evaluate((target: HTMLElement) => {
const bounds = target.getBoundingClientRect();
const centerX = bounds.left + bounds.width / 2;
const centerY = bounds.top + bounds.height / 2;
return { centerX, centerY };
});
// 僅提供 clientX 和 clientY,因為應用程式只關心這些座標。
const touches = [{
identifier: 0,
clientX: centerX,
clientY: centerY,
}];
await locator.dispatchEvent('touchstart',
{ touches, changedTouches: touches, targetTouches: touches });
steps = steps ?? 5;
deltaX = deltaX ?? 0;
deltaY = deltaY ?? 0;
for (let i = 1; i <= steps; i++) {
const touches = [{
identifier: 0,
clientX: centerX + deltaX * i / steps,
clientY: centerY + deltaY * i / steps,
}];
await locator.dispatchEvent('touchmove',
{ touches, changedTouches: touches, targetTouches: touches });
}
await locator.dispatchEvent('touchend');
}
test(`平移手勢來移動地圖`, async ({ page }) => {
await page.goto('https://www.google.com/maps/place/@37.4117722,-122.0713234,15z',
{ waitUntil: 'commit' });
await page.getByRole('button', { name: 'Keep using web' }).click();
await expect(page.getByRole('button', { name: 'Keep using web' })).not.toBeVisible();
// 取得地圖元素。
const met = page.locator('[data-test-id="met"]');
for (let i = 0; i < 5; i++)
await pan(met, 200, 100);
// 確保地圖已被移動。
await expect(met).toHaveScreenshot();
});
模擬縮放手勢
在以下範例中,我們模擬縮放手勢,也就是兩個觸控點彼此靠近的動作。這預期會縮小地圖。受測試的應用程式只使用觸控點的 clientX/clientY
座標,因此我們只初始化這些項目。在更複雜的情況下,如果您的應用程式需要的話,您可能還需要設定 pageX/pageY/screenX/screenY
。
import { test, expect, devices, type Locator } from '@playwright/test';
test.use({ ...devices['Pixel 7'] });
async function pinch(locator: Locator,
arg: { deltaX?: number, deltaY?: number, steps?: number, direction?: 'in' | 'out' }) {
const { centerX, centerY } = await locator.evaluate((target: HTMLElement) => {
const bounds = target.getBoundingClientRect();
const centerX = bounds.left + bounds.width / 2;
const centerY = bounds.top + bounds.height / 2;
return { centerX, centerY };
});
const deltaX = arg.deltaX ?? 50;
const steps = arg.steps ?? 5;
const stepDeltaX = deltaX / (steps + 1);
// 兩個與元素中心等距的觸控點。
const touches = [
{
identifier: 0,
clientX: centerX - (arg.direction === 'in' ? deltaX : stepDeltaX),
clientY: centerY,
},
{
identifier: 1,
clientX: centerX + (arg.direction === 'in' ? deltaX : stepDeltaX),
clientY: centerY,
},
];
await locator.dispatchEvent('touchstart',
{ touches, changedTouches: touches, targetTouches: touches });
// 將觸控點彼此靠近或遠離。
for (let i = 1; i <= steps; i++) {
const offset = (arg.direction === 'in' ? (deltaX - i * stepDeltaX) : (stepDeltaX * (i + 1)));
const touches = [
{
identifier: 0,
clientX: centerX - offset,
clientY: centerY,
},
{
identifier: 0,
clientX: centerX + offset,
clientY: centerY,
},
];
await locator.dispatchEvent('touchmove',
{ touches, changedTouches: touches, targetTouches: touches });
}
await locator.dispatchEvent('touchend', { touches: [], changedTouches: [], targetTouches: [] });
}
test(`縮放手勢來縮小地圖`, async ({ page }) => {
await page.goto('https://www.google.com/maps/place/@37.4117722,-122.0713234,15z',
{ waitUntil: 'commit' });
await page.getByRole('button', { name: 'Keep using web' }).click();
await expect(page.getByRole('button', { name: 'Keep using web' })).not.toBeVisible();
// 取得地圖元素。
const met = page.locator('[data-test-id="met"]');
for (let i = 0; i < 5; i++)
await pinch(met, { deltaX: 40, direction: 'in' });
// 確保地圖已被縮小。
await expect(met).toHaveScreenshot();
});