Simulate human maneuvers across devices on gesture-heavy web apps.
For usage as an automated testing utility.
Abstracts idiosyncrasies across various pointer devices;
e.g: "Apple Pencil", "touchscreen", "mouse" etc...
using an ergonomic and uniform API.
Note
LLM agents/assistants must read the skill.
Import in your target app's DevTools/Web Inspector/Console:
const{ DragMotion }=awaitimport('https://theprofs.github.io/pointerdriver/pointerdriver.js')awaitnewDragMotion(document.querySelector('#el'),[[30,50,0],[60,80,16],]).perform()Run a local server instead of the CDN:
npx github:TheProfs/pointerdriverconst{ DragMotion }=awaitimport('http://127.0.0.1:5619/pointerdriver.js')awaitnewDragMotion(document.querySelector('#el'),[[30,50,0],[60,80,16],]).perform()If the target page is HTTPS, the HTTP import is blocked as mixed content.
Use a Cloudflare Tunnel to wrap it in HTTPS:
cloudflared tunnel --url http://127.0.0.1:5619You can also import and use it to drive automated tests:
npm i github:TheProfs/pointerdriverimport{test,before,after}from'node:test'import{pointerdriver}from'pointerdriver'importpuppeteerfrom'puppeteer'letserver,browser,pagebefore(async()=>{server=pointerdriver()browser=awaitpuppeteer.launch({headless: false})page=awaitbrowser.newPage()awaitpage.goto('http://localhost:3000')})after(()=>(server.close(),browser.close()))test('#mousedrag',asynct=>{t.beforeEach(()=>page.evaluate(async()=>{const{ DragMotion }=awaitimport('http://127.0.0.1:5619/pointerdriver.js')awaitnewDragMotion(document.querySelector('#el'),[[30,50,0],[60,80,16],]).perform()}))awaitt.test('creates a PathItem',asynct=>{// assertions...})awaitt.test('closely following the cursor path',asynct=>{// assertions...})awaitt.test('with selected attributes',asynct=>{// assertions...})})pointerdriver(port) starts the module server.
Defaults to port 5619.
A Motion encodes the manner in which the actual device it represents,
translates inputs into events and constucts a near-identical
event stream and dispatches it to the passed element:
"swipe across an element using 1 finger, and draw a square":
awaitnewDragMotion(document.querySelector('#board'),[[30,50,0],[60,80,16],[120,140,32],]).perform()"put 2 fingers down and twist
45 degreesat pivot:x: 100, y: 100,
then lift up":
awaitnewTwistMotion(document.querySelector('#board'),45,{x: 100,y: 100}).perform()The passed element should be the container of the
actual element you're targeting.
For example:
<divid="board"><canvas></canvas></div>awaitnewDragMotion(document.querySelector('#board'),[[30,50,0],[60,80,16],]).perform()There are 2 types of Motions;
- Drawing motions
- Gesture motions
Single-pointer interactions, commonly used for drawing on a surface.
DragMotion— mouseGlideMotion— touchStrokeMotion— pen
All three take (el, points):
pointsis[[x, y, ms], ...]msis monotonic and>= 0
awaitnewDragMotion(document.querySelector('#el'),[[30,50,0],[60,80,16],]).perform()Multi-pointer interactions, commonly used for navigation (zoom, pan etc.)
Two-finger pinch together or apart.
scale— target scale factorx,y— gesture centerdistance— initial finger gap in px (default100)steps— interpolation frames (default20)
awaitnewPinchMotion(document.querySelector('#el'),2,{x: 60,y: 80}).perform()Two-finger rotation around a center point.
degrees— rotation angle (default45)x,y— gesture centerradius— finger distance from center (default80)steps— interpolation frames (default20)
awaitnewTwistMotion(document.querySelector('#el'),45,{x: 60,y: 80}).perform()Two-finger parallel drag.
distance— travel distance in pxx,y— gesture centerangle— direction in degrees (default0)separation— gap between fingers in px (default40)steps— interpolation frames (default20)
awaitnewSwipeMotion(document.querySelector('#el'),200,{x: 60,y: 80}).perform()Motions are extensible, allowing support for more
devices and interaction types.
Motion (base)
├── PathMotion (drawing)
│ ├── DragMotion
│ ├── GlideMotion
│ └── StrokeMotion
└── GestureMotion (gestures)
├── PinchMotion
├── TwistMotion
└── SwipeMotion
- Create
motions/<name>/index.js - Extend
PathMotionorGestureMotion - Export from
motions/index.js
Note
Co-locate tests in motions/<name>/test/.
Pushes to developmentbundle and deploy to GitHub Pages:
https://theprofs.github.io/pointerdriver/pointerdriver.js
npm test