UNPKG

@ionic/core

Version:
98 lines (97 loc) 5.1 kB
/*! * (C) Ionic http://ionicframework.com - MIT License */ /** * The drag gesture will not operate as expected when the element is dragged outside of the viewport because the Mouse class does not fire events outside of the viewport. * * For example, if the mouse is moved outside of the viewport, then the `mouseup` event will not fire. * * See https://playwright.dev/docs/api/class-mouse#mouse-move for more information. */ export const dragElementBy = async (el, page, dragByX = 0, dragByY = 0, startXCoord, startYCoord, releaseDrag = true) => { const boundingBox = await el.boundingBox(); if (!boundingBox) { throw new Error('Cannot get a bounding box for an element that is not visible. See https://playwright.dev/docs/api/class-locator#locator-bounding-box for more information'); } const startX = startXCoord === undefined ? boundingBox.x + boundingBox.width / 2 : startXCoord; const startY = startYCoord === undefined ? boundingBox.y + boundingBox.height / 2 : startYCoord; // Navigate to the start position. await page.mouse.move(startX, startY); await page.mouse.down(); // Drag the element. await moveElement(page, startX, startY, dragByX, dragByY); if (releaseDrag) { await page.mouse.up(); } }; /** * Drags an element by the given amount of pixels on the Y axis. * @param el The element to drag. * @param page The E2E Page object. * @param dragByY The amount of pixels to drag the element by. * @param startYCoord The Y coordinate to start the drag gesture at. Defaults to the center of the element. */ export const dragElementByYAxis = async (el, page, dragByY, startYCoord) => { const boundingBox = await el.boundingBox(); if (!boundingBox) { throw new Error('Cannot get a bounding box for an element that is not visible. See https://playwright.dev/docs/api/class-locator#locator-bounding-box for more information'); } const startX = boundingBox.x + boundingBox.width / 2; const startY = startYCoord === undefined ? boundingBox.y + boundingBox.height / 2 : startYCoord; // Navigate to the start position. await page.mouse.move(startX, startY); await page.mouse.down(); // Drag the element. await moveElement(page, startX, startY, 0, dragByY); await page.mouse.up(); }; const validateDragByX = (startX, dragByX, viewportWidth) => { const endX = startX + dragByX; // The element is being dragged past the right of the viewport. if (endX > viewportWidth) { const recommendedDragByX = viewportWidth - startX - 5; throw new Error(`The element is being dragged past the right of the viewport. Update the dragByX value to prevent going out of bounds. A recommended value is ${recommendedDragByX}.`); } // The element is being dragged past the left of the viewport. if (endX < 0) { const recommendedDragByX = startX - 5; throw new Error(`The element is being dragged past the left of the viewport. Update the dragByX value to prevent going out of bounds. A recommended value is ${recommendedDragByX}.`); } }; const validateDragByY = (startY, dragByY, viewportHeight) => { const endY = startY + dragByY; // The element is being dragged past the bottom of the viewport. if (endY > viewportHeight) { const recommendedDragByY = viewportHeight - startY - 5; throw new Error(`The element is being dragged past the bottom of the viewport. Update the dragByY value to prevent going out of bounds. A recommended value is ${recommendedDragByY}.`); } // The element is being dragged past the top of the viewport. if (endY < 0) { const recommendedDragByY = startY - 5; throw new Error(`The element is being dragged past the top of the viewport. Update the dragByY value to prevent going out of bounds. A recommended value is ${recommendedDragByY}.`); } }; const moveElement = async (page, startX, startY, dragByX = 0, dragByY = 0) => { const steps = 10; const browser = page.context().browser().browserType().name(); const viewport = page.viewportSize(); if (viewport === null) { throw new Error('Cannot get viewport size. See https://playwright.dev/docs/api/class-page#page-viewport-size for more information'); } validateDragByX(startX, dragByX, viewport.width); validateDragByY(startY, dragByY, viewport.height); const endX = startX + dragByX; const endY = startY + dragByY; // Drag the element. for (let i = 1; i <= steps; i++) { const middleX = startX + (endX - startX) * (i / steps); const middleY = startY + (endY - startY) * (i / steps); await page.mouse.move(middleX, middleY); // Safari needs to wait for a repaint to occur before moving the mouse again. if (browser === 'webkit' && i % 2 === 0) { // Repainting every 2 steps is enough to keep the drag gesture smooth. // Anything past 4 steps will cause the drag gesture to be flaky. await page.evaluate(() => new Promise(requestAnimationFrame)); } } };