siesta-lite
Version:
Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers
293 lines (292 loc) • 13.3 kB
JavaScript
"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;