Created
November 13, 2017 16:00
-
-
Save dukhanov/a348aee18ff976cc4a93d3f4fddaf180 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ENDPOINTS = { | |
ACTIONS: '/session/:sessionId/actions', | |
} | |
const ActionType = { | |
KEY_DOWN: 'keyDown', | |
KEY_UP: 'keyUp', | |
PAUSE: 'pause', | |
POINTER_DOWN: 'pointerDown', | |
POINTER_UP: 'pointerUp', | |
POINTER_MOVE: 'pointerMove', | |
POINTER_CANCEL: 'pointerCancel', | |
} | |
const Button = { | |
LEFT: 0, | |
MIDDLE: 1, | |
RIGHT: 2, | |
} | |
const Origin = { | |
/** Compute offsets relative to the pointer's current position. */ | |
POINTER: 'pointer', | |
/** Compute offsets relative to the viewport. */ | |
VIEWPORT: 'viewport', | |
} | |
const ELEMENT_ID_REGEXP = /(^([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$)/g | |
export const Key = { | |
NULL: '\uE000', | |
CANCEL: '\uE001', // ^break | |
HELP: '\uE002', | |
BACK_SPACE: '\uE003', | |
TAB: '\uE004', | |
CLEAR: '\uE005', | |
RETURN: '\uE006', | |
ENTER: '\uE007', | |
SHIFT: '\uE008', | |
CONTROL: '\uE009', | |
ALT: '\uE00A', | |
PAUSE: '\uE00B', | |
ESCAPE: '\uE00C', | |
SPACE: '\uE00D', | |
PAGE_UP: '\uE00E', | |
PAGE_DOWN: '\uE00F', | |
END: '\uE010', | |
HOME: '\uE011', | |
ARROW_LEFT: '\uE012', | |
LEFT: '\uE012', | |
ARROW_UP: '\uE013', | |
UP: '\uE013', | |
ARROW_RIGHT: '\uE014', | |
RIGHT: '\uE014', | |
ARROW_DOWN: '\uE015', | |
DOWN: '\uE015', | |
INSERT: '\uE016', | |
DELETE: '\uE017', | |
SEMICOLON: '\uE018', | |
EQUALS: '\uE019', | |
NUMPAD0: '\uE01A', // number pad keys | |
NUMPAD1: '\uE01B', | |
NUMPAD2: '\uE01C', | |
NUMPAD3: '\uE01D', | |
NUMPAD4: '\uE01E', | |
NUMPAD5: '\uE01F', | |
NUMPAD6: '\uE020', | |
NUMPAD7: '\uE021', | |
NUMPAD8: '\uE022', | |
NUMPAD9: '\uE023', | |
MULTIPLY: '\uE024', | |
ADD: '\uE025', | |
SEPARATOR: '\uE026', | |
SUBTRACT: '\uE027', | |
DECIMAL: '\uE028', | |
DIVIDE: '\uE029', | |
F1: '\uE031', // function keys | |
F2: '\uE032', | |
F3: '\uE033', | |
F4: '\uE034', | |
F5: '\uE035', | |
F6: '\uE036', | |
F7: '\uE037', | |
F8: '\uE038', | |
F9: '\uE039', | |
F10: '\uE03A', | |
F11: '\uE03B', | |
F12: '\uE03C', | |
COMMAND: '\uE03D', // Apple command key | |
META: '\uE03D', // alias for Windows key | |
} | |
function createPointerMove({ element = Origin.POINTER, x = 0, y = 0, duration = 100 } = {}) { | |
return { | |
type: ActionType.POINTER_MOVE, | |
duration, | |
x, | |
y, | |
origin: element, | |
} | |
} | |
function createPointerEvent({ type = ActionType.POINTER_DOWN, button = Button.LEFT } = {}) { | |
return { | |
type, | |
button, | |
} | |
} | |
function createKeyEvent({ type = ActionType.KEY_DOWN, value = Key.ESCAPE } = {}) { | |
return { | |
type, | |
value, | |
} | |
} | |
function createPointerActionsObject(...actions) { | |
return [ | |
{ | |
type: 'pointer', | |
id: 'default mouse', | |
parameters: { | |
pointerType: 'mouse', | |
}, | |
actions, | |
}, | |
] | |
} | |
function createKeyboardActionsObject(actions) { | |
return [ | |
{ | |
type: 'key', | |
id: 'default keyboard', | |
parameters: { | |
pointerType: 'mouse', | |
}, | |
actions, | |
}, | |
] | |
} | |
function createRequest(endpoint, data) { | |
return browser.requestHandler.create(endpoint, data).catch((err) => { | |
throw new Error(`Request error ${JSON.stringify(err)}`) | |
}) | |
} | |
function getId(selector) { | |
if (!selector) return undefined | |
if (ELEMENT_ID_REGEXP.test(selector)) { | |
return { | |
ELEMENT: selector, | |
} | |
} | |
return browser.element(selector).value | |
} | |
export function pointerMoveMixin(selector = undefined, x = 0, y = 0) { | |
const element = getId(selector) | |
const actions = createPointerActionsObject(createPointerMove({ element, x, y })) | |
return createRequest(ENDPOINTS.ACTIONS, { actions }) | |
} | |
export function pointerDownMixin(button = Button.LEFT) { | |
const actions = createPointerActionsObject(createPointerEvent({ | |
button, type: ActionType.POINTER_DOWN, | |
})) | |
return createRequest(ENDPOINTS.ACTIONS, { actions }) | |
} | |
export function pointerUpMixin(button = Button.LEFT) { | |
const actions = createPointerActionsObject(createPointerEvent({ | |
button, type: ActionType.POINTER_UP, | |
})) | |
return createRequest(ENDPOINTS.ACTIONS, { actions }) | |
} | |
export function pointerClickMixin( | |
selector = undefined, button = Button.LEFT, | |
x = undefined, y = undefined | |
) { | |
if (selector && x && y) { | |
let size = browser.getElementSize(selector) | |
if (Array.isArray(size)) size = size[0] | |
if (!size) throw new Error('could not receive an element size', selector) | |
const { width, height } = size | |
const startX = x - Math.floor(width / 2) | |
const startY = y - Math.floor(height / 2) | |
this.pointerMove(selector, startX, startY) | |
} else if (selector) { | |
this.pointerMove(selector) | |
} else { | |
this.pointerMove(undefined, x, y) | |
} | |
this.pointerDown(button) | |
this.pointerUp(button) | |
} | |
export function pointerLeftClickMixin(selector, x, y) { | |
this.pointerClick(selector, Button.LEFT, x, y) | |
} | |
export function pointerRightClickMixin(selector, x, y) { | |
this.pointerClick(selector, Button.RIGHT, x, y) | |
} | |
const normalizeCommand = string => string.toLowerCase().replace(/[_ ]/g, '') | |
export function keyCommandMixin(key = undefined) { | |
if (key) { | |
const keyNormalized = normalizeCommand(key) | |
const keyCommand = Object.keys(Key).find(k => normalizeCommand(k) === keyNormalized) | |
if (keyCommand) key = Key[keyCommand] | |
} | |
const sequence = [ | |
createKeyEvent({ type: ActionType.KEY_DOWN, value: key }), | |
createKeyEvent({ type: ActionType.KEY_UP, value: key }), | |
] | |
const actions = createKeyboardActionsObject(sequence) | |
return createRequest(ENDPOINTS.ACTIONS, { actions }) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment