UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

293 lines (292 loc) 13.3 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var types = require("../../generic/simulator/Types.js"); var ChildEndPoint_js_1 = require("../channel/websocket/ChildEndPoint.js"); var FormatHelper = Class({ does: Siesta.Util.Role.CanFormatStrings }); var formatStringHelper = new FormatHelper(); var RemoteSimulatorClient = /** @class */ (function (_super) { __extends(RemoteSimulatorClient, _super); function RemoteSimulatorClient(props) { var _this = _super.call(this, props) || this; _this.type = 'native'; _this.commandTimeout = 15000; _this.currentPosition = [0, 0]; // delta between screen position and browser viewport position - this is set on the harness page level _this.screenDeltaX = 0; _this.screenDeltaY = 0; // additional offset - set on the individual test level _this.offsetX = 0; _this.offsetY = 0; _this.antiClickMergeDelay = 500; _this.states = {}; _this.states[types.PointerModifier.Left] = types.PointerState.Up; _this.states[types.PointerModifier.Middle] = types.PointerState.Up; _this.states[types.PointerModifier.Right] = types.PointerState.Up; // aka Object.assign(this, props) for (var i in props) if (props.hasOwnProperty(i)) _this[i] = props[i]; return _this; } RemoteSimulatorClient.prototype.onTestLaunch = function (test) { this.adjustToElement(test.global.frameElement); this.lastClickTime = null; this.lastClickFromTest = null; this.lastClickPoint = null; this.syntheticSimulatorClass = test.getSimulatorClass(); this.syntheticSimulatorConfig = test.simulatorConfig; this.currentTest = test; }; RemoteSimulatorClient.prototype.cleanup = function () { this.syntheticSimulator = null; this.syntheticSimulatorConfig = null; this.syntheticSimulatorClass = null; this.currentTest = null; }; RemoteSimulatorClient.prototype.getSyntheticSimulator = function () { if (this.syntheticSimulator) return this.syntheticSimulator; this.syntheticSimulator = new this.syntheticSimulatorClass(this.syntheticSimulatorConfig || {}); this.syntheticSimulator.onTestLaunch(this.currentTest); return this.syntheticSimulator; }; RemoteSimulatorClient.prototype.setup = function () { return Promise.resolve(); }; RemoteSimulatorClient.prototype.onSocketOpen = function (event) { }; RemoteSimulatorClient.prototype.onSocketClose = function (event) { _super.prototype.onSocketClose.call(this, event); this.onSocketCloseListener && this.onSocketCloseListener(event); }; RemoteSimulatorClient.prototype.adjustToElement = function (el) { if (!el) { this.offsetX = this.offsetY = 0; return; } var rect = el.getBoundingClientRect(); this.offsetX = rect.left; this.offsetY = rect.top; }; RemoteSimulatorClient.prototype.translateX = function (x) { return Math.max(0, x + this.screenDeltaX + this.offsetX); }; RemoteSimulatorClient.prototype.translateY = function (y) { return Math.max(0, y + this.screenDeltaY + this.offsetY); }; // calculate mouse move precision, based on the value for synthetic RemoteSimulatorClient.prototype.calculateMouseMovePrecision = function () { var config = this.syntheticSimulatorConfig; if (config) { // "speedRun" mode if (config.mouseMovePrecision == 1 && config.pathBatchSize == 30) return 3; return config.mouseMovePrecision; } else return null; }; RemoteSimulatorClient.prototype.simulateMouseMove = function (x, y, options, params) { var _this = this; // we don't use default value for the argument because it is sometimes provided // as `undefiend` or `null` from the outer code if (!params) params = {}; return this.sendRpcCall({ type: 'move_pointer', x: this.translateX(x), y: this.translateY(y), moveKind: params.moveKind || "smooth", mouseMovePrecision: params.mouseMovePrecision || this.calculateMouseMovePrecision(), modifierKey: this.optionsToModifierKeys(options) }, 2 * this.commandTimeout).then(function (result) { _this.currentPosition[0] = x; _this.currentPosition[1] = y; return result; }); }; RemoteSimulatorClient.prototype.simulateMouseDown = function (clickInfo, options) { var _this = this; var cont = this.getAntiClickMergePromise(clickInfo, options); return cont.then(function () { return _this.sendRpcCall({ type: 'set_pointer_state', state: types.PointerState.Down, modifier: types.PointerModifier.Left, modifierKey: _this.optionsToModifierKeys(options) }, _this.commandTimeout).then(function (result) { _this.states[types.PointerModifier.Left] = types.PointerState.Down; return result; }); }); }; RemoteSimulatorClient.prototype.simulateMouseUp = function (clickInfo, options) { var _this = this; var cont = this.getAntiClickMergePromise(clickInfo, options); return cont.then(function () { return _this.sendRpcCall({ type: 'set_pointer_state', state: types.PointerState.Up, modifier: types.PointerModifier.Left, modifierKey: _this.optionsToModifierKeys(options) }, _this.commandTimeout).then(function (result) { _this.states[types.PointerModifier.Left] = types.PointerState.Up; return result; }); }); }; // TODO remove the `clickInfo` arg? which was used to apply additional condition, that // action happened at the same point // which seems not to be enough in certain cases and needs to be removed RemoteSimulatorClient.prototype.getAntiClickMergePromise = function (clickInfo, options) { var _this = this; if (options === void 0) { options = {}; } var clickFrom = options.testUniqueId; var cont; // this construct is solving "click merge" problem in native simulation, // where 2 consequent clicks in the same point (like "t.click()") // will be treated by browser like double click // that double click will select text in the input for example and something that // does not happen in synthetic simulation (which users are used to) // the heuristic is: // if the click happens less than 1000 ms since the last click // REMOVED: and its on the same point // and its from different test (or different subtest of the same test file) if (this.lastClickTime && clickFrom != null && (new Date().getTime() - this.lastClickTime) < 1000 && clickFrom != this.lastClickFromTest // && clickInfo.globalXY[ 0 ] == this.lastClickPoint[ 0 ] // && clickInfo.globalXY[ 1 ] == this.lastClickPoint[ 1 ] ) { //console.log("Delaying click") cont = new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, _this.antiClickMergeDelay); }); } else { cont = Promise.resolve(); } this.lastClickTime = new Date().getTime(); this.lastClickFromTest = clickFrom; // this.lastClickPoint = clickInfo.globalXY.slice() //console.log("click time ", this.lastClickTime, " click test id ", this.lastClickFromTest, " click point ", this.lastClickPoint) return cont; }; RemoteSimulatorClient.prototype.simulateMouseClick = function (clickInfo, options) { var _this = this; if (options === void 0) { options = {}; } var cont = this.getAntiClickMergePromise(clickInfo, options); // not possible to click on <option> (at least easily) since <option> element // has no "getBoundingClientRect" and we don't know where to click // fallback to synthetic for backward compat if (clickInfo.el && clickInfo.el.tagName.toLowerCase() == 'option') { return this.getSyntheticSimulator().simulateMouseClick(clickInfo, options); } else return cont.then(function () { return _this.sendRpcCall({ type: 'pointer_click', modifier: types.PointerModifier.Left, modifierKey: _this.optionsToModifierKeys(options), }, _this.commandTimeout); }); }; RemoteSimulatorClient.prototype.simulateRightClick = function (clickInfo, options) { var _this = this; var cont = this.getAntiClickMergePromise(clickInfo, options); return cont.then(function () { return _this.sendRpcCall({ type: 'pointer_click', modifier: types.PointerModifier.Right, modifierKey: _this.optionsToModifierKeys(options) }, _this.commandTimeout); }); }; RemoteSimulatorClient.prototype.simulateDoubleClick = function (clickInfo, options) { var _this = this; var cont = this.getAntiClickMergePromise(clickInfo, options); return cont.then(function () { return _this.sendRpcCall({ type: 'pointer_double_click', modifier: types.PointerModifier.Left, modifierKey: _this.optionsToModifierKeys(options) }, _this.commandTimeout); }); }; RemoteSimulatorClient.prototype.simulateDrag = function (sourceXY, targetXY, options, dragOnly) { var _this = this; var cont = this.getAntiClickMergePromise(undefined, options); return cont.then(function () { return _this.sendRpcCall({ type: 'pointer_drag', modifier: types.PointerModifier.Left, fromX: _this.translateX(sourceXY[0]), fromY: _this.translateY(sourceXY[1]), toX: _this.translateX(targetXY[0]), toY: _this.translateY(targetXY[1]), dragOnly: dragOnly, modifierKey: _this.optionsToModifierKeys(options) }, 2 * _this.commandTimeout).then(function () { _this.currentPosition[0] = targetXY[0]; _this.currentPosition[1] = targetXY[1]; _this.states[types.PointerModifier.Left] = dragOnly ? types.PointerState.Up : types.PointerState.Down; }); }); }; RemoteSimulatorClient.prototype.simulateMouseWheel = function (clickInfo, options) { return this.sendRpcCall({ type: 'mouse_wheel', deltaX: options.deltaX || 0, deltaY: options.deltaY || 0, modifierKey: this.optionsToModifierKeys(options) }, this.commandTimeout); }; RemoteSimulatorClient.prototype.optionsToModifierKeys = function (options) { if (!options) return []; var modifiers = []; if (options.shiftKey) modifiers.push('SHIFT'); if (options.ctrlKey) modifiers.push('CTRL'); if (options.altKey) modifiers.push('ALT'); // is this correct? if (options.metaKey) modifiers.push('CMD'); return modifiers; }; // proxy method to be available in the subclasses RemoteSimulatorClient.prototype.extractKeysAndSpecialKeys = function (text) { return formatStringHelper.extractKeysAndSpecialKeys(text).map(function (key) { if (key.length == 1) return key; return key.substring(1, key.length - 1); }); }; RemoteSimulatorClient.prototype.simulateType = function (text, options, params) { return this.sendRpcCall({ type: 'type', text: this.extractKeysAndSpecialKeys(text), modifierKey: this.optionsToModifierKeys(options) }, this.commandTimeout); }; RemoteSimulatorClient.prototype.doFullSimulationReset = function () { return this.sendRpcCall({ type: 'reset' }, this.commandTimeout); }; return RemoteSimulatorClient; }(ChildEndPoint_js_1.ChildEndPoint)); exports.RemoteSimulatorClient = RemoteSimulatorClient;