testcafe
Version:
Automated browser testing for the modern web development stack.
1,313 lines (961 loc) • 95.2 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 initTestCafeUI(window) {
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": {
"ui": {
"cursor": {
"iframe-cursor.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('../deps/testcafe-core');
var _messages = require('./messages');
var _messages2 = _interopRequireDefault(_messages);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var browserUtils = _hammerhead2.default.utils.browser;
// HACK: In most browsers, the iframe's getElementFromPoint function ignores elements
// from the parent frame. But in IE it doesn't, and our cursor overlaps the target
// element. So, we move the cursor to a position one pixel farther to avoid this.
var RECOGNITION_INCREMENT = browserUtils.isIE ? 1 : 0;
exports.default = {
move: function move(x, y) {
var msg = {
cmd: _messages2.default.moveRequest,
x: x + RECOGNITION_INCREMENT,
y: y + RECOGNITION_INCREMENT
};
return (0, _testcafeCore.sendRequestToFrame)(msg, _messages2.default.moveResponse, window.parent);
},
leftButtonDown: function leftButtonDown() {
return (0, _testcafeCore.sendRequestToFrame)({
cmd: _messages2.default.leftButtonDownRequest
}, _messages2.default.leftButtonDownResponse, window.parent);
},
rightButtonDown: function rightButtonDown() {
return (0, _testcafeCore.sendRequestToFrame)({
cmd: _messages2.default.rightButtonDownRequest
}, _messages2.default.rightButtonDownResponse, window.parent);
},
buttonUp: function buttonUp() {
return (0, _testcafeCore.sendRequestToFrame)({
cmd: _messages2.default.buttonUpRequest
}, _messages2.default.buttonUpResponse, window.parent);
}
};
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 _uiRoot = require('../ui-root');
var _uiRoot2 = _interopRequireDefault(_uiRoot);
var _messages = require('./messages');
var _messages2 = _interopRequireDefault(_messages);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var Promise = _hammerhead2.default.Promise;
var shadowUI = _hammerhead2.default.shadowUI;
var browserUtils = _hammerhead2.default.utils.browser;
var featureDetection = _hammerhead2.default.utils.featureDetection;
var messageSandbox = _hammerhead2.default.eventSandbox.message;
var styleUtils = _testcafeCore2.default.styleUtils;
var positionUtils = _testcafeCore2.default.positionUtils;
var CURSOR_CLASS = 'cursor';
var TOUCH_CLASS = 'touch';
var L_MOUSE_DOWN_CLASS = 'l-mouse-down';
var R_MOUSE_DOWN_CLASS = 'r-mouse-down';
var STATE_CLASSES = [L_MOUSE_DOWN_CLASS, R_MOUSE_DOWN_CLASS].join(' ');
// Setup cross-iframe interaction
messageSandbox.on(messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (e) {
var msg = e.message;
var position = null;
switch (msg.cmd) {
case _messages2.default.moveRequest:
position = positionUtils.getIframePointRelativeToParentFrame({ x: msg.x, y: msg.y }, e.source);
CursorUI.move(position.x, position.y).then(function () {
return messageSandbox.sendServiceMsg({ cmd: _messages2.default.moveResponse }, e.source);
});
break;
case _messages2.default.leftButtonDownRequest:
CursorUI.leftButtonDown().then(function () {
return messageSandbox.sendServiceMsg({ cmd: _messages2.default.leftButtonDownResponse }, e.source);
});
break;
case _messages2.default.rightButtonDownRequest:
CursorUI.rightButtonDown().then(function () {
return messageSandbox.sendServiceMsg({ cmd: _messages2.default.rightButtonDownResponse }, e.source);
});
break;
case _messages2.default.buttonUpRequest:
CursorUI.buttonUp().then(function () {
return messageSandbox.sendServiceMsg({ cmd: _messages2.default.buttonUpResponse }, e.source);
});
break;
}
});
var CursorUI = {
cursorElement: null,
x: 50,
y: 50,
pointerOffsetX: 0,
pointerOffsetY: 0,
_createElement: function _createElement() {
this.cursorElement = document.createElement('div');
shadowUI.addClass(this.cursorElement, CURSOR_CLASS);
// NOTE: For IE, we can't use the touch cursor in a cross-domain iframe
// because we won't be able to get an element under the cursor
if (featureDetection.isTouchDevice && !browserUtils.isIE) {
shadowUI.addClass(this.cursorElement, TOUCH_CLASS);
// NOTE: in touch mode, the pointer should be in the center of the cursor
this.pointerOffsetX = Math.ceil(styleUtils.getWidth(this.cursorElement) / 2);
this.pointerOffsetY = Math.ceil(styleUtils.getHeight(this.cursorElement) / 2);
}
_uiRoot2.default.element().appendChild(this.cursorElement);
},
isVisible: function isVisible() {
return this.cursorElement && styleUtils.get(this.cursorElement, 'visibility') !== 'hidden';
},
hide: function hide() {
if (!this.cursorElement) this._createElement();
styleUtils.set(this.cursorElement, 'visibility', 'hidden');
},
show: function show() {
if (!this.cursorElement) this._createElement();
styleUtils.set(this.cursorElement, 'visibility', '');
},
move: function move(x, y) {
this.x = x;
this.y = y;
if (!this.cursorElement) this._createElement();
styleUtils.set(this.cursorElement, {
left: this.x - this.pointerOffsetX + 'px',
top: this.y - this.pointerOffsetY + 'px'
});
return Promise.resolve();
},
leftButtonDown: function leftButtonDown() {
if (!this.cursorElement) this._createElement();
shadowUI.removeClass(this.cursorElement, STATE_CLASSES);
shadowUI.addClass(this.cursorElement, L_MOUSE_DOWN_CLASS);
return Promise.resolve();
},
rightButtonDown: function rightButtonDown() {
if (!this.cursorElement) this._createElement();
shadowUI.removeClass(this.cursorElement, STATE_CLASSES);
shadowUI.addClass(this.cursorElement, R_MOUSE_DOWN_CLASS);
return Promise.resolve();
},
buttonUp: function buttonUp() {
if (!this.cursorElement) this._createElement();
shadowUI.removeClass(this.cursorElement, STATE_CLASSES);
return Promise.resolve();
}
};
exports.default = CursorUI;
module.exports = exports['default'];
},
"messages.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = {
moveRequest: 'ui|cursor|move|request',
leftButtonDownRequest: 'ui|cursor|leftbuttondown|request',
rightButtonDownRequest: 'ui|cursor|rightbuttondown|request',
buttonUpRequest: 'ui|cursor|buttonup|request',
moveResponse: 'ui|cursor|move|response',
leftButtonDownResponse: 'ui|cursor|leftbuttondown|response',
rightButtonDownResponse: 'ui|cursor|rightbuttondown|response',
buttonUpResponse: 'ui|cursor|buttonup|response'
};
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'];
}
},
"index.js": function (exports, module, require) {
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('./deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _selectElement = require('./select-element');
var selectElement = _interopRequireWildcard(_selectElement);
var _modalBackground = require('./modal-background');
var modalBackground = _interopRequireWildcard(_modalBackground);
var _progressPanel = require('./progress-panel');
var _progressPanel2 = _interopRequireDefault(_progressPanel);
var _statusBar = require('./status-bar');
var _statusBar2 = _interopRequireDefault(_statusBar);
var _iframeStatusBar = require('./status-bar/iframe-status-bar');
var _iframeStatusBar2 = _interopRequireDefault(_iframeStatusBar);
var _cursor = require('./cursor');
var _cursor2 = _interopRequireDefault(_cursor);
var _iframeCursor = require('./cursor/iframe-cursor');
var iframeCursorUI = _interopRequireWildcard(_iframeCursor);
var _screenshotMark = require('./screenshot-mark');
var _screenshotMark2 = _interopRequireDefault(_screenshotMark);
var _uiRoot = require('./ui-root');
var _uiRoot2 = _interopRequireDefault(_uiRoot);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var Promise = _hammerhead2.default.Promise;
var messageSandbox = _hammerhead2.default.eventSandbox.message;
var sendRequestToFrame = _testcafeCore2.default.sendRequestToFrame;
var HIDE_REQUEST_CMD = 'ui|hide|request';
var HIDE_RESPONSE_CMD = 'ui|hide|response';
var SHOW_REQUEST_CMD = 'ui|show|request';
var SHOW_RESPONSE_CMD = 'ui|show|response';
// Setup cross-iframe interaction
messageSandbox.on(messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (e) {
if (e.message.cmd === HIDE_REQUEST_CMD) {
_uiRoot2.default.hide();
messageSandbox.sendServiceMsg({ cmd: HIDE_RESPONSE_CMD }, e.source);
} else if (e.message.cmd === SHOW_REQUEST_CMD) {
_uiRoot2.default.show();
messageSandbox.sendServiceMsg({ cmd: SHOW_RESPONSE_CMD }, e.source);
}
});
exports.cursorUI = _cursor2.default;
exports.iframeCursorUI = iframeCursorUI;
exports.selectElement = selectElement;
exports.modalBackground = modalBackground;
exports.ProgressPanel = _progressPanel2.default;
exports.StatusBar = _statusBar2.default;
exports.IframeStatusBar = _iframeStatusBar2.default;
exports.get = require;
exports.hide = function (hideTopRoot) {
if (hideTopRoot) return sendRequestToFrame({ cmd: HIDE_REQUEST_CMD }, HIDE_RESPONSE_CMD, window.top);
_uiRoot2.default.hide();
return Promise.resolve();
};
exports.show = function (showTopRoot) {
if (showTopRoot) return sendRequestToFrame({ cmd: SHOW_REQUEST_CMD }, SHOW_RESPONSE_CMD, window.top);
_uiRoot2.default.show();
return Promise.resolve();
};
exports.showScreenshotMark = function (url) {
return _screenshotMark2.default.show(url);
};
exports.hideScreenshotMark = function () {
return _screenshotMark2.default.hide();
};
var nativeMethods = _hammerhead2.default.nativeMethods;
var evalIframeScript = _hammerhead2.default.EVENTS.evalIframeScript;
nativeMethods.objectDefineProperty(window, '%testCafeUI%', { configurable: true, value: exports });
// eslint-disable-next-line no-undef
_hammerhead2.default.on(evalIframeScript, function (e) {
return initTestCafeUI(nativeMethods.contentWindowGetter.call(e.iframe), true);
});
},
"modal-background.js": function (exports, module, require) {
exports.__esModule = true;
exports.initAndShowLoadingText = initAndShowLoadingText;
exports.show = show;
exports.hide = hide;
exports.showLoadingIcon = showLoadingIcon;
exports.hideLoadingIcon = hideLoadingIcon;
var _hammerhead = require('./deps/hammerhead');
var _testcafeCore = require('./deps/testcafe-core');
var _uiRoot = require('./ui-root');
var _uiRoot2 = _interopRequireDefault(_uiRoot);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
//Const
var LOADING_TEXT = 'Loading page...';
var BACKGROUND_CLASS = 'modal-background';
var LOADING_TEXT_CLASS = 'loading-text';
var BACKGROUND_OPACITY = 0.7;
var BACKGROUND_OPACITY_WITH_LOADING_TEXT = 0.8;
var LOADING_ICON_CLASS = 'loading-icon';
//Globals
var backgroundDiv = null;
var loadingTextDiv = null;
var loadingIconDiv = null;
var initialized = false;
//Markup
function createBackground() {
var root = _uiRoot2.default.element();
backgroundDiv = document.createElement('div');
root.appendChild(backgroundDiv);
_hammerhead.shadowUI.addClass(backgroundDiv, BACKGROUND_CLASS);
loadingTextDiv = document.createElement('div');
_hammerhead.nativeMethods.nodeTextContentSetter.call(loadingTextDiv, LOADING_TEXT);
root.appendChild(loadingTextDiv);
_hammerhead.shadowUI.addClass(loadingTextDiv, LOADING_TEXT_CLASS);
loadingIconDiv = document.createElement('div');
_testcafeCore.styleUtils.set(loadingIconDiv, 'visibility', 'hidden');
root.appendChild(loadingIconDiv);
_hammerhead.shadowUI.addClass(loadingIconDiv, LOADING_ICON_CLASS);
}
//Behavior
function adjustLoadingTextPos() {
var wHeight = _testcafeCore.styleUtils.getHeight(window);
var wWidth = _testcafeCore.styleUtils.getWidth(window);
var loadingTextHidden = !_testcafeCore.styleUtils.hasDimensions(loadingTextDiv);
if (loadingTextHidden) {
_testcafeCore.styleUtils.set(loadingTextDiv, 'visibility', 'hidden');
_testcafeCore.styleUtils.set(loadingTextDiv, 'display', 'block');
}
_testcafeCore.styleUtils.set(loadingTextDiv, {
left: Math.max((wWidth - _testcafeCore.styleUtils.getWidth(loadingTextDiv)) / 2, 0) + 'px',
top: Math.max((wHeight - _testcafeCore.styleUtils.getHeight(loadingTextDiv)) / 2, 0) + 'px'
});
if (loadingTextHidden) {
_testcafeCore.styleUtils.set(loadingTextDiv, 'display', 'none');
_testcafeCore.styleUtils.set(loadingTextDiv, 'visibility', '');
}
}
function initSizeAdjustments() {
var adjust = function adjust() {
var wHeight = _testcafeCore.styleUtils.getHeight(window);
var wWidth = _testcafeCore.styleUtils.getWidth(window);
_testcafeCore.styleUtils.set(backgroundDiv, 'width', wWidth + 'px');
_testcafeCore.styleUtils.set(backgroundDiv, 'height', wHeight + 'px');
_testcafeCore.styleUtils.set(loadingIconDiv, {
left: Math.round((wWidth - _testcafeCore.styleUtils.getWidth(loadingIconDiv)) / 2) + 'px',
top: Math.round((wHeight - _testcafeCore.styleUtils.getHeight(loadingIconDiv)) / 2) + 'px'
});
};
adjust();
_testcafeCore.eventUtils.bind(window, 'resize', adjust);
}
function init() {
createBackground();
initSizeAdjustments();
adjustLoadingTextPos();
initialized = true;
}
function initAndShowLoadingText() {
var shown = false;
//NOTE: init and show modal background as soon as possible
var initAndShow = function initAndShow() {
init();
_testcafeCore.styleUtils.set(backgroundDiv, 'opacity', BACKGROUND_OPACITY_WITH_LOADING_TEXT);
_testcafeCore.styleUtils.set(backgroundDiv, 'display', 'block');
_testcafeCore.styleUtils.set(loadingTextDiv, 'display', 'block');
shown = true;
};
var tryShowBeforeReady = function tryShowBeforeReady() {
if (!shown) {
if (document.body) initAndShow();else _hammerhead.nativeMethods.setTimeout.call(window, tryShowBeforeReady, 0);
}
};
tryShowBeforeReady();
//NOTE: ensure that background was shown on ready
_testcafeCore.eventUtils.documentReady().then(function () {
if (!shown) initAndShow();
});
}
function show(transparent) {
if (!initialized) init();
_testcafeCore.styleUtils.set(backgroundDiv, 'opacity', transparent ? 0 : BACKGROUND_OPACITY);
_testcafeCore.styleUtils.set(backgroundDiv, 'display', 'block');
}
function hide() {
if (!initialized) return;
_testcafeCore.styleUtils.set(loadingTextDiv, 'display', 'none');
_testcafeCore.styleUtils.set(backgroundDiv, 'display', 'none');
}
function showLoadingIcon() {
_testcafeCore.styleUtils.set(loadingIconDiv, 'visibility', 'visible');
}
function hideLoadingIcon() {
_testcafeCore.styleUtils.set(loadingIconDiv, 'visibility', 'hidden');
}
},
"progress-panel": {
"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 _progressBar = require('./progress-bar');
var _progressBar2 = _interopRequireDefault(_progressBar);
var _uiRoot = require('../ui-root');
var _uiRoot2 = _interopRequireDefault(_uiRoot);
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 shadowUI = _hammerhead2.default.shadowUI;
var nativeMethods = _hammerhead2.default.nativeMethods;
var eventUtils = _testcafeCore2.default.eventUtils;
var styleUtils = _testcafeCore2.default.styleUtils;
var PANEL_CLASS = 'progress-panel';
var TITLE_CLASS = 'title';
var CONTENT_CLASS = 'content';
var UPDATE_INTERVAL = 100;
var ANIMATION_UPDATE_INTERVAL = 10;
var OPENING_DELAY = 300;
var SHOWING_DELAY = 200;
var HIDING_DELAY = 600;
var MIN_SHOWING_TIME = 1000;
var ProgressPanel = function () {
function ProgressPanel() {
var _this = this;
_classCallCheck(this, ProgressPanel);
this.startTime = null;
this.openingTimeout = null;
this.updateInterval = null;
this.animationInterval = null;
this.panelDiv = document.createElement('div');
_uiRoot2.default.element().appendChild(this.panelDiv);
this.titleDiv = document.createElement('div');
this.panelDiv.appendChild(this.titleDiv);
this.contentDiv = document.createElement('div');
this.panelDiv.appendChild(this.contentDiv);
shadowUI.addClass(this.panelDiv, PANEL_CLASS);
shadowUI.addClass(this.titleDiv, TITLE_CLASS);
shadowUI.addClass(this.contentDiv, CONTENT_CLASS);
ProgressPanel._showAtWindowCenter(this.panelDiv);
this.progressBar = new _progressBar2.default(this.contentDiv);
this.disposePanel = function () {
return ProgressPanel._showAtWindowCenter(_this.panelDiv);
};
}
ProgressPanel._getInvisibleElementProperty = function _getInvisibleElementProperty(element, property) {
var needShowElement = styleUtils.get(element, 'display') === 'none';
if (needShowElement) styleUtils.set(element, 'display', 'block');
var value = element[property];
if (needShowElement) styleUtils.set(element, 'display', 'none');
return value;
};
ProgressPanel._showAtWindowCenter = function _showAtWindowCenter(element) {
var elementHeight = ProgressPanel._getInvisibleElementProperty(element, 'offsetHeight');
var elementWidth = ProgressPanel._getInvisibleElementProperty(element, 'offsetWidth');
var top = Math.round(styleUtils.getHeight(window) / 2 - elementHeight / 2);
var left = Math.round(styleUtils.getWidth(window) / 2 - elementWidth / 2);
styleUtils.set(element, {
left: left + 'px',
top: top + 'px'
});
};
ProgressPanel.prototype._setCurrentProgress = function _setCurrentProgress() {
var progress = Math.round((Date.now() - this.startTime) / this.maxTimeout * 100);
this.progressBar.setValue(progress);
};
ProgressPanel.prototype._setSuccess = function _setSuccess(value) {
this.progressBar.setSuccess(value);
};
ProgressPanel.prototype._stopAnimation = function _stopAnimation() {
nativeMethods.clearInterval.call(window, this.animationInterval);
};
ProgressPanel.prototype._animate = function _animate(el, duration, show, complete) {
var _this2 = this;
var startTime = Date.now();
var startOpacityValue = show ? 0 : 1;
var passedTime = 0;
var progress = 0;
var delta = 0;
if (show) {
styleUtils.set(el, 'opacity', startOpacityValue);
styleUtils.set(el, 'display', 'block');
}
this._stopAnimation();
this.animationInterval = nativeMethods.setInterval.call(window, function () {
passedTime = Date.now() - startTime;
progress = Math.min(passedTime / duration, 1);
delta = 0.5 - Math.cos(progress * Math.PI) / 2;
styleUtils.set(el, 'opacity', startOpacityValue + (show ? delta : -delta));
if (progress === 1) {
_this2._stopAnimation();
if (complete) complete();
}
}, ANIMATION_UPDATE_INTERVAL);
};
ProgressPanel.prototype._showPanel = function _showPanel() {
eventUtils.bind(window, 'resize', this.disposePanel);
this._animate(this.panelDiv, SHOWING_DELAY, true);
};
ProgressPanel.prototype._hidePanel = function _hidePanel(force) {
var _this3 = this;
this.startTime = null;
eventUtils.unbind(window, 'resize', this.disposePanel);
this._animate(this.panelDiv, force ? 0 : HIDING_DELAY, false, function () {
return styleUtils.set(_this3.panelDiv, 'display', 'none');
});
};
ProgressPanel.prototype.show = function show(text, timeout) {
var _this4 = this;
this.startTime = Date.now();
this.maxTimeout = timeout;
nativeMethods.nodeTextContentSetter.call(this.titleDiv, text);
this._setSuccess(false);
this.openingTimeout = nativeMethods.setTimeout.call(window, function () {
_this4.openingTimeout = null;
_this4._setCurrentProgress();
_this4._showPanel();
_this4.updateInterval = nativeMethods.setInterval.call(window, function () {
return _this4._setCurrentProgress();
}, UPDATE_INTERVAL);
}, OPENING_DELAY);
};
ProgressPanel.prototype.close = function close(success) {
var _this5 = this;
if (success) this._setSuccess(true);
if (this.openingTimeout) {
nativeMethods.clearTimeout.call(window, this.openingTimeout);
this.openingTimeout = null;
}
if (this.updateInterval) {
nativeMethods.clearInterval.call(window, this.updateInterval);
this.updateInterval = null;
}
if (success) {
if (this.startTime && Date.now() - this.startTime < MIN_SHOWING_TIME) {
nativeMethods.setTimeout.call(window, function () {
nativeMethods.setTimeout.call(window, function () {
return _this5._hidePanel(false);
}, SHOWING_DELAY);
}, UPDATE_INTERVAL);
} else nativeMethods.setTimeout.call(window, function () {
return _this5._hidePanel(false);
}, SHOWING_DELAY);
} else this._hidePanel(true);
};
return ProgressPanel;
}();
exports.default = ProgressPanel;
module.exports = exports['default'];
},
"progress-bar.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);
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 shadowUI = _hammerhead2.default.shadowUI;
var styleUtils = _testcafeCore2.default.styleUtils;
var CONTAINER_CLASS = 'progress-bar';
var VALUE_CLASS = 'value';
var SUCCESS_CLASS = 'success';
var ProgressBar = function () {
function ProgressBar(containerElement) {
_classCallCheck(this, ProgressBar);
this.containerElement = document.createElement('div');
this.valueElement = document.createElement('div');
containerElement.appendChild(this.containerElement);
this.containerElement.appendChild(this.valueElement);
shadowUI.addClass(this.containerElement, CONTAINER_CLASS);
shadowUI.addClass(this.valueElement, VALUE_CLASS);
}
ProgressBar.prototype.setValue = function setValue(value) {
value = typeof value !== 'number' ? 0 : Math.min(Math.max(value, 0), 100);
styleUtils.set(this.valueElement, 'width', value + '%');
};
ProgressBar.prototype.setSuccess = function setSuccess(value) {
if (value) shadowUI.addClass(this.containerElement, SUCCESS_CLASS);else shadowUI.removeClass(this.containerElement, SUCCESS_CLASS);
};
return ProgressBar;
}();
exports.default = ProgressBar;
module.exports = exports['default'];
}
},
"screenshot-mark.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('./deps/hammerhead');
var _constants = require('../../screenshots/constants');
exports.default = {
screenshotMark: null,
_createMark: function _createMark() {
this.screenshotMark = document.createElement('img');
_hammerhead.shadowUI.addClass(this.screenshotMark, 'screenshot-mark');
this.screenshotMark.style.right = _constants.MARK_RIGHT_MARGIN / window.devicePixelRatio + 'px';
this.screenshotMark.style.width = _constants.MARK_LENGTH / window.devicePixelRatio + 'px';
this.screenshotMark.style.height = _constants.MARK_HEIGHT / window.devicePixelRatio + 'px';
this.hide();
_hammerhead.shadowUI.getRoot().appendChild(this.screenshotMark);
},
hide: function hide() {
if (!this.screenshotMark) return;
this.screenshotMark.style.visibility = 'hidden';
},
show: function show(url) {
if (!this.screenshotMark) this._createMark();
_hammerhead.nativeMethods.imageSrcSetter.call(this.screenshotMark, url);
this.screenshotMark.style.visibility = '';
}
};
module.exports = exports['default'];
},
"select-element.js": function (exports, module, require) {
exports.__esModule = true;
exports.expandOptionList = expandOptionList;
exports.collapseOptionList = collapseOptionList;
exports.isOptionListExpanded = isOptionListExpanded;
exports.getEmulatedChildElement = getEmulatedChildElement;
exports.scrollOptionListByChild = scrollOptionListByChild;
exports.getSelectChildCenter = getSelectChildCenter;
exports.switchOptionsByKeys = switchOptionsByKeys;
exports.isOptionElementVisible = isOptionElementVisible;
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _testcafeCore = require('./deps/testcafe-core');
var _testcafeCore2 = _interopRequireDefault(_testcafeCore);
var _uiRoot = require('./ui-root');
var _uiRoot2 = _interopRequireDefault(_uiRoot);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var shadowUI = _hammerhead2.default.shadowUI; //NOTE: we can't manipulate (open/close option list) with a native select element during test running, so we
// draw our custom option list to emulate this.
var browserUtils = _hammerhead2.default.utils.browser;
var featureDetection = _hammerhead2.default.utils.featureDetection;
var nativeMethods = _hammerhead2.default.nativeMethods;
var eventSimulator = _hammerhead2.default.eventSandbox.eventSimulator;
var listeners = _hammerhead2.default.eventSandbox.listeners;
var positionUtils = _testcafeCore2.default.positionUtils;
var domUtils = _testcafeCore2.default.domUtils;
var styleUtils = _testcafeCore2.default.styleUtils;
var eventUtils = _testcafeCore2.default.eventUtils;
var arrayUtils = _testcafeCore2.default.arrayUtils;
var OPTION_LIST_CLASS = 'tcOptionList';
var OPTION_GROUP_CLASS = 'tcOptionGroup';
var OPTION_CLASS = 'tcOption';
var DISABLED_CLASS = 'disabled';
var MAX_OPTION_LIST_LENGTH = browserUtils.isIE ? 30 : 20;
var curSelectEl = null;
var optionList = null;
var groups = [];
var options = [];
function onDocumentMouseDown(e) {
//NOTE: only in Mozilla 'mousedown' raises for option
if ((e.target || e.srcElement) !== curSelectEl && !domUtils.containsElement(curSelectEl, e.target) && !domUtils.containsElement(optionList, e.target)) collapseOptionList();
}
function onWindowClick(e, dispatched, preventDefault) {
var optionIndex = arrayUtils.indexOf(options, e.target);
if (optionIndex < 0) return;
preventDefault();
var isDisabled = e.target.className.indexOf(DISABLED_CLASS) > -1;
if (isDisabled && browserUtils.isWebKit) return;
clickOnOption(optionIndex, isDisabled);
}
function clickOnOption(optionIndex, isOptionDisabled) {
var curSelectIndex = curSelectEl.selectedIndex;
var realOption = curSelectEl.getElementsByTagName('option')[optionIndex];
var clickLeadChanges = !isOptionDisabled && optionIndex !== curSelectIndex;
if (clickLeadChanges && !browserUtils.isIE) curSelectEl.selectedIndex = optionIndex;
if (!browserUtils.isFirefox && !browserUtils.isIE && clickLeadChanges) {
eventSimulator.input(curSelectEl);
eventSimulator.change(curSelectEl);
}
if (browserUtils.isFirefox || browserUtils.isIE) eventSimulator.mousedown(browserUtils.isFirefox ? realOption : curSelectEl);
if (!featureDetection.isTouchDevice) eventSimulator.mouseup(browserUtils.isFirefox ? realOption : curSelectEl);
if ((browserUtils.isFirefox || browserUtils.isIE) && clickLeadChanges) {
if (browserUtils.isIE) curSelectEl.selectedIndex = optionIndex;
if (!browserUtils.isIE) eventSimulator.input(curSelectEl);
eventSimulator.change(curSelectEl);
}
if (!featureDetection.isTouchDevice) eventSimulator.click(browserUtils.isFirefox || browserUtils.isIE ? realOption : curSelectEl);
if (!isOptionDisabled) collapseOptionList();
}
function createOption(realOption, parent) {
var option = document.createElement('div');
var isOptionDisabled = realOption.disabled || domUtils.getTagName(realOption.parentElement) === 'optgroup' && realOption.parentElement.disabled;
// eslint-disable-next-line no-restricted-properties
nativeMethods.nodeTextContentSetter.call(option, realOption.text);
parent.appendChild(option);
shadowUI.addClass(option, OPTION_CLASS);
if (isOptionDisabled) {
shadowUI.addClass(option, DISABLED_CLASS);
styleUtils.set(option, 'color', styleUtils.get(realOption, 'color'));
}
options.push(option);
}
function createGroup(realGroup, parent) {
var group = document.createElement('div');
nativeMethods.nodeTextContentSetter.call(group, realGroup.label || ' ');
parent.appendChild(group);
shadowUI.addClass(group, OPTION_GROUP_CLASS);
if (group.disabled) {
shadowUI.addClass(group, DISABLED_CLASS);
styleUtils.set(group, 'color', styleUtils.get(realGroup, 'color'));
}
createChildren(realGroup.children, group);
groups.push(group);
}
function createChildren(children, parent) {
var childrenLength = domUtils.getChildrenLength(children);
for (var i = 0; i < childrenLength; i++) {
if (domUtils.isOptionElement(children[i])) createOption(children[i], parent);else if (domUtils.getTagName(children[i]) === 'optgroup') createGroup(children[i], parent);
}
}
function expandOptionList(select) {
var selectChildren = select.children;
if (!selectChildren.length) return;
//NOTE: check is option list expanded
if (curSelectEl) {
var isSelectExpanded = select === curSelectEl;
collapseOptionList();
if (isSelectExpanded) return;
}
curSelectEl = select;
optionList = document.createElement('div');
_uiRoot2.default.element().appendChild(optionList);
shadowUI.addClass(optionList, OPTION_LIST_CLASS);
createChildren(selectChildren, optionList);
listeners.addInternalEventListener(window, ['click'], onWindowClick);
nativeMethods.setTimeout.call(window, function () {
eventUtils.bind(document, 'mousedown', onDocumentMouseDown);
}, 0);
styleUtils.set(optionList, {
position: 'absolute',
fontSize: styleUtils.get(curSelectEl, 'fontSize'),
fontFamily: styleUtils.get(curSelectEl, 'fontFamily'),
minWidth: styleUtils.getWidth(curSelectEl) + 'px',
left: positionUtils.getOffsetPosition(curSelectEl).left + 'px',
height: domUtils.getSelectVisibleChildren(select).length > MAX_OPTION_LIST_LENGTH ? styleUtils.getOptionHeight(select) * MAX_OPTION_LIST_LENGTH : ''
});
var selectTopPosition = positionUtils.getOffsetPosition(curSelectEl).top;
var optionListHeight = styleUtils.getHeight(optionList);
var optionListTopPosition = selectTopPosition + styleUtils.getHeight(curSelectEl) + 2;
if (optionListTopPosition + optionListHeight > styleUtils.getScrollTop(window) + styleUtils.getHeight(window)) {
var topPositionAboveSelect = selectTopPosition - 3 - optionListHeight;
if (topPositionAboveSelect >= styleUtils.getScrollTop(window)) optionListTopPosition = topPositionAboveSelect;
}
styleUtils.set(optionList, 'top', optionListTopPosition + 'px');
}
function collapseOptionList() {
domUtils.remove(optionList);
eventUtils.unbind(document, 'mousedown', onDocumentMouseDown);
optionList = null;
curSelectEl = null;
options = [];
groups = [];
}
function isOptionListExpanded(select) {
return select ? select === curSelectEl : !!curSelectEl;
}
function getEmulatedChildElement(element) {
var isGroup = domUtils.getTagName(element) === 'optgroup';
var elementIndex = isGroup ? domUtils.getElementIndexInParent(curSelectEl, element) : domUtils.getElementIndexInParent(curSelectEl, element);
if (!isGroup) return options[elementIndex];
return groups[elementIndex];
}
function scrollOptionListByChild(child) {
var select = domUtils.getSelectParent(child);
if (!select) return;
var realSizeValue = styleUtils.getSelectElementSize(select);
var optionHeight = styleUtils.getOptionHeight(select);
var scrollIndent = 0;
var topVisibleIndex = Math.max(styleUtils.getScrollTop(select) / optionHeight, 0);
var bottomVisibleIndex = topVisibleIndex + realSizeValue - 1;
var childIndex = domUtils.getChildVisibleIndex(select, child);
if (childIndex < topVisibleIndex) {
scrollIndent = optionHeight * (topVisibleIndex - childIndex);
styleUtils.setScrollTop(select, Math.max(styleUtils.getScrollTop(select) - scrollIndent, 0));
} else if (childIndex > bottomVisibleIndex) {
scrollIndent = optionHeight * (childIndex - bottomVisibleIndex);
styleUtils.setScrollTop(select, styleUtils.getScrollTop(select) + scrollIndent);
}
}
function getSelectChildCenter(child) {
var select = domUtils.getSelectParent(child);
if (!select) {
return {
x: 0,
y: 0
};
}
var optionHeight = styleUtils.getOptionHeight(select);
var childRectangle = positionUtils.getElementRectangle(child);
return {
x: Math.round(childRectangle.left + childRectangle.width / 2),
y: Math.round(childRectangle.top + optionHeight / 2)
};
}
function switchOptionsByKeys(element, command) {
var selectSize = styleUtils.getSelectElementSize(element);
var optionListHidden = !styleUtils.hasDimensions(shadowUI.select('.' + OPTION_LIST_CLASS)[0]);
if (/down|up/.test(command) || !browserUtils.isIE && (selectSize <= 1 || browserUtils.isFirefox) && (optionListHidden || browserUtils.isFirefox) && /left|right/.test(command)) {
var realOptions = element.querySelectorAll('option');
var enabledOptions = [];
for (var i = 0; i < realOptions.length; i++) {
var parent = realOptions[i].parentElement;
if (!realOptions[i].disabled && !(domUtils.getTagName(parent) === 'optgroup' && parent.disabled)) enabledOptions.push(realOptions[i]);
}
var curSelectedOptionIndex = arrayUtils.indexOf(enabledOptions, realOptions[element.selectedIndex]);
var nextIndex = curSelectedOptionIndex + (/down|right/.test(command) ? 1 : -1);
if (nextIndex >= 0 && nextIndex < enabledOptions.length) {
element.selectedIndex = arrayUtils.indexOf(realOptions, enabledOptions[nextIndex]);
if (!browserUtils.isIE) eventSimulator.input(element);
eventSimulator.change(element);
}
}
}
function isOptionElementVisible(el) {
var parentSelect = domUtils.getSelectParent(el);
if (!parentSelect) return true;
var expanded = isOptionListExpanded(parentSelect);
var selectSizeValue = styleUtils.getSelectElementSize(parentSelect);
return expanded || selectSizeValue > 1;
}
},
"status-bar": {
"iframe-status-bar.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 _messages = require('./messages');
var _messages2 = _interopRequireDefault(_messages);
var _index = require('./index');
var _index2 = _interopRequireDefault(_index);
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 sendRequestToFrame = _testcafeCore2.default.sendRequestToFrame;
var messageSandbox = _hammerhead2.default.eventSandbox.message;
var IframeStatusBar = function (_StatusBar) {
_inherits(IframeStatusBar, _StatusBar);
function IframeStatusBar() {
_classCallCheck(this, IframeStatusBar);
return _possibleConstructorReturn(this, _StatusBar.call(this));
}
//API
IframeStatusBar.prototype.showWaitingElementStatus = function showWaitingElementStatus(timeout) {
messageSandbox.sendServiceMsg({ cmd: _messages2.default.startWaitingElement, timeout: timeout }, window.top);
};
IframeStatusBar.prototype.hideWaitingElementStatus = function hideWaitingElementStatus(waitingSuccess) {
var msg = { cmd: _messages2.default.endWaitingElementRequest, waitingSuccess: waitingSuccess };
return sendRequestToFrame(msg, _messages2.default.endWaitingElementResponse, window.top);
};
IframeStatusBar.prototype.showWaitingAssertionRetriesStatus = function showWaitingAssertionRetriesStatus(timeout) {
messageSandbox.sendServiceMsg({ cmd: _messages2.default.startWaitingAssertionRetries, timeout: timeout }, window.top);
};
IframeStatusBar.prototype.hideWaitingAssertionRetriesStatus = function hideWaitingAssertionRetriesStatus(waitingSuccess) {
var msg = { cmd: _messages2.default.endWaitingAssertionRetriesRequest, waitingSuccess: waitingSuccess };
return sendRequestToFrame(msg, _messages2.default.endWaitingAssertionRetriesResponse, window.top);
};
return IframeStatusBar;
}(_index2.default);
exports.default = IframeStatusBar;
module.exports = exports['default'];
},
"index.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('./../deps/hammerhea