testcafe
Version:
Automated browser testing for the modern web development stack.
1,226 lines (868 loc) • 392 kB
JavaScript
// NOTE: We should have the capability to initialize scripts with different contexts.
// This is required for iframes without the src attribute because Hammerhead does not
// inject scripts into such iframes. So, we wrap all scripts in initialization functions.
(function () {
function initTestCafeAutomation(window, isIFrameWithoutSrc) {
var document = window.document;
// This file was generated by modules-webmake (modules for web) project.
// See: https://github.com/medikoo/modules-webmake
(function (modules) {
'use strict';
var resolve, getRequire, wmRequire, notFoundError, findFile
, extensions = {".js":[],".json":[],".css":[],".html":[]}
, envRequire = typeof require === 'function' ? require : null;
notFoundError = function (path) {
var error = new Error("Could not find module '" + path + "'");
error.code = 'MODULE_NOT_FOUND';
return error;
};
findFile = function (scope, name, extName) {
var i, ext;
if (typeof scope[name + extName] === 'function') return name + extName;
for (i = 0; (ext = extensions[extName][i]); ++i) {
if (typeof scope[name + ext] === 'function') return name + ext;
}
return null;
};
resolve = function (scope, tree, path, fullPath, state, id) {
var name, dir, exports, module, fn, found, ext;
path = path.split(/[\\/]/);
name = path.pop();
if ((name === '.') || (name === '..')) {
path.push(name);
name = '';
}
while ((dir = path.shift()) != null) {
if (!dir || (dir === '.')) continue;
if (dir === '..') {
scope = tree.pop();
id = id.slice(0, id.lastIndexOf('/'));
} else {
tree.push(scope);
scope = scope[dir];
id += '/' + dir;
}
if (!scope) throw notFoundError(fullPath);
}
if (name && (typeof scope[name] !== 'function')) {
found = findFile(scope, name, '.js');
if (!found) found = findFile(scope, name, '.json');
if (!found) found = findFile(scope, name, '.css');
if (!found) found = findFile(scope, name, '.html');
if (found) {
name = found;
} else if ((state !== 2) && (typeof scope[name] === 'object')) {
tree.push(scope);
scope = scope[name];
id += '/' + name;
name = '';
}
}
if (!name) {
if ((state !== 1) && scope[':mainpath:']) {
return resolve(scope, tree, scope[':mainpath:'], fullPath, 1, id);
}
return resolve(scope, tree, 'index', fullPath, 2, id);
}
fn = scope[name];
if (!fn) throw notFoundError(fullPath);
if (fn.hasOwnProperty('module')) return fn.module.exports;
exports = {};
fn.module = module = { exports: exports, id: id + '/' + name };
fn.call(exports, exports, module, getRequire(scope, tree, id));
return module.exports;
};
wmRequire = function (scope, tree, fullPath, id) {
var name, path = fullPath, t = fullPath.charAt(0), state = 0;
if (t === '/') {
path = path.slice(1);
scope = modules['/'];
if (!scope) {
if (envRequire) return envRequire(fullPath);
throw notFoundError(fullPath);
}
id = '/';
tree = [];
} else if (t !== '.') {
name = path.split('/', 1)[0];
scope = modules[name];
if (!scope) {
if (envRequire) return envRequire(fullPath);
throw notFoundError(fullPath);
}
id = name;
tree = [];
path = path.slice(name.length + 1);
if (!path) {
path = scope[':mainpath:'];
if (path) {
state = 1;
} else {
path = 'index';
state = 2;
}
}
}
return resolve(scope, tree, path, fullPath, state, id);
};
getRequire = function (scope, tree, id) {
return function (path) {
return wmRequire(scope, [].concat(tree), path, id);
};
};
return getRequire(modules, [], '');
})({
"testcafe-release": {
"src": {
"client": {
"automation": {
"cursor.js": function (exports, module, require) {
exports.__esModule = true;
var _testcafeCore = require('./deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _testcafeUi = require('./deps/testcafe-ui');
var _testcafeUi2 = _interopRequireDefault(_testcafeUi);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var domUtils = _testcafeCore2.default.domUtils;
var cursorUI = window.top === window ? _testcafeUi2.default.cursorUI : _testcafeUi2.default.iframeCursorUI;
// NOTE: the default position should be outside of the page (GH-794)
exports.default = {
x: -1,
y: -1,
currentActiveWindow: window.top,
_ensureActiveWindow: function _ensureActiveWindow() {
if (this.currentActiveWindow === window || this.currentActiveWindow === window.parent) return;
var activeFrame = domUtils.findIframeByWindow(this.currentActiveWindow);
if (!activeFrame || !domUtils.isElementInDocument(activeFrame)) this.currentActiveWindow = window;
},
get active() {
this._ensureActiveWindow();
return this.currentActiveWindow === window;
},
set activeWindow(win) {
this.currentActiveWindow = win;
},
get activeWindow() {
this._ensureActiveWindow();
return this.currentActiveWindow;
},
get position() {
return { x: this.x, y: this.y };
},
get visible() {
return window.top === window && cursorUI.isVisible();
},
move: function move(newX, newY) {
this.x = newX;
this.y = newY;
return cursorUI.move(this.x, this.y);
},
hide: function hide() {
if (this.visible) cursorUI.hide();
},
show: function show() {
if (window.top === window) cursorUI.show();
},
leftButtonDown: function leftButtonDown() {
return cursorUI.leftButtonDown();
},
rightButtonDown: function rightButtonDown() {
return cursorUI.rightButtonDown();
},
buttonUp: function buttonUp() {
return cursorUI.buttonUp();
}
};
module.exports = exports['default'];
},
"deps": {
"hammerhead.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = window['%hammerhead%'];
module.exports = exports['default'];
},
"testcafe-core.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = window['%testCafeCore%'];
module.exports = exports['default'];
},
"testcafe-ui.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = window['%testCafeUI%'];
module.exports = exports['default'];
}
},
"errors.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = {
elementIsInvisibleError: 'elementIsInvisibleError',
foundElementIsNotTarget: 'foundElementIsNotTarget'
};
module.exports = exports['default'];
},
"get-element.js": function (exports, module, require) {
exports.__esModule = true;
exports.fromPoint = fromPoint;
exports.underCursor = underCursor;
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('./deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _testcafeUi = require('./deps/testcafe-ui');
var _testcafeUi2 = _interopRequireDefault(_testcafeUi);
var _cursor = require('./cursor');
var _cursor2 = _interopRequireDefault(_cursor);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var browserUtils = _hammerhead2.default.utils.browser;
var Promise = _hammerhead2.default.Promise;
var nativeMethods = _hammerhead2.default.nativeMethods;
var positionUtils = _testcafeCore2.default.positionUtils;
var domUtils = _testcafeCore2.default.domUtils;
function getElementFromPoint(x, y, underTopShadowUIElement) {
var topElement = null;
return _testcafeUi2.default.hide(underTopShadowUIElement).then(function () {
topElement = positionUtils.getElementFromPoint(x, y);
return _testcafeUi2.default.show(underTopShadowUIElement);
}).then(function () {
return topElement;
});
}
function ensureImageMap(imgElement, areaElement) {
var mapElement = domUtils.closest(areaElement, 'map');
return mapElement && mapElement.name === imgElement.useMap.substring(1) ? areaElement : imgElement;
}
function findElementOrNonEmptyChildFromPoint(x, y, element) {
var topElement = positionUtils.getElementFromPoint(x, y);
var isNonEmptyChild = domUtils.containsElement(element, topElement) && nativeMethods.nodeTextContentGetter.call(topElement).length;
if (topElement && topElement === element || isNonEmptyChild) return topElement;
return null;
}
function correctTopElementByExpectedElement(topElement, expectedElement) {
var expectedElementDefined = expectedElement && domUtils.isDomElement(expectedElement);
if (!expectedElementDefined || !topElement || topElement === expectedElement) return topElement;
var isTREFElement = domUtils.getTagName(expectedElement) === 'tref';
// NOTE: 'document.elementFromPoint' can't find these types of elements
if (isTREFElement) return expectedElement;
// NOTE: T299665 - Incorrect click automation for images with an associated map element in Firefox
// All browsers return the <area> element from document.getElementFromPoint, but
// Firefox returns the <img> element. We should accomplish this for Firefox as well.
var isImageMapArea = domUtils.getTagName(expectedElement) === 'area' && domUtils.isImgElement(topElement);
if (browserUtils.isFirefox && isImageMapArea) return ensureImageMap(topElement, expectedElement);
// NOTE: try to find a multi-line link by its rectangle (T163678)
var isLinkOrChildExpected = domUtils.isAnchorElement(expectedElement) || domUtils.getParents(expectedElement, 'a').length;
var isTopElementChildOfLink = isLinkOrChildExpected && domUtils.containsElement(expectedElement, topElement) && nativeMethods.nodeTextContentGetter.call(topElement).length;
var shouldSearchForMultilineLink = isLinkOrChildExpected && !isTopElementChildOfLink && nativeMethods.nodeTextContentGetter.call(expectedElement).length;
if (!shouldSearchForMultilineLink) return topElement;
var linkRect = expectedElement.getBoundingClientRect();
return findElementOrNonEmptyChildFromPoint(linkRect.right - 1, linkRect.top + 1, expectedElement) || findElementOrNonEmptyChildFromPoint(linkRect.left + 1, linkRect.bottom - 1, expectedElement) || topElement;
}
function fromPoint(x, y, expectedElement) {
var isInIframe = window !== window.top;
var foundElement = null;
return getElementFromPoint(x, y).then(function (topElement) {
foundElement = topElement;
// NOTE: when trying to get an element by elementFromPoint in iframe and the target
// element is under any of shadow-ui elements, you will get null (only in IE).
// In this case, you should hide a top window's shadow-ui root to obtain an element.
var resChain = Promise.resolve(topElement);
if (!foundElement && isInIframe && x > 0 && y > 0) {
resChain = resChain.then(function () {
return getElementFromPoint(x, y, true);
}).then(function (element) {
foundElement = element;
return element;
});
}
return resChain.then(function (element) {
return correctTopElementByExpectedElement(element, expectedElement);
}).then(function (correctedElement) {
return { element: correctedElement, corrected: correctedElement !== foundElement };
});
});
}
function underCursor() {
var cursorPosition = _cursor2.default.position;
return fromPoint(cursorPosition.x, cursorPosition.y).then(function (_ref) {
var element = _ref.element;
return element;
});
}
},
"index.js": function (exports, module, require) {
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _scroll = require('./playback/scroll');
var _scroll2 = _interopRequireDefault(_scroll);
var _click = require('./playback/click');
var _click2 = _interopRequireDefault(_click);
var _selectChild = require('./playback/click/select-child');
var _selectChild2 = _interopRequireDefault(_selectChild);
var _dblclick = require('./playback/dblclick');
var _dblclick2 = _interopRequireDefault(_dblclick);
var _toOffset = require('./playback/drag/to-offset');
var _toOffset2 = _interopRequireDefault(_toOffset);
var _toElement = require('./playback/drag/to-element');
var _toElement2 = _interopRequireDefault(_toElement);
var _hover = require('./playback/hover');
var _hover2 = _interopRequireDefault(_hover);
var _press = require('./playback/press');
var _press2 = _interopRequireDefault(_press);
var _rclick = require('./playback/rclick');
var _rclick2 = _interopRequireDefault(_rclick);
var _selectText = require('./playback/select/select-text');
var _selectText2 = _interopRequireDefault(_selectText);
var _selectEditableContent = require('./playback/select/select-editable-content');
var _selectEditableContent2 = _interopRequireDefault(_selectEditableContent);
var _type = require('./playback/type');
var _type2 = _interopRequireDefault(_type);
var _upload = require('./playback/upload');
var _upload2 = _interopRequireDefault(_upload);
var _options = require('../../test-run/commands/options');
var _settings = require('./settings');
var _settings2 = _interopRequireDefault(_settings);
var _offsets = require('./utils/offsets');
var _utils = require('./playback/press/utils');
var _calculateSelectTextArguments = require('./playback/select/calculate-select-text-arguments');
var _calculateSelectTextArguments2 = _interopRequireDefault(_calculateSelectTextArguments);
var _errors = require('./errors');
var _errors2 = _interopRequireDefault(_errors);
var _cursor = require('./cursor');
var _cursor2 = _interopRequireDefault(_cursor);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.Scroll = _scroll2.default;
exports.Click = _click2.default;
exports.SelectChildClick = _selectChild2.default;
exports.DblClick = _dblclick2.default;
exports.DragToOffset = _toOffset2.default;
exports.DragToElement = _toElement2.default;
exports.Hover = _hover2.default;
exports.Press = _press2.default;
exports.RClick = _rclick2.default;
exports.SelectText = _selectText2.default;
exports.SelectEditableContent = _selectEditableContent2.default;
exports.Type = _type2.default;
exports.Upload = _upload2.default;
exports.MouseOptions = _options.MouseOptions;
exports.ClickOptions = _options.ClickOptions;
exports.TypeOptions = _options.TypeOptions;
exports.ERROR_TYPES = _errors2.default;
exports.AutomationSettings = _settings2.default;
exports.getOffsetOptions = _offsets.getOffsetOptions;
exports.calculateSelectTextArguments = _calculateSelectTextArguments2.default;
exports.cursor = _cursor2.default;
exports.getNextFocusableElement = _utils.getNextFocusableElement;
exports.get = require;
var nativeMethods = _hammerhead2.default.nativeMethods;
var evalIframeScript = _hammerhead2.default.EVENTS.evalIframeScript;
nativeMethods.objectDefineProperty(window, '%testCafeAutomation%', { configurable: true, value: exports });
// eslint-disable-next-line no-undef
_hammerhead2.default.on(evalIframeScript, function (e) {
return initTestCafeAutomation(nativeMethods.contentWindowGetter.call(e.iframe), true);
});
},
"playback": {
"click": {
"click-command.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = function (eventState, eventArgs) {
var elementBoundToLabel = (0, _utils.getElementBoundToLabel)(eventArgs.element);
var isSelectElement = domUtils.isSelectElement(eventArgs.element);
var isOptionElement = domUtils.isOptionElement(eventArgs.element);
var isLabelElement = domUtils.isLabelElement(eventArgs.element) && elementBoundToLabel;
var isLabelledCheckbox = elementBoundToLabel && domUtils.isCheckboxElement(elementBoundToLabel);
if (isSelectElement) return new SelectElementClickCommand(eventState, eventArgs);
if (isOptionElement) return new OptionElementClickCommand(eventState, eventArgs);
if (isLabelledCheckbox) return new LabelledCheckboxElementClickCommand(eventState, eventArgs);
if (isLabelElement) return new LabelElementClickCommand(eventState, eventArgs);
return new ElementClickCommand(eventState, eventArgs);
};
var _hammerhead = require('../../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('../../deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _testcafeUi = require('../../deps/testcafe-ui');
var _testcafeUi2 = _interopRequireDefault(_testcafeUi);
var _utils = require('../../utils/utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var browserUtils = _hammerhead2.default.utils.browser;
var eventSimulator = _hammerhead2.default.eventSandbox.eventSimulator;
var listeners = _hammerhead2.default.eventSandbox.listeners;
var domUtils = _testcafeCore2.default.domUtils;
var styleUtils = _testcafeCore2.default.styleUtils;
var selectElementUI = _testcafeUi2.default.selectElement;
var ElementClickCommand = function () {
function ElementClickCommand(eventState, eventArgs) {
_classCallCheck(this, ElementClickCommand);
this.eventState = eventState;
this.eventArgs = eventArgs;
}
ElementClickCommand.prototype.run = function run() {
if (this.eventState.clickElement) eventSimulator.click(this.eventState.clickElement, this.eventArgs.options);
if (!domUtils.isElementFocusable(this.eventArgs.element)) (0, _utils.focusByRelatedElement)(this.eventArgs.element);
};
return ElementClickCommand;
}();
var LabelElementClickCommand = function (_ElementClickCommand) {
_inherits(LabelElementClickCommand, _ElementClickCommand);
function LabelElementClickCommand(eventState, eventArgs) {
_classCallCheck(this, LabelElementClickCommand);
var _this = _possibleConstructorReturn(this, _ElementClickCommand.call(this, eventState, eventArgs));
_this.label = _this.eventArgs.element;
_this.input = (0, _utils.getElementBoundToLabel)(_this.eventArgs.element);
return _this;
}
LabelElementClickCommand.prototype.run = function run() {
var _this2 = this;
var focusRaised = false;
var ensureFocusRaised = function ensureFocusRaised(e) {
focusRaised = e.target === _this2.input;
};
listeners.addInternalEventListener(window, ['focus'], ensureFocusRaised);
_ElementClickCommand.prototype.run.call(this);
listeners.removeInternalEventListener(window, ['focus'], ensureFocusRaised);
if (domUtils.isElementFocusable(this.label) && !focusRaised) this._ensureBoundElementFocusRaised();
};
LabelElementClickCommand.prototype._ensureBoundElementFocusRaised = function _ensureBoundElementFocusRaised() {
eventSimulator.focus(this.input);
};
return LabelElementClickCommand;
}(ElementClickCommand);
var SelectElementClickCommand = function (_ElementClickCommand2) {
_inherits(SelectElementClickCommand, _ElementClickCommand2);
function SelectElementClickCommand(eventState, eventArgs) {
_classCallCheck(this, SelectElementClickCommand);
return _possibleConstructorReturn(this, _ElementClickCommand2.call(this, eventState, eventArgs));
}
SelectElementClickCommand.prototype.run = function run() {
_ElementClickCommand2.prototype.run.call(this);
this._toggleSelectOptionList();
};
SelectElementClickCommand.prototype._toggleSelectOptionList = function _toggleSelectOptionList() {
// NOTE: Emulating the click event on the 'select' element doesn't expand the
// dropdown with options (except chrome), therefore we should emulate it.
var element = this.eventArgs.element;
var isSelectWithDropDown = styleUtils.getSelectElementSize(element) === 1;
if (isSelectWithDropDown && this.eventState.simulateDefaultBehavior !== false) {
if (selectElementUI.isOptionListExpanded(element)) selectElementUI.collapseOptionList();else selectElementUI.expandOptionList(element);
}
};
return SelectElementClickCommand;
}(ElementClickCommand);
var OptionElementClickCommand = function (_ElementClickCommand3) {
_inherits(OptionElementClickCommand, _ElementClickCommand3);
function OptionElementClickCommand(eventState, eventArgs) {
_classCallCheck(this, OptionElementClickCommand);
return _possibleConstructorReturn(this, _ElementClickCommand3.call(this, eventState, eventArgs));
}
OptionElementClickCommand.prototype.run = function run() {
return this.eventArgs.element;
};
return OptionElementClickCommand;
}(ElementClickCommand);
var LabelledCheckboxElementClickCommand = function (_LabelElementClickCom) {
_inherits(LabelledCheckboxElementClickCommand, _LabelElementClickCom);
function LabelledCheckboxElementClickCommand(eventState, eventArgs) {
_classCallCheck(this, LabelledCheckboxElementClickCommand);
var _this5 = _possibleConstructorReturn(this, _LabelElementClickCom.call(this, eventState, eventArgs));
_this5.checkbox = _this5.input;
return _this5;
}
LabelledCheckboxElementClickCommand.prototype.run = function run() {
var changed = false;
var onChange = function onChange() {
changed = true;
};
listeners.addInternalEventListener(window, ['change'], onChange);
_LabelElementClickCom.prototype.run.call(this);
listeners.removeInternalEventListener(window, ['change'], onChange);
if (browserUtils.isChrome && !changed) this._ensureCheckboxStateChanged();
};
LabelledCheckboxElementClickCommand.prototype._ensureCheckboxStateChanged = function _ensureCheckboxStateChanged() {
this.checkbox.checked = !this.checkbox.checked;
eventSimulator.change(this.checkbox);
};
return LabelledCheckboxElementClickCommand;
}(LabelElementClickCommand);
module.exports = exports['default'];
},
"index.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('../../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('../../deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _visibleElementAutomation = require('../visible-element-automation');
var _visibleElementAutomation2 = _interopRequireDefault(_visibleElementAutomation);
var _utils = require('../../utils/utils');
var _cursor = require('../../cursor');
var _cursor2 = _interopRequireDefault(_cursor);
var _nextTick = require('../../utils/next-tick');
var _nextTick2 = _interopRequireDefault(_nextTick);
var _clickCommand = require('./click-command');
var _clickCommand2 = _interopRequireDefault(_clickCommand);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Promise = _hammerhead2.default.Promise;
var extend = _hammerhead2.default.utils.extend;
var browserUtils = _hammerhead2.default.utils.browser;
var featureDetection = _hammerhead2.default.utils.featureDetection;
var eventSimulator = _hammerhead2.default.eventSandbox.eventSimulator;
var listeners = _hammerhead2.default.eventSandbox.listeners;
var domUtils = _testcafeCore2.default.domUtils;
var eventUtils = _testcafeCore2.default.eventUtils;
var arrayUtils = _testcafeCore2.default.arrayUtils;
var delay = _testcafeCore2.default.delay;
var ClickAutomation = function (_VisibleElementAutoma) {
_inherits(ClickAutomation, _VisibleElementAutoma);
function ClickAutomation(element, clickOptions) {
_classCallCheck(this, ClickAutomation);
var _this = _possibleConstructorReturn(this, _VisibleElementAutoma.call(this, element, clickOptions));
_this.modifiers = clickOptions.modifiers;
_this.caretPos = clickOptions.caretPos;
_this.targetElementParentNodes = [];
_this.activeElementBeforeMouseDown = null;
_this.mouseDownElement = null;
_this.eventState = {
mousedownPrevented: false,
blurRaised: false,
simulateDefaultBehavior: true,
clickElement: null
};
return _this;
}
ClickAutomation.prototype._bindMousedownHandler = function _bindMousedownHandler() {
var _this2 = this;
var onmousedown = function onmousedown(e) {
_this2.eventState.mousedownPrevented = e.defaultPrevented;
eventUtils.preventDefault(e);
eventUtils.unbind(_this2.element, 'mousedown', onmousedown);
};
eventUtils.bind(this.element, 'mousedown', onmousedown);
};
ClickAutomation.prototype._bindBlurHandler = function _bindBlurHandler(element) {
var _this3 = this;
var onblur = function onblur() {
_this3.eventState.blurRaised = true;
eventUtils.unbind(element, 'blur', onblur, true);
};
eventUtils.bind(element, 'blur', onblur, true);
};
ClickAutomation.prototype._raiseTouchEvents = function _raiseTouchEvents(eventArgs) {
if (featureDetection.isTouchDevice) {
eventSimulator.touchstart(eventArgs.element, eventArgs.options);
eventSimulator.touchend(eventArgs.element, eventArgs.options);
}
};
ClickAutomation.prototype._mousedown = function _mousedown(eventArgs) {
var _this4 = this;
this.targetElementParentNodes = domUtils.getParents(eventArgs.element);
this.mouseDownElement = eventArgs.element;
return _cursor2.default.leftButtonDown().then(function () {
_this4._raiseTouchEvents(eventArgs);
var activeElement = domUtils.getActiveElement();
_this4.activeElementBeforeMouseDown = activeElement;
// NOTE: In WebKit and IE, the mousedown event opens the select element's dropdown;
// therefore, we should prevent mousedown and hide the dropdown (B236416).
var needCloseSelectDropDown = (browserUtils.isWebKit || browserUtils.isIE) && domUtils.isSelectElement(_this4.mouseDownElement);
if (needCloseSelectDropDown) _this4._bindMousedownHandler();
_this4._bindBlurHandler(activeElement);
_this4.eventState.simulateDefaultBehavior = eventSimulator.mousedown(eventArgs.element, eventArgs.options);
if (_this4.eventState.simulateDefaultBehavior === false) _this4.eventState.simulateDefaultBehavior = needCloseSelectDropDown && !_this4.eventState.mousedownPrevented;
return _this4._ensureActiveElementBlur(activeElement);
}).then(function () {
return _this4._focus(eventArgs);
});
};
ClickAutomation.prototype._ensureActiveElementBlur = function _ensureActiveElementBlur(element) {
var _this5 = this;
// NOTE: In some cases, mousedown may lead to active element change (browsers raise blur).
// We simulate the blur event if the active element was changed after the mousedown, and
// the blur event does not get raised automatically (B239273, B253520)
return new Promise(function (resolve) {
var simulateBlur = domUtils.getActiveElement() !== element && !_this5.eventState.blurRaised;
if (!simulateBlur) {
resolve();
return;
}
if (browserUtils.isIE && browserUtils.version < 12) {
// NOTE: In whatever way an element is blurred from the client script, the
// blur event is raised asynchronously in IE (in MSEdge focus/blur is sync)
(0, _nextTick2.default)().then(function () {
if (!_this5.eventState.blurRaised) eventSimulator.blur(element);
resolve();
});
} else {
eventSimulator.blur(element);
resolve();
}
});
};
ClickAutomation.prototype._focus = function _focus(eventArgs) {
if (this.eventState.simulateDefaultBehavior === false) return Promise.resolve();
// NOTE: If a target element is a contentEditable element, we need to call focusAndSetSelection directly for
// this element. Otherwise, if the element obtained by elementFromPoint is a child of the contentEditable
// element, a selection position may be calculated incorrectly (by using the caretPos option).
var elementForFocus = domUtils.isContentEditableElement(this.element) ? this.element : eventArgs.element;
// NOTE: IE doesn't perform focus if active element has been changed while executing mousedown
var simulateFocus = !browserUtils.isIE || this.activeElementBeforeMouseDown === domUtils.getActiveElement();
return (0, _utils.focusAndSetSelection)(elementForFocus, simulateFocus, this.caretPos);
};
ClickAutomation._getElementForClick = function _getElementForClick(mouseDownElement, topElement, mouseDownElementParentNodes) {
var topElementParentNodes = domUtils.getParents(topElement);
var areElementsSame = domUtils.isTheSameNode(topElement, mouseDownElement);
// NOTE: Mozilla Firefox always skips click, if an element under cursor has been changed after mousedown.
if (browserUtils.isFirefox) return areElementsSame ? mouseDownElement : null;
if (!areElementsSame) {
if (mouseDownElement.contains(topElement) && !domUtils.isEditableFormElement(topElement)) return mouseDownElement;
if (topElement.contains(mouseDownElement)) return topElement;
// NOTE: If elements are not in the parent-child relationships,
// non-ff browsers raise the `click` event for their common parent.
return arrayUtils.getCommonElement(topElementParentNodes, mouseDownElementParentNodes);
}
// NOTE: In case the target element and the top element are the same,
// non-FF browsers are dispatching the `click` event if the target
// element hasn't changed its position in the DOM after mousedown.
return arrayUtils.equals(mouseDownElementParentNodes, topElementParentNodes) ? mouseDownElement : null;
};
ClickAutomation.prototype._mouseup = function _mouseup(eventArgs) {
var _this6 = this;
return _cursor2.default.buttonUp().then(function () {
return _this6._getElementForEvent(eventArgs);
}).then(function (element) {
eventArgs.element = element;
_this6.eventState.clickElement = ClickAutomation._getElementForClick(_this6.mouseDownElement, element, _this6.targetElementParentNodes);
var timeStamp = {};
var getTimeStamp = function getTimeStamp(e) {
timeStamp = e.timeStamp;
listeners.removeInternalEventListener(window, ['mouseup'], getTimeStamp);
};
if (!browserUtils.isIE) listeners.addInternalEventListener(window, ['mouseup'], getTimeStamp);
eventSimulator.mouseup(element, eventArgs.options);
return { timeStamp: timeStamp };
});
};
ClickAutomation.prototype._click = function _click(eventArgs) {
var clickCommand = (0, _clickCommand2.default)(this.eventState, eventArgs);
clickCommand.run();
return eventArgs;
};
ClickAutomation.prototype.run = function run(useStrictElementCheck) {
var _this7 = this;
var eventArgs = null;
return this._ensureElement(useStrictElementCheck).then(function (_ref) {
var element = _ref.element,
clientPoint = _ref.clientPoint,
screenPoint = _ref.screenPoint,
devicePoint = _ref.devicePoint;
eventArgs = {
point: clientPoint,
screenPoint: screenPoint,
element: element,
options: extend({
clientX: clientPoint.x,
clientY: clientPoint.y,
screenX: devicePoint.x,
screenY: devicePoint.y
}, _this7.modifiers)
};
// NOTE: we should raise mouseup event with 'mouseActionStepDelay' after we trigger
// mousedown event regardless of how long mousedown event handlers were executing
return Promise.all([delay(_this7.automationSettings.mouseActionStepDelay), _this7._mousedown(eventArgs)]);
}).then(function () {
return _this7._mouseup(eventArgs);
}).then(function (_ref2) {
var timeStamp = _ref2.timeStamp;
eventArgs.options.timeStamp = timeStamp;
return _this7._click(eventArgs);
});
};
return ClickAutomation;
}(_visibleElementAutomation2.default);
exports.default = ClickAutomation;
module.exports = exports['default'];
},
"select-child.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('../../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('../../deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _testcafeUi = require('../../deps/testcafe-ui');
var _testcafeUi2 = _interopRequireDefault(_testcafeUi);
var _move2 = require('../move');
var _move3 = _interopRequireDefault(_move2);
var _options = require('../../../../test-run/commands/options');
var _offsets = require('../../utils/offsets');
var _settings = require('../../settings');
var _settings2 = _interopRequireDefault(_settings);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Promise = _hammerhead2.default.Promise;
var browserUtils = _hammerhead2.default.utils.browser;
var featureDetection = _hammerhead2.default.utils.featureDetection;
var eventSimulator = _hammerhead2.default.eventSandbox.eventSimulator;
var focusBlurSandbox = _hammerhead2.default.eventSandbox.focusBlur;
var nativeMethods = _hammerhead2.default.nativeMethods;
var domUtils = _testcafeCore2.default.domUtils;
var styleUtils = _testcafeCore2.default.styleUtils;
var delay = _testcafeCore2.default.delay;
var selectElementUI = _testcafeUi2.default.selectElement;
var FOCUS_DELAY = featureDetection.isTouchDevice ? 0 : 160;
var SelectChildClickAutomation = function () {
function SelectChildClickAutomation(element, clickOptions) {
_classCallCheck(this, SelectChildClickAutomation);
this.element = element;
this.modifiers = clickOptions.modifiers;
this.caretPos = clickOptions.caretPos;
this.offsetX = clickOptions.offsetX;
this.offsetY = clickOptions.offsetY;
this.speed = clickOptions.speed;
this.automationSettings = new _settings2.default(clickOptions.speed);
this.parentSelect = domUtils.getSelectParent(this.element);
this.optionListExpanded = this.parentSelect ? selectElementUI.isOptionListExpanded(this.parentSelect) : false;
this.childIndex = null;
this.clickCausesChange = false;
if (this.parentSelect) {
var isOption = domUtils.isOptionElement(this.element);
var selectedIndex = this.parentSelect.selectedIndex;
this.childIndex = isOption ? domUtils.getElementIndexInParent(this.parentSelect, this.element) : domUtils.getElementIndexInParent(this.parentSelect, this.element);
var parent = nativeMethods.nodeParentNodeGetter.call(this.element);
var parentOptGroup = domUtils.isOptionGroupElement(parent) ? parent : null;
var isDisabled = this.element.disabled || parentOptGroup && parentOptGroup.disabled;
this.clickCausesChange = isOption && !isDisabled && this.childIndex !== selectedIndex;
}
this.eventsArgs = {
options: this.modifiers,
element: this.element
};
}
SelectChildClickAutomation.prototype._calculateEventArguments = function _calculateEventArguments() {
var childElement = this.optionListExpanded ? selectElementUI.getEmulatedChildElement(this.element) : this.element;
var parentSelectSize = styleUtils.getSelectElementSize(this.parentSelect) > 1;
return {
options: this.modifiers,
element: browserUtils.isIE && parentSelectSize ? this.parentSelect : childElement
};
};
SelectChildClickAutomation.prototype._getMoveArguments = function _getMoveArguments() {
var element = null;
var offsetX = null;
var offsetY = null;
if (this.optionListExpanded) {
element = selectElementUI.getEmulatedChildElement(this.element);
var moveActionOffsets = (0, _offsets.getDefaultAutomationOffsets)(element);
offsetX = moveActionOffsets.offsetX;
offsetY = moveActionOffsets.offsetY;
} else {
element = document.documentElement;
var elementCenter = selectElementUI.getSelectChildCenter(this.element);
offsetX = elementCenter.x;
offsetY = elementCenter.y;
}
return { element: element, offsetX: offsetX, offsetY: offsetY, speed: this.speed };
};
SelectChildClickAutomation.prototype._move = function _move(_ref) {
var _this = this;
var element = _ref.element,
offsetX = _ref.offsetX,
offsetY = _ref.offsetY,
speed = _ref.speed;
var moveOptions = new _options.MoveOptions({
offsetX: offsetX,
offsetY: offsetY,
speed: speed,
modifiers: this.modifiers
}, false);
var moveAutomation = new _move3.default(element, moveOptions);
return moveAutomation.run().then(function () {
return delay(_this.automationSettings.mouseActionStepDelay);
});
};
SelectChildClickAutomation.prototype._mousedown = function _mousedown() {
var _this2 = this;
if (browserUtils.isFirefox) {
eventSimulator.mousedown(this.eventsArgs.element, this.eventsArgs.options);
if (this.clickCausesChange) this.parentSelect.selectedIndex = this.childIndex;
return this._focus();
}
if (browserUtils.isIE) {
eventSimulator.mousedown(this.eventsArgs.element, this.eventsArgs.options);
return this._focus();
}
// NOTE: In Chrome, document.activeElement is 'select' after mousedown. But we need to
// raise blur and change the event for a previously active element during focus raising.
// That's why we should change the event order and raise focus before mousedown.
return this._focus().then(function () {
return delay(FOCUS_DELAY);
}).then(function () {
eventSimulator.mousedown(_this2.eventsArgs.element, _this2.eventsArgs.options);
if (_this2.clickCausesChange) _this2.parentSelect.selectedIndex = _this2.childIndex;
});
};
SelectChildClickAutomation.prototype._focus = function _focus() {
var _this3 = this;
return new Promise(function (resolve) {
focusBlurSandbox.focus(_this3.parentSelect, resolve, false, true);
});
};
SelectChildClickAutomation.prototype._mouseup = function _mouseup() {
var elementForMouseupEvent = browserUtils.isIE ? this.parentSelect : this.eventsArgs.element;
eventSimulator.mouseup(elementForMouseupEvent, this.eventsArgs.options);
if (browserUtils.isIE && this.clickCausesChange) this.parentSelect.selectedIndex = this.childIndex;
var simulateInputEventOnValueChange = browserUtils.isFirefox || browserUtils.isSafari || browserUtils.isChrome && browserUtils.version >= 53;
var simulateChangeEventOnValueChange = simulateInputEventOnValueChange || browserUtils.isIE;
if (simulateInputEventOnValueChange && this.clickCausesChange) eventSimulator.input(this.parentSelect);
if (simulateChangeEventOnValueChange && this.clickCausesChange) eventSimulator.change(this.parentSelect);
return Promise.resolve();
};
SelectChildClickAutomation.prototype._click = function _click() {
eventSimulator.click(this.eventsArgs.element, this.eventsArgs.options);
};
SelectChildClickAutomation.prototype.run = function run() {
var _this4 = this;
if (!this.parentSelect) {
eventSimulator.click(this.eventsArgs.element, this.eventsArgs.options);
return Promise.resolve();
}
if (!this.optionListExpanded) selectElementUI.scrollOptionListByChild(this.element);
var moveArguments = this._getMoveArguments();
this.eventsArgs = this._calculateEventArguments();
if (styleUtils.getSelectElementSize(this.parentSelect) <= 1) {
return this._move(moveArguments).then(function () {
return _this4._click();
});
}
return this._move(moveArguments).then(function () {
return _this4._mousedown();
}).then(function () {
return _this4._mouseup();
}).then(function () {
return _this4._click();
});
};
return SelectChildClickAutomation;
}();
exports.default = SelectChildClickAutomation;
module.exports = exports['default'];
}
},
"dblclick.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('../deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _options = require('../../../test-run/commands/options');
var _visibleElementAutomation = require('./visible-element-automation');
var _visibleElementAutomation2 = _interopRequireDefault(_visibleElementAutomation);
var _click = require('./click');
var _click2 = _interopRequireDefault(_click);
var _settings = require('../settings');
var _settings2 = _interopRequireDefault(_settings);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if