testcafe
Version:
Automated browser testing for the modern web development stack.
1,440 lines (1,093 loc) • 180 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 initTestCafeCore(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, [], '');
})({
"pinkie": {
"index.js": function (exports, module, require) {
var PENDING = 'pending';
var SETTLED = 'settled';
var FULFILLED = 'fulfilled';
var REJECTED = 'rejected';
var NOOP = function NOOP() {};
var isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function';
var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate;
var asyncQueue = [];
var asyncTimer;
function asyncFlush() {
// run promise callbacks
for (var i = 0; i < asyncQueue.length; i++) {
asyncQueue[i][0](asyncQueue[i][1]);
}
// reset async asyncQueue
asyncQueue = [];
asyncTimer = false;
}
function asyncCall(callback, arg) {
asyncQueue.push([callback, arg]);
if (!asyncTimer) {
asyncTimer = true;
asyncSetTimer(asyncFlush, 0);
}
}
function invokeResolver(resolver, promise) {
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(reason) {
reject(promise, reason);
}
try {
resolver(resolvePromise, rejectPromise);
} catch (e) {
rejectPromise(e);
}
}
function invokeCallback(subscriber) {
var owner = subscriber.owner;
var settled = owner._state;
var value = owner._data;
var callback = subscriber[settled];
var promise = subscriber.then;
if (typeof callback === 'function') {
settled = FULFILLED;
try {
value = callback(value);
} catch (e) {
reject(promise, e);
}
}
if (!handleThenable(promise, value)) {
if (settled === FULFILLED) {
resolve(promise, value);
}
if (settled === REJECTED) {
reject(promise, value);
}
}
}
function handleThenable(promise, value) {
var resolved;
try {
if (promise === value) {
throw new TypeError('A promises callback cannot return that same promise.');
}
if (value && (typeof value === 'function' || typeof value === 'object')) {
// then should be retrieved only once
var then = value.then;
if (typeof then === 'function') {
then.call(value, function (val) {
if (!resolved) {
resolved = true;
if (value === val) {
fulfill(promise, val);
} else {
resolve(promise, val);
}
}
}, function (reason) {
if (!resolved) {
resolved = true;
reject(promise, reason);
}
});
return true;
}
}
} catch (e) {
if (!resolved) {
reject(promise, e);
}
return true;
}
return false;
}
function resolve(promise, value) {
if (promise === value || !handleThenable(promise, value)) {
fulfill(promise, value);
}
}
function fulfill(promise, value) {
if (promise._state === PENDING) {
promise._state = SETTLED;
promise._data = value;
asyncCall(publishFulfillment, promise);
}
}
function reject(promise, reason) {
if (promise._state === PENDING) {
promise._state = SETTLED;
promise._data = reason;
asyncCall(publishRejection, promise);
}
}
function publish(promise) {
promise._then = promise._then.forEach(invokeCallback);
}
function publishFulfillment(promise) {
promise._state = FULFILLED;
publish(promise);
}
function publishRejection(promise) {
promise._state = REJECTED;
publish(promise);
if (!promise._handled && isNode) {
global.process.emit('unhandledRejection', promise._data, promise);
}
}
function notifyRejectionHandled(promise) {
global.process.emit('rejectionHandled', promise);
}
/**
* @class
*/
function Promise(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError('Promise resolver ' + resolver + ' is not a function');
}
if (this instanceof Promise === false) {
throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
}
this._then = [];
invokeResolver(resolver, this);
}
Promise.prototype = {
constructor: Promise,
_state: PENDING,
_then: null,
_data: undefined,
_handled: false,
then: function then(onFulfillment, onRejection) {
var subscriber = {
owner: this,
then: new this.constructor(NOOP),
fulfilled: onFulfillment,
rejected: onRejection
};
if ((onRejection || onFulfillment) && !this._handled) {
this._handled = true;
if (this._state === REJECTED && isNode) {
asyncCall(notifyRejectionHandled, this);
}
}
if (this._state === FULFILLED || this._state === REJECTED) {
// already resolved, call callback async
asyncCall(invokeCallback, subscriber);
} else {
// subscribe
this._then.push(subscriber);
}
return subscriber.then;
},
catch: function _catch(onRejection) {
return this.then(null, onRejection);
}
};
Promise.all = function (promises) {
if (!Array.isArray(promises)) {
throw new TypeError('You must pass an array to Promise.all().');
}
return new Promise(function (resolve, reject) {
var results = [];
var remaining = 0;
function resolver(index) {
remaining++;
return function (value) {
results[index] = value;
if (! --remaining) {
resolve(results);
}
};
}
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolver(i), reject);
} else {
results[i] = promise;
}
}
if (!remaining) {
resolve(results);
}
});
};
Promise.race = function (promises) {
if (!Array.isArray(promises)) {
throw new TypeError('You must pass an array to Promise.race().');
}
return new Promise(function (resolve, reject) {
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolve, reject);
} else {
resolve(promise);
}
}
});
};
Promise.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function (reason) {
return new Promise(function (resolve, reject) {
reject(reason);
});
};
module.exports = Promise;
}
},
"testcafe-release": {
"src": {
"browser": {
"connection": {
"command.js": function (exports, module, require) {
exports.__esModule = true;
// --------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// --------------------------------------------------------
exports.default = {
run: 'run',
idle: 'idle'
};
module.exports = exports['default'];
},
"status.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = {
ok: 'ok',
closing: 'closing'
};
module.exports = exports['default'];
},
"unstable-network-mode.js": function (exports, module, require) {
exports.__esModule = true;
var UNSTABLE_NETWORK_MODE_HEADER = exports.UNSTABLE_NETWORK_MODE_HEADER = 'x-testcafe-cache-page-request';
}
}
},
"client": {
"browser": {
"index.js": function (exports, module, require) {
exports.__esModule = true;
exports.sendXHR = sendXHR;
exports.startHeartbeat = startHeartbeat;
exports.startInitScriptExecution = startInitScriptExecution;
exports.stopInitScriptExecution = stopInitScriptExecution;
exports.redirect = redirect;
exports.fetchPageToCache = fetchPageToCache;
exports.checkStatus = checkStatus;
exports.enableRetryingTestPages = enableRetryingTestPages;
exports.disableRetryingTestPages = disableRetryingTestPages;
exports.isRetryingTestPagesEnabled = isRetryingTestPagesEnabled;
var _pinkie = require('pinkie');
var _pinkie2 = _interopRequireDefault(_pinkie);
var _command = require('../../browser/connection/command');
var _command2 = _interopRequireDefault(_command);
var _status = require('../../browser/connection/status');
var _status2 = _interopRequireDefault(_status);
var _unstableNetworkMode = require('../../browser/connection/unstable-network-mode');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// TODO: once we'll have client commons load it from there instead of node modules (currently it's leads to two copies of this packages on client)
var HEARTBEAT_INTERVAL = 2 * 1000;
var allowInitScriptExecution = false;
var retryTestPages = false;
var noop = function noop() {
return void 0;
};
var delay = function delay(ms) {
return new _pinkie2.default(function (resolve) {
return setTimeout(resolve, ms);
});
};
var FETCH_PAGE_TO_CACHE_RETRY_DELAY = 300;
var FETCH_PAGE_TO_CACHE_RETRY_COUNT = 5;
//Utils
// NOTE: the window.XMLHttpRequest may have been wrapped by Hammerhead, while we should send a request to
// the original URL. That's why we need the XMLHttpRequest argument to send the request via native methods.
function sendXHR(url, createXHR) {
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref$method = _ref.method,
method = _ref$method === undefined ? 'GET' : _ref$method,
_ref$data = _ref.data,
data = _ref$data === undefined ? null : _ref$data,
_ref$parseResponse = _ref.parseResponse,
parseResponse = _ref$parseResponse === undefined ? true : _ref$parseResponse;
return new _pinkie2.default(function (resolve, reject) {
var xhr = createXHR();
xhr.open(method, url, true);
if (isRetryingTestPagesEnabled()) {
xhr.setRequestHeader(_unstableNetworkMode.UNSTABLE_NETWORK_MODE_HEADER, 'true');
xhr.setRequestHeader('accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var responseText = xhr.responseText || '';
if (responseText && parseResponse) responseText = JSON.parse(xhr.responseText); //eslint-disable-line no-restricted-globals
resolve(responseText);
} else reject('disconnected');
}
};
xhr.send(data);
});
}
function isCurrentLocation(url) {
/*eslint-disable no-restricted-properties*/
return document.location.href.toLowerCase() === url.toLowerCase();
/*eslint-enable no-restricted-properties*/
}
//API
function startHeartbeat(heartbeatUrl, createXHR) {
function heartbeat() {
sendXHR(heartbeatUrl, createXHR).then(function (status) {
if (status.code === _status2.default.closing && !isCurrentLocation(status.url)) {
stopInitScriptExecution();
document.location = status.url;
}
});
}
window.setInterval(heartbeat, HEARTBEAT_INTERVAL);
heartbeat();
}
function executeInitScript(initScriptUrl, createXHR) {
if (!allowInitScriptExecution) return;
sendXHR(initScriptUrl, createXHR).then(function (res) {
if (!res.code) return null;
/* eslint-disable no-eval, no-restricted-globals*/
return sendXHR(initScriptUrl, createXHR, { method: 'POST', data: JSON.stringify(eval(res.code)) });
/* eslint-enable no-eval, no-restricted-globals */
}).then(function () {
window.setTimeout(function () {
return executeInitScript(initScriptUrl, createXHR);
}, 1000);
});
}
function startInitScriptExecution(initScriptUrl, createXHR) {
allowInitScriptExecution = true;
executeInitScript(initScriptUrl, createXHR);
}
function stopInitScriptExecution() {
allowInitScriptExecution = false;
}
function redirect(command) {
stopInitScriptExecution();
document.location = command.url;
}
function fetchPageToCache(pageUrl, createXHR) {
var requestAttempt = function requestAttempt() {
return sendXHR(pageUrl, createXHR, { parseResponse: false });
};
var retryRequest = function retryRequest() {
return delay(FETCH_PAGE_TO_CACHE_RETRY_DELAY).then(requestAttempt);
};
var fetchPagePromise = requestAttempt();
for (var i = 0; i < FETCH_PAGE_TO_CACHE_RETRY_COUNT; i++) {
fetchPagePromise = fetchPagePromise.catch(retryRequest);
}return fetchPagePromise.catch(noop);
}
function checkStatus(statusUrl, createXHR, opts) {
var _ref2 = opts || {},
manualRedirect = _ref2.manualRedirect;
return sendXHR(statusUrl, createXHR).then(function (result) {
var ensurePagePromise = _pinkie2.default.resolve();
if (result.url && isRetryingTestPagesEnabled()) ensurePagePromise = fetchPageToCache(result.url, createXHR);
return ensurePagePromise.then(function () {
return result;
});
}).then(function (result) {
var redirecting = (result.cmd === _command2.default.run || result.cmd === _command2.default.idle) && !isCurrentLocation(result.url);
if (redirecting && !manualRedirect) redirect(result);
return { command: result, redirecting: redirecting };
});
}
function enableRetryingTestPages() {
retryTestPages = true;
}
function disableRetryingTestPages() {
retryTestPages = false;
}
function isRetryingTestPagesEnabled() {
return retryTestPages;
}
}
},
"core": {
"deps": {
"hammerhead.js": function (exports, module, require) {
exports.__esModule = true;
exports.default = window['%hammerhead%'];
module.exports = exports['default'];
}
},
"index.js": function (exports, module, require) {
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _keyMaps = require('./utils/key-maps');
var _keyMaps2 = _interopRequireDefault(_keyMaps);
var _nodeTypeDescriptions = require('./utils/node-type-descriptions');
var _nodeTypeDescriptions2 = _interopRequireDefault(_nodeTypeDescriptions);
var _requestBarrier = require('./request-barrier');
var _requestBarrier2 = _interopRequireDefault(_requestBarrier);
var _pageUnloadBarrier = require('./page-unload-barrier');
var pageUnloadBarrier = _interopRequireWildcard(_pageUnloadBarrier);
var _preventRealEvents = require('./prevent-real-events');
var _scrollController = require('./scroll-controller');
var _scrollController2 = _interopRequireDefault(_scrollController);
var _service = require('./utils/service');
var serviceUtils = _interopRequireWildcard(_service);
var _dom = require('./utils/dom');
var domUtils = _interopRequireWildcard(_dom);
var _contentEditable = require('./utils/content-editable');
var contentEditable = _interopRequireWildcard(_contentEditable);
var _position = require('./utils/position');
var positionUtils = _interopRequireWildcard(_position);
var _style = require('./utils/style');
var styleUtils = _interopRequireWildcard(_style);
var _event = require('./utils/event');
var eventUtils = _interopRequireWildcard(_event);
var _array = require('./utils/array');
var arrayUtils = _interopRequireWildcard(_array);
var _promise = require('./utils/promise');
var promiseUtils = _interopRequireWildcard(_promise);
var _textSelection = require('./utils/text-selection');
var textSelection = _interopRequireWildcard(_textSelection);
var _waitFor = require('./utils/wait-for');
var _waitFor2 = _interopRequireDefault(_waitFor);
var _delay = require('./utils/delay');
var _delay2 = _interopRequireDefault(_delay);
var _getTimeLimitedPromise = require('./utils/get-time-limited-promise');
var _getTimeLimitedPromise2 = _interopRequireDefault(_getTimeLimitedPromise);
var _noop = require('./utils/noop');
var _noop2 = _interopRequireDefault(_noop);
var _getKeyArray = require('./utils/get-key-array');
var _getKeyArray2 = _interopRequireDefault(_getKeyArray);
var _getSanitizedKey = require('./utils/get-sanitized-key');
var _getSanitizedKey2 = _interopRequireDefault(_getSanitizedKey);
var _parseKeySequence = require('./utils/parse-key-sequence');
var _parseKeySequence2 = _interopRequireDefault(_parseKeySequence);
var _sendRequestToFrame = require('./utils/send-request-to-frame');
var _sendRequestToFrame2 = _interopRequireDefault(_sendRequestToFrame);
var _browser = require('../browser');
var browser = _interopRequireWildcard(_browser);
var _selectorTextFilter = require('../../client-functions/selectors/selector-text-filter');
var _selectorTextFilter2 = _interopRequireDefault(_selectorTextFilter);
var _selectorAttributeFilter = require('../../client-functions/selectors/selector-attribute-filter');
var _selectorAttributeFilter2 = _interopRequireDefault(_selectorAttributeFilter);
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 }; }
exports.RequestBarrier = _requestBarrier2.default;
exports.pageUnloadBarrier = pageUnloadBarrier;
exports.preventRealEvents = _preventRealEvents.preventRealEvents;
exports.disableRealEventsPreventing = _preventRealEvents.disableRealEventsPreventing;
exports.scrollController = _scrollController2.default;
exports.serviceUtils = serviceUtils;
exports.domUtils = domUtils;
exports.contentEditable = contentEditable;
exports.positionUtils = positionUtils;
exports.styleUtils = styleUtils;
exports.eventUtils = eventUtils;
exports.arrayUtils = arrayUtils;
exports.promiseUtils = promiseUtils;
exports.textSelection = textSelection;
exports.waitFor = _waitFor2.default;
exports.delay = _delay2.default;
exports.getTimeLimitedPromise = _getTimeLimitedPromise2.default;
exports.noop = _noop2.default;
exports.getKeyArray = _getKeyArray2.default;
exports.getSanitizedKey = _getSanitizedKey2.default;
exports.parseKeySequence = _parseKeySequence2.default;
exports.sendRequestToFrame = _sendRequestToFrame2.default;
exports.KEY_MAPS = _keyMaps2.default;
exports.NODE_TYPE_DESCRIPTIONS = _nodeTypeDescriptions2.default;
exports.browser = browser;
exports.selectorTextFilter = _selectorTextFilter2.default;
exports.selectorAttributeFilter = _selectorAttributeFilter2.default;
exports.get = require;
var nativeMethods = _hammerhead2.default.nativeMethods;
var evalIframeScript = _hammerhead2.default.EVENTS.evalIframeScript;
nativeMethods.objectDefineProperty(window, '%testCafeCore%', { configurable: true, value: exports });
// NOTE: initTestCafeCore defined in wrapper template
/* global initTestCafeCore */
_hammerhead2.default.on(evalIframeScript, function (e) {
return initTestCafeCore(nativeMethods.contentWindowGetter.call(e.iframe), true);
});
},
"page-unload-barrier.js": function (exports, module, require) {
exports.__esModule = true;
exports.init = init;
exports.watchForPageNavigationTriggers = watchForPageNavigationTriggers;
exports.wait = wait;
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _event = require('./utils/event');
var eventUtils = _interopRequireWildcard(_event);
var _delay = require('./utils/delay');
var _delay2 = _interopRequireDefault(_delay);
var _clientMessages = require('../../test-run/client-messages');
var _clientMessages2 = _interopRequireDefault(_clientMessages);
var _dom = require('./utils/dom');
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 browserUtils = _hammerhead2.default.utils.browser;
var nativeMethods = _hammerhead2.default.nativeMethods;
var transport = _hammerhead2.default.transport;
var DEFAULT_BARRIER_TIMEOUT = 400;
var SHORT_WAIT_FOR_UNLOAD_TIMEOUT = 30;
var FILE_DOWNLOAD_CHECK_DELAY = 500;
var MAX_UNLOADING_TIMEOUT = 15 * 1000;
var waitingForUnload = false;
var waitingForUnloadTimeoutId = null;
var waitingPromiseResolvers = [];
var unloading = false;
var pageNavigationTriggeredListener = null;
var pageNavigationTriggered = false;
function onBeforeUnload() {
if (!browserUtils.isIE) {
unloading = true;
return;
}
prolongUnloadWaiting(SHORT_WAIT_FOR_UNLOAD_TIMEOUT);
(0, _delay2.default)(0).then(function () {
// NOTE: except file downloading
if (document.readyState === 'loading') {
var activeElement = nativeMethods.documentActiveElementGetter.call(document);
if (!activeElement || !(0, _dom.isAnchorElement)(activeElement) || !activeElement.hasAttribute('download')) unloading = true;
}
});
}
function prolongUnloadWaiting(timeout) {
if (waitingForUnloadTimeoutId) nativeMethods.clearTimeout.call(window, waitingForUnloadTimeoutId);
waitingForUnload = true;
waitingForUnloadTimeoutId = nativeMethods.setTimeout.call(window, function () {
waitingForUnloadTimeoutId = null;
waitingForUnload = false;
waitingPromiseResolvers.forEach(function (resolve) {
return resolve();
});
waitingPromiseResolvers = [];
}, timeout);
}
function waitForFileDownload() {
return new Promise(function (resolve) {
nativeMethods.setTimeout.call(window, function () {
transport.queuedAsyncServiceMsg({ cmd: _clientMessages2.default.waitForFileDownload }).then(function (fileDownloadingHandled) {
// NOTE: we use a flag to confirm file download because if unload
// is raised the browser can respond with an empty string
if (fileDownloadingHandled) resolve();
});
}, FILE_DOWNLOAD_CHECK_DELAY);
});
}
// API
function init() {
_hammerhead2.default.on(_hammerhead2.default.EVENTS.beforeUnload, onBeforeUnload);
eventUtils.bind(window, 'unload', function () {
unloading = true;
});
}
function watchForPageNavigationTriggers() {
pageNavigationTriggeredListener = function pageNavigationTriggeredListener() {
pageNavigationTriggered = true;
};
_hammerhead2.default.on(_hammerhead2.default.EVENTS.pageNavigationTriggered, pageNavigationTriggeredListener);
}
function wait(timeout) {
var waitForUnloadingPromise = new Promise(function (resolve) {
if (timeout === void 0) timeout = !pageNavigationTriggeredListener || pageNavigationTriggered ? DEFAULT_BARRIER_TIMEOUT : 0;
if (pageNavigationTriggeredListener) {
_hammerhead2.default.off(_hammerhead2.default.EVENTS.pageNavigationTriggered, pageNavigationTriggeredListener);
pageNavigationTriggeredListener = null;
}
(0, _delay2.default)(timeout).then(function () {
if (unloading) {
waitForFileDownload().then(function () {
unloading = false;
resolve();
});
return;
}
if (!waitingForUnload) resolve();else waitingPromiseResolvers.push(resolve);
});
});
// NOTE: sometimes the page isn't actually unloaded after the beforeunload event
// fires (see issues #664, #437). To avoid test hanging, we resolve the unload
// barrier waiting promise in MAX_UNLOADING_TIMEOUT. We can improve this logic when
// the https://github.com/DevExpress/testcafe-hammerhead/issues/667 issue is fixed.
var watchdog = (0, _delay2.default)(MAX_UNLOADING_TIMEOUT).then(function () {
unloading = false;
});
return Promise.race([waitForUnloadingPromise, watchdog]);
}
},
"prevent-real-events.js": function (exports, module, require) {
exports.__esModule = true;
exports.preventRealEvents = preventRealEvents;
exports.disableRealEventsPreventing = disableRealEventsPreventing;
var _hammerhead = require('./deps/hammerhead');
var _scrollController = require('./scroll-controller');
var _scrollController2 = _interopRequireDefault(_scrollController);
var _style = require('./utils/style');
var _array = require('./utils/array');
var _dom = require('./utils/dom');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var browserUtils = _hammerhead.utils.browser;
var listeners = _hammerhead.eventSandbox.listeners;
var eventSimulator = _hammerhead.eventSandbox.eventSimulator;
var PREVENTED_EVENTS = ['click', 'mousedown', 'mouseup', 'dblclick', 'contextmenu', 'mousemove', 'mouseover', 'mouseout', 'touchstart', 'touchmove', 'touchend', 'keydown', 'keypress', 'input', 'keyup', 'change', 'focus', 'blur', 'MSPointerDown', 'MSPointerMove', 'MSPointerOver', 'MSPointerOut', 'MSPointerUp', 'pointerdown', 'pointermove', 'pointerover', 'pointerout', 'pointerup'];
var F12_KEY_CODE = 123;
function checkBrowserHotkey(e) {
// NOTE: Opening browser tools with F12, CTRL+SHIFT+<SYMBOL KEY>
// on PC or with OPTION(ALT)+CMD+<SYMBOL KEY> on Mac.
return e.shiftKey && e.ctrlKey || (e.altKey || e.metaKey) && browserUtils.isMacPlatform || e.keyCode === F12_KEY_CODE;
}
// NOTE: when tests are running, we should block real events (from mouse
// or keyboard), because they may lead to unexpected test result.
function preventRealEventHandler(e, dispatched, preventDefault, cancelHandlers, stopEventPropagation) {
var target = e.target || e.srcElement;
if (!dispatched && !(0, _dom.isShadowUIElement)(target)) {
// NOTE: this will allow pressing hotkeys to open developer tools.
if (/^key/.test(e.type) && checkBrowserHotkey(e)) {
stopEventPropagation();
return;
}
// NOTE: if an element loses focus because of becoming invisible, the blur event is
// raised. We must not prevent this blur event. In IE, an element loses focus only
// if the CSS 'display' property is set to 'none', other ways of making an element
// invisible don't lead to blurring (in MSEdge, focus/blur are sync).
if (e.type === 'blur') {
if (browserUtils.isIE && browserUtils.version < 12) {
var isWindowInstance = (0, _dom.isWindow)(target);
var isElementInvisible = !isWindowInstance && (0, _style.get)(target, 'display') === 'none';
var elementParents = null;
var invisibleParents = false;
if (!isWindowInstance && !isElementInvisible) {
elementParents = (0, _dom.getParents)(target);
invisibleParents = (0, _array.filter)(elementParents, function (parent) {
return (0, _style.get)(parent, 'display') === 'none';
});
}
if (isElementInvisible || invisibleParents.length) {
// NOTE: In IE we should prevent the event and raise it on timeout. This is a fix for
// the case when a focus event leads to the element disappearing. If we don't prevent
// the blur event it will be raised before the previous focus event is raised (see B254768)
_hammerhead.eventSandbox.timers.deferFunction(function () {
eventSimulator.blur(target);
});
}
}
// NOTE: fix for a jQuery bug. An exception is raised when calling .is(':visible')
// for a window or document on page loading (when e.ownerDocument is null).
else if (target !== window && target !== window.document && !(0, _style.hasDimensions)(target)) return;
}
preventDefault();
}
}
function preventRealEvents() {
listeners.initElementListening(window, PREVENTED_EVENTS);
listeners.addFirstInternalHandler(window, PREVENTED_EVENTS, preventRealEventHandler);
_scrollController2.default.init();
}
function disableRealEventsPreventing() {
listeners.removeInternalEventListener(window, PREVENTED_EVENTS, preventRealEventHandler);
}
},
"request-barrier.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('./deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
var _delay = require('./utils/delay');
var _delay2 = _interopRequireDefault(_delay);
var _array = require('./utils/array');
var _service = require('./utils/service');
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 nativeMethods = _hammerhead2.default.nativeMethods;
var REQUESTS_COLLECTION_DELAY_DEFAULT = 50;
var REQUESTS_FINISHED_EVENT = 'requests-finished';
var GLOBAL_REQUEST_BARRIER_FIELD = 'testcafe|request-barrier';
var RequestBarrier = function (_EventEmitter) {
_inherits(RequestBarrier, _EventEmitter);
function RequestBarrier() {
var delays = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, RequestBarrier);
var _this = _possibleConstructorReturn(this, _EventEmitter.call(this));
_this.BARRIER_TIMEOUT = 3000;
_this.delays = {
requestsCollection: delays.requestsCollection === void 0 ? REQUESTS_COLLECTION_DELAY_DEFAULT : delays.requestsCollection,
additionalRequestsCollection: delays.additionalRequestsCollection === void 0 ? REQUESTS_COLLECTION_DELAY_DEFAULT : delays.additionalRequestsCollection,
pageInitialRequestsCollection: delays.pageInitialRequestsCollection === void 0 ? REQUESTS_COLLECTION_DELAY_DEFAULT : delays.pageInitialRequestsCollection
};
_this.collectingReqs = true;
_this.requests = [];
_this.watchdog = null;
_this._unbindHandlers = null;
_this._init();
return _this;
}
RequestBarrier.prototype._init = function _init() {
var _this2 = this;
var onXhrSend = function onXhrSend(e) {
return _this2._onXhrSend(e.xhr);
};
var onXhrCompleted = function onXhrCompleted(e) {
return _this2._onRequestCompleted(e.xhr);
};
var onXhrError = function onXhrError(e) {
return _this2._onRequestError(e.xhr, e.err);
};
var onFetchSend = function onFetchSend(e) {
return _this2._onFetchSend(e);
};
_hammerhead2.default.on(_hammerhead2.default.EVENTS.beforeXhrSend, onXhrSend);
_hammerhead2.default.on(_hammerhead2.default.EVENTS.xhrCompleted, onXhrCompleted);
_hammerhead2.default.on(_hammerhead2.default.EVENTS.xhrError, onXhrError);
_hammerhead2.default.on(_hammerhead2.default.EVENTS.fetchSent, onFetchSend);
this._unbindHandlers = function () {
_hammerhead2.default.off(_hammerhead2.default.EVENTS.beforeXhrSend, onXhrSend);
_hammerhead2.default.off(_hammerhead2.default.EVENTS.xhrCompleted, onXhrCompleted);
_hammerhead2.default.off(_hammerhead2.default.EVENTS.xhrError, onXhrError);
_hammerhead2.default.off(_hammerhead2.default.EVENTS.fetchSent, onFetchSend);
};
};
RequestBarrier.prototype._onXhrSend = function _onXhrSend(request) {
if (this.collectingReqs) this.requests.push(request);
};
RequestBarrier.prototype._onRequestCompleted = function _onRequestCompleted(request) {
var _this3 = this;
// NOTE: let the last real XHR handler finish its job and try to obtain
// any additional requests if they were initiated by this handler
(0, _delay2.default)(this.delays.additionalRequestsCollection).then(function () {
return _this3._onRequestFinished(request);
});
};
RequestBarrier.prototype._onRequestError = function _onRequestError(request) {
this._onRequestFinished(request);
};
RequestBarrier.prototype._onRequestFinished = function _onRequestFinished(request) {
if ((0, _array.indexOf)(this.requests, request) > -1) {
(0, _array.remove)(this.requests, request);
if (!this.collectingReqs && !this.requests.length) this.emit(REQUESTS_FINISHED_EVENT);
}
};
RequestBarrier.prototype._onFetchSend = function _onFetchSend(request) {
var _this4 = this;
if (this.collectingReqs) {
this.requests.push(request);
request.then(function () {
return _this4._onRequestCompleted(request);
}).catch(function () {
return _this4._onRequestError(request);
});
}
};
RequestBarrier.prototype.wait = function wait(isPageLoad) {
var _this5 = this;
return new Promise(function (resolve) {
(0, _delay2.default)(isPageLoad ? _this5.delays.pageInitialRequestsCollection : _this5.delays.requestsCollection).then(function () {
_this5.collectingReqs = false;
var onRequestsFinished = function onRequestsFinished() {
if (_this5.watchdog) nativeMethods.clearTimeout.call(window, _this5.watchdog);
_this5._unbindHandlers();
resolve();
};
if (_this5.requests.length) {
_this5.watchdog = nativeMethods.setTimeout.call(window, onRequestsFinished, _this5.BARRIER_TIMEOUT);
_this5.on(REQUESTS_FINISHED_EVENT, onRequestsFinished);
} else onRequestsFinished();
});
});
};
return RequestBarrier;
}(_service.EventEmitter);
exports.default = RequestBarrier;
RequestBarrier.GLOBAL_REQUEST_BARRIER_FIELD = GLOBAL_REQUEST_BARRIER_FIELD;
window[RequestBarrier.GLOBAL_REQUEST_BARRIER_FIELD] = RequestBarrier;
module.exports = exports['default'];
},
"scroll-controller.js": function (exports, module, require) {
exports.__esModule = true;
var _hammerhead = require('./deps/hammerhead');
var _service = require('./utils/service');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var listeners = _hammerhead.eventSandbox.listeners;
var ScrollController = function () {
function ScrollController() {
_classCallCheck(this, ScrollController);
this.initialized = false;
this.stopPropagationFlag = false;
this.events = new _service.EventEmitter();
}
ScrollController.prototype._internalListener = function _internalListener(event, dispatched, preventEvent, cancelHandlers, stopPropagation) {
this.events.emit('scroll', event);
if (this.stopPropagationFlag) {
cancelHandlers();
stopPropagation();
}
};
ScrollController.prototype.init = function init() {
var _this = this;
if (this.initialized) return;
this.initialized = true;
listeners.initElementListening(window, ['scroll']);
listeners.addFirstInternalHandler(window, ['scroll'], function () {
return _this._internalListener.apply(_this, arguments);
});
};
ScrollController.prototype.waitForScroll = function waitForScroll() {
var _this2 = this;
var promiseResolver = null;
var promise = new _hammerhead.Promise(function (resolve) {
promiseResolver = resolve;
});
promise.cancel = function () {
return _this2.events.off('scroll', promiseResolver);
};
if (this.initialized) this.events.once('scroll', promiseResolver);else promiseResolver();
return promise;
};
ScrollController.prototype.stopPropagation = function stopPropagation() {
this.stopPropagationFlag = true;
};
ScrollController.prototype.enablePropagation = function enablePropagation() {
this.stopPropagationFlag = false;
};
return ScrollController;
}();
exports.default = new ScrollController();
module.exports = exports['default'];
},
"utils": {
"array.js": function (exports, module, require) {
exports.__esModule = true;
exports.toArray = toArray;
exports.reverse = reverse;
exports.isArray = isArray;
exports.find = find;
exports.indexOf = indexOf;
exports.forEach = forEach;
exports.some = some;
exports.map = map;
exports.filter = filter;
exports.reduce = reduce;
exports.remove = remove;
exports.equals = equals;
exports.getCommonElement = getCommonElement;
var _hammerhead = require('../deps/hammerhead');
var _hammerhead2 = _interopRequireDefault(_hammerhead);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var nativeIndexOf = Array.prototype.indexOf;
var nativeForEach = Array.prototype.forEach;
var nativeSome = Array.prototype.some;
var nativeMap = Array.prototype.map;
var nativeFilter = Array.prototype.filter;
var nativeReverse = Array.prototype.reverse;
var nativeReduce = Array.prototype.reduce;
var nativeSplice = Array.prototype.splice;
function toArray(arg) {
var arr = [];
var length = arg.length;
for (var i = 0; i < length; i++) {
arr.push(arg[i]);
}return arr;
}
function reverse(arr) {
return nativeReverse.call(arr);
}
function isArray(arg) {
return _hammerhead2.default.nativeMethods.objectToString.call(arg) === '[object Array]';
}
function find(arr, callback) {
var length = arr.length;
for (var i = 0; i < length; i++) {
if (callback(arr[i], i, arr)) return arr[i];
}
return null;
}
function indexOf(arr, arg) {
return nativeIndexOf.call(arr, arg);
}
function forEach(arr, callback) {
nativeForEach.call(arr, callback);
}
function some(arr, callback) {
return nativeSome.call(arr, callback);
}
function map(arr, callback) {
return nativeMap.call(arr, callback);
}
function filter(arr, callback) {
return nativeFilter.call(arr, callback);
}
function reduce(arr, callback, initialValue) {
return nativeReduce.call(arr, callback, initialValue);
}
function remove(arr, item) {
var index = indexOf(arr, item);
if (index > -1) nativeSplice.call(arr, index, 1);
}
function equals(arr1, arr2) {
if (arr1.length !== arr2.length) return false;
for (var i = 0, l = arr1.length; i < l; i++) {
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
function getCommonElement(arr1, arr2) {
for (var i = 0; i < arr1.length; i++) {
for (var t = 0; t < arr2.length; t++) {
if (arr1[i] === arr2[t]) return arr1[i];
}
}
return null;
}
},
"content-editable.js": function (exports, module, require) {
exports.__esModule = true;
exports.getFirstVisibleTextNode = getFirstVisibleTextNode;
exports.getLastTextNode = getLastTextNode;
exports.getFirstNonWhitespaceSymbolIndex = getFirstNonWhitespaceSymbolIndex;
exports.getLastNonWhitespaceSymbolIndex = getLastNonWhitespaceSymbolIndex;
exports.isInvisibleTextNode = isInvisibleTextNode;
exports.findContentEditableParent = findContentEditableParent;
exports.getNearestCommonAncestor = getNearestCommonAncestor;
exports.getSelection = getSelection;
exports.getSelectionStartPosition = getSelectionStartPosition;
exports.getSelectionEndPosition = getSelectionEndPosition;
exports.calculateNodeAndOffsetByPosition = calculateNodeAndOffsetByPosition;
exports.calculatePositionByNodeAndOffset = calculatePositionByNodeAndOffset;
exports.getElementBySelection = getElementBySelection;
exports.getFirstVisiblePosition = getFirstVisiblePosition;
exports.getLastVisiblePosition = getLastVisiblePosition;
exports.getContentEditableValue = getContentEditableValue;
var _dom = require('./dom');
var domUtils = _interopRequireWildcard(_dom);
var _array = require('./array');
var arrayUtils = _interopRequireWildcard(_array);
var _style = require('./style');
var styleUtils = _interopRequireWildcard(_style);
var _hammerhead = require('../../driver/deps/hammerhead');
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; } }
//nodes utils
function getOwnFirstVisibleTextNode(el) {
var children