WebDriver/Selenium 2 Node.js client for browser automation and testing
—
Advanced touch gesture support using TouchAction, MultiAction, and W3C Actions builders for mobile and touch-enabled devices.
Build and execute single touch gesture sequences.
/**
* TouchAction constructor
* @param driver - WebDriver instance
*/
class TouchAction {
constructor(driver: Webdriver);
/**
* Add tap gesture
* @param opts - Tap options
*/
tap(opts?: {element?: Element, x?: number, y?: number, count?: number}): TouchAction;
/**
* Add press gesture
* @param opts - Press options
*/
press(opts?: {element?: Element, x?: number, y?: number}): TouchAction;
/**
* Add long press gesture
* @param opts - Long press options
*/
longPress(opts?: {element?: Element, x?: number, y?: number}): TouchAction;
/**
* Add move gesture
* @param opts - Move options
*/
moveTo(opts?: {element?: Element, x?: number, y?: number}): TouchAction;
/**
* Add release gesture
*/
release(): TouchAction;
/**
* Add wait/pause
* @param opts - Wait options or duration in milliseconds
*/
wait(opts: {ms: number} | number): TouchAction;
/**
* Cancel all gestures
*/
cancel(): TouchAction;
/**
* Execute the touch action sequence
* @param cb - Callback receiving (err)
*/
perform(cb?: callback): void;
}Usage Examples:
const wd = require('wd');
// Simple tap gesture
const touchAction = new wd.TouchAction(browser);
touchAction
.tap({element: targetElement})
.perform(function(err) {
console.log('Tap gesture completed');
});
// Tap at coordinates
touchAction
.tap({x: 100, y: 200})
.perform();
// Long press gesture
touchAction
.longPress({element: menuButton})
.wait(1000)
.release()
.perform(function(err) {
console.log('Long press menu opened');
});
// Drag and drop gesture
touchAction
.press({element: draggableItem})
.wait(500)
.moveTo({element: dropZone})
.release()
.perform(function(err) {
console.log('Item dragged and dropped');
});
// Swipe gesture
touchAction
.press({x: 300, y: 400})
.wait(100)
.moveTo({x: 300, y: 100}) // Swipe up
.release()
.perform(function(err) {
console.log('Swipe up completed');
});Execute multiple TouchAction sequences simultaneously.
/**
* MultiAction constructor
* @param browserOrElement - WebDriver instance or Element
*/
class MultiAction {
constructor(browserOrElement: Webdriver | Element);
/**
* Add TouchAction to the multi-action
* @param touchActions - One or more TouchAction instances
*/
add(...touchActions: TouchAction[]): MultiAction;
/**
* Cancel all actions
*/
cancel(): MultiAction;
/**
* Execute all touch actions simultaneously
* @param cb - Callback receiving (err)
*/
perform(cb?: callback): void;
}Usage Examples:
// Two-finger pinch gesture
const finger1 = new wd.TouchAction(browser);
finger1.press({x: 200, y: 200}).wait(100).moveTo({x: 150, y: 150}).release();
const finger2 = new wd.TouchAction(browser);
finger2.press({x: 300, y: 300}).wait(100).moveTo({x: 350, y: 350}).release();
const pinchOut = new wd.MultiAction(browser);
pinchOut.add(finger1, finger2).perform(function(err) {
console.log('Pinch out gesture completed');
});
// Two-finger zoom in
const zoom1 = new wd.TouchAction(browser);
zoom1.press({x: 150, y: 150}).wait(100).moveTo({x: 100, y: 100}).release();
const zoom2 = new wd.TouchAction(browser);
zoom2.press({x: 350, y: 350}).wait(100).moveTo({x: 400, y: 400}).release();
const zoomIn = new wd.MultiAction(browser);
zoomIn.add(zoom1, zoom2).perform(function(err) {
console.log('Zoom in gesture completed');
});
// Multi-finger tap
const tap1 = new wd.TouchAction(browser).tap({x: 100, y: 200});
const tap2 = new wd.TouchAction(browser).tap({x: 200, y: 200});
const tap3 = new wd.TouchAction(browser).tap({x: 300, y: 200});
const multiTap = new wd.MultiAction(browser);
multiTap.add(tap1, tap2, tap3).perform(function(err) {
console.log('Multi-finger tap completed');
});Modern W3C Actions API for complex input sequences.
/**
* W3C Actions constructor
* @param driver - WebDriver instance
*/
class W3CActions {
constructor(driver: Webdriver);
/**
* Add input device to the action sequence
* @param inputSource - InputDevice instance
*/
addInputDevice(inputSource: InputDevice): W3CActions;
/**
* Add touch input device
*/
addTouchInput(): InputDevice;
/**
* Add mouse input device
*/
addMouseInput(): InputDevice;
/**
* Add pen input device
*/
addPenInput(): InputDevice;
/**
* Add keyboard input device
*/
addKeyInput(): InputDevice;
/**
* Execute the W3C actions
* @param cb - Callback receiving (err)
*/
perform(cb?: callback): void;
}
/**
* InputDevice for W3C Actions
*/
class InputDevice {
constructor(opts?: {type?: string, id?: string, pointerType?: string, parameters?: object});
/**
* Pause input source
* @param opts - Pause options or duration
*/
pause(opts: {duration: number} | number): InputDevice;
// Key input methods (for type='key')
keyDown(opts: {value: string} | string): InputDevice;
keyUp(opts: {value: string} | string): InputDevice;
// Pointer input methods (for type='pointer')
pointerDown(opts?: {button?: number}): InputDevice;
pointerUp(opts?: {button?: number}): InputDevice;
pointerMove(opts: {element?: Element, duration?: number, origin?: string, x?: number, y?: number}): InputDevice;
pointerCancel(opts?: {button?: number}): InputDevice;
}Usage Examples:
// Basic W3C touch gesture
const w3cActions = new wd.W3CActions(browser);
const finger = w3cActions.addTouchInput();
finger
.pointerMove({x: 100, y: 200})
.pointerDown()
.pause(100)
.pointerMove({x: 300, y: 200})
.pointerUp();
w3cActions.perform(function(err) {
console.log('W3C touch gesture completed');
});
// Multi-touch W3C gesture
const w3cMultiTouch = new wd.W3CActions(browser);
const finger1 = w3cMultiTouch.addTouchInput();
const finger2 = w3cMultiTouch.addTouchInput();
// Pinch gesture
finger1
.pointerMove({x: 200, y: 200})
.pointerDown()
.pause(100)
.pointerMove({x: 150, y: 150})
.pointerUp();
finger2
.pointerMove({x: 300, y: 300})
.pointerDown()
.pause(100)
.pointerMove({x: 350, y: 350})
.pointerUp();
w3cMultiTouch.perform(function(err) {
console.log('W3C pinch gesture completed');
});
// Combined input types
const mixedActions = new wd.W3CActions(browser);
const touch = mixedActions.addTouchInput();
const keyboard = mixedActions.addKeyInput();
// Touch and type simultaneously
touch.pointerMove({x: 100, y: 100}).pointerDown();
keyboard.keyDown('a').keyUp('a');
touch.pointerUp();
mixedActions.perform(function(err) {
console.log('Mixed input actions completed');
});Common gesture patterns and helper functions.
Usage Examples:
// Swipe helper functions
function swipeUp(element, distance = 100) {
const touchAction = new wd.TouchAction(browser);
return touchAction
.press({element: element})
.wait(100)
.moveTo({element: element, x: 0, y: -distance})
.release()
.perform();
}
function swipeDown(element, distance = 100) {
const touchAction = new wd.TouchAction(browser);
return touchAction
.press({element: element})
.wait(100)
.moveTo({element: element, x: 0, y: distance})
.release()
.perform();
}
function swipeLeft(element, distance = 100) {
const touchAction = new wd.TouchAction(browser);
return touchAction
.press({element: element})
.wait(100)
.moveTo({element: element, x: -distance, y: 0})
.release()
.perform();
}
function swipeRight(element, distance = 100) {
const touchAction = new wd.TouchAction(browser);
return touchAction
.press({element: element})
.wait(100)
.moveTo({element: element, x: distance, y: 0})
.release()
.perform();
}
// Usage of swipe helpers
browser.elementByCss('.swipeable-area', function(err, area) {
swipeUp(area, 200); // Swipe up 200 pixels
});
// Pinch zoom helper
function pinchZoom(centerX, centerY, scale = 1.5) {
const distance = 100;
const scaledDistance = distance * scale;
const finger1 = new wd.TouchAction(browser);
finger1
.press({x: centerX - distance/2, y: centerY})
.wait(100)
.moveTo({x: centerX - scaledDistance/2, y: centerY})
.release();
const finger2 = new wd.TouchAction(browser);
finger2
.press({x: centerX + distance/2, y: centerY})
.wait(100)
.moveTo({x: centerX + scaledDistance/2, y: centerY})
.release();
const multiAction = new wd.MultiAction(browser);
return multiAction.add(finger1, finger2).perform();
}
// Usage of pinch zoom
pinchZoom(200, 300, 2.0); // Zoom 2x at coordinates (200, 300)
// Scroll helper using touch
function touchScroll(element, direction, distance) {
const directions = {
up: {x: 0, y: -distance},
down: {x: 0, y: distance},
left: {x: -distance, y: 0},
right: {x: distance, y: 0}
};
const offset = directions[direction] || directions.down;
const touchAction = new wd.TouchAction(browser);
return touchAction
.press({element: element})
.wait(200)
.moveTo({element: element, x: offset.x, y: offset.y})
.release()
.perform();
}
// Usage of touch scroll
browser.elementByCss('.scrollable-list', function(err, list) {
touchScroll(list, 'down', 300); // Scroll down 300 pixels
});
// Double tap helper
function doubleTap(element, delay = 100) {
const touchAction = new wd.TouchAction(browser);
return touchAction
.tap({element: element})
.wait(delay)
.tap({element: element})
.perform();
}
// Custom gesture builder
class GestureBuilder {
constructor(browser) {
this.browser = browser;
}
createSwipe(startX, startY, endX, endY, duration = 1000) {
const touchAction = new wd.TouchAction(this.browser);
return touchAction
.press({x: startX, y: startY})
.wait(100)
.moveTo({x: endX, y: endY})
.release();
}
createTap(x, y, count = 1) {
const touchAction = new wd.TouchAction(this.browser);
let action = touchAction;
for (let i = 0; i < count; i++) {
action = action.tap({x: x, y: y});
if (i < count - 1) {
action = action.wait(100);
}
}
return action;
}
createPinch(centerX, centerY, startDistance, endDistance) {
const finger1 = new wd.TouchAction(this.browser);
finger1
.press({x: centerX - startDistance/2, y: centerY})
.wait(100)
.moveTo({x: centerX - endDistance/2, y: centerY})
.release();
const finger2 = new wd.TouchAction(this.browser);
finger2
.press({x: centerX + startDistance/2, y: centerY})
.wait(100)
.moveTo({x: centerX + endDistance/2, y: centerY})
.release();
return new wd.MultiAction(this.browser).add(finger1, finger2);
}
}
// Usage of gesture builder
const gestureBuilder = new GestureBuilder(browser);
// Create and execute custom gestures
gestureBuilder.createSwipe(100, 300, 400, 300).perform(); // Horizontal swipe
gestureBuilder.createTap(200, 200, 3).perform(); // Triple tap
gestureBuilder.createPinch(250, 400, 50, 150).perform(); // Pinch outBest practices for efficient touch gesture automation.
Usage Examples:
// Batch gestures for better performance
const gestures = [];
// Create multiple gestures
for (let i = 0; i < 5; i++) {
const touchAction = new wd.TouchAction(browser);
touchAction.tap({x: 100 + i * 50, y: 200});
gestures.push(touchAction);
}
// Execute gestures in sequence
async function executeGestures(gestures) {
for (const gesture of gestures) {
await new Promise((resolve, reject) => {
gesture.perform(function(err) {
if (err) reject(err);
else resolve();
});
});
}
}
executeGestures(gestures).then(() => {
console.log('All gestures completed');
});
// Optimize gesture timing
function createOptimizedSwipe(element, direction) {
const touchAction = new wd.TouchAction(browser);
// Shorter waits for faster execution
return touchAction
.press({element: element})
.wait(50) // Reduced from 100ms
.moveTo({element: element, x: direction.x, y: direction.y})
.release();
}
// Error handling for gestures
function safeGesture(gestureFunction, retries = 3) {
return new Promise((resolve, reject) => {
let attempt = 0;
function tryGesture() {
attempt++;
gestureFunction().perform(function(err) {
if (err && attempt < retries) {
console.log(`Gesture attempt ${attempt} failed, retrying...`);
setTimeout(tryGesture, 1000);
} else if (err) {
reject(err);
} else {
resolve();
}
});
}
tryGesture();
});
}
// Usage of safe gesture
const swipeGesture = () => new wd.TouchAction(browser)
.press({x: 100, y: 200})
.moveTo({x: 300, y: 200})
.release();
safeGesture(swipeGesture, 3).then(() => {
console.log('Gesture completed successfully');
}).catch(err => {
console.error('Gesture failed after retries:', err);
});Install with Tessl CLI
npx tessl i tessl/npm-wd