Skip to content

Instantly share code, notes, and snippets.

@dukhanov
Created November 13, 2017 16:00
Show Gist options
  • Save dukhanov/a348aee18ff976cc4a93d3f4fddaf180 to your computer and use it in GitHub Desktop.
Save dukhanov/a348aee18ff976cc4a93d3f4fddaf180 to your computer and use it in GitHub Desktop.
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