forked from enviPath/enviPy
281 lines
8.0 KiB
JavaScript
281 lines
8.0 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _promise = require('babel-runtime/core-js/promise');
|
|
|
|
var _promise2 = _interopRequireDefault(_promise);
|
|
|
|
var _keys = require('babel-runtime/core-js/object/keys');
|
|
|
|
var _keys2 = _interopRequireDefault(_keys);
|
|
|
|
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
|
|
|
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
|
|
|
var _createClass2 = require('babel-runtime/helpers/createClass');
|
|
|
|
var _createClass3 = _interopRequireDefault(_createClass2);
|
|
|
|
var _q = require('q');
|
|
|
|
var _q2 = _interopRequireDefault(_q);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
/**
|
|
* Multibrowser
|
|
*/
|
|
var Multibrowser = function () {
|
|
function Multibrowser() {
|
|
(0, _classCallCheck3.default)(this, Multibrowser);
|
|
|
|
this.instances = {};
|
|
this.promiseBucket = [];
|
|
|
|
var defer = _q2.default.defer();
|
|
this.qResolve = defer.resolve.toString();
|
|
}
|
|
|
|
/**
|
|
* add instance to multibrowser instance
|
|
*/
|
|
|
|
|
|
(0, _createClass3.default)(Multibrowser, [{
|
|
key: 'addInstance',
|
|
value: function addInstance(browserName, client) {
|
|
if (this.instances[browserName]) {
|
|
throw new Error('webdriver instance "' + browserName + '" is already defined');
|
|
}
|
|
this.instances[browserName] = client;
|
|
}
|
|
|
|
/**
|
|
* modifier for multibrowser instance
|
|
*/
|
|
|
|
}, {
|
|
key: 'getModifier',
|
|
value: function getModifier() {
|
|
return multiremoteModifier.bind(this);
|
|
}
|
|
|
|
/**
|
|
* flush bucket and return current pending promises
|
|
*/
|
|
|
|
}, {
|
|
key: 'flushPromiseBucket',
|
|
value: function flushPromiseBucket() {
|
|
var bucket = this.promiseBucket.filter(function (promise) {
|
|
return promise.inspect().state === 'pending';
|
|
});
|
|
this.promiseBucket = [];
|
|
return bucket;
|
|
}
|
|
|
|
/**
|
|
* modifier for single webdriverio instances
|
|
*/
|
|
|
|
}, {
|
|
key: 'getInstanceModifier',
|
|
value: function getInstanceModifier() {
|
|
return instanceModifier.bind(this);
|
|
}
|
|
}]);
|
|
return Multibrowser;
|
|
}();
|
|
|
|
function instanceModifier(client) {
|
|
var _next = client.next;
|
|
var multibrowser = this;
|
|
|
|
/**
|
|
* Overwrite next (bind) method to put each command into a bucket.
|
|
* This provides us useful information about all current running
|
|
* commands.
|
|
*/
|
|
client.next = function () {
|
|
multibrowser.promiseBucket.push(this.promise);
|
|
return _next.apply(this, arguments);
|
|
};
|
|
|
|
return client;
|
|
}
|
|
|
|
function multiremoteModifier(client) {
|
|
var multibrowser = this;
|
|
var browserNames = (0, _keys2.default)(multibrowser.instances);
|
|
|
|
client.getInstances = function () {
|
|
return browserNames;
|
|
};
|
|
|
|
client.next = function () {
|
|
var _this = this;
|
|
|
|
var promises = [];
|
|
|
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
var fnName = args.pop();
|
|
|
|
/**
|
|
* no need for actual function here
|
|
*/
|
|
args.shift();
|
|
|
|
/**
|
|
* flush promise bucket
|
|
*/
|
|
multibrowser.promiseBucket = [];
|
|
var commandArgs = args.pop();
|
|
return this.lastPromise.done(function () {
|
|
browserNames.forEach(function (browserName) {
|
|
var instance = multibrowser.instances[browserName];
|
|
promises.push(instance[fnName].apply(instance, commandArgs).promise);
|
|
});
|
|
|
|
return _promise2.default.all(promises).then(function (result) {
|
|
/**
|
|
* custom event handling since multibrowser instance
|
|
* actually never executes any command
|
|
*/
|
|
var payload = {
|
|
fnName: fnName
|
|
};
|
|
|
|
for (var i = 0; i < browserNames.length; ++i) {
|
|
payload[browserNames[i]] = result[i];
|
|
}
|
|
|
|
if (fnName.match(/(init|end)/)) {
|
|
_this.emit(fnName, payload);
|
|
}
|
|
|
|
_this.emit('result', payload);
|
|
_this.defer.resolve(result);
|
|
}, function (err) {
|
|
_this.emit('error', err);
|
|
_this.defer.reject(err);
|
|
});
|
|
});
|
|
};
|
|
|
|
var _then = client.then;
|
|
client.then = function (onFulfilled, onRejected) {
|
|
/**
|
|
* curry arguments
|
|
* as multibrowser commands return with an array of results for each instance
|
|
* respectively (see q.all) we need to curry them (expand arguments) to help
|
|
* users to better work with the results
|
|
*
|
|
* uncurried original version:
|
|
* ```js
|
|
* matrix.getTitle().then(function (result) {
|
|
* expect(result[0]).to.be.equal('title of browser A')
|
|
* expect(result[1]).to.be.equal('title of browser B')
|
|
* })
|
|
* ```
|
|
*
|
|
* curried version:
|
|
* ```js
|
|
* matrix.getTitle().then(function (result) {
|
|
* expect(result.browserA).to.be.equal('title of browser A')
|
|
* expect(result.browserB).to.be.equal('title of browser B')
|
|
* })
|
|
* ```
|
|
*/
|
|
var curryArguments = function curryArguments(args) {
|
|
/**
|
|
* when returning with a promise within a multibrowser promise like
|
|
*
|
|
* ```js
|
|
* matrix.url(...).getTitle().then(function () {
|
|
* return matrix.getSource()
|
|
* })
|
|
* ```
|
|
*
|
|
* we will have problems as we are running through curryArguments twice.
|
|
* Therefor check if the onFulFilled handler is from the Q library and
|
|
* handle that promise as usual here.
|
|
* It's an ugly hack but the only way to get around with this and having
|
|
* nice curried arguments.
|
|
*
|
|
*/
|
|
if (onFulfilled.toString() === multibrowser.qResolve) {
|
|
return onFulfilled.apply(this, arguments);
|
|
}
|
|
if (arguments.length === 1 && !Array.isArray(args)) {
|
|
return onFulfilled.call(this, args);
|
|
}
|
|
|
|
if (arguments.length > 1) {
|
|
args = Array.prototype.slice.call(arguments);
|
|
}
|
|
|
|
var result = {};
|
|
for (var i = 0; i < browserNames.length; ++i) {
|
|
result[browserNames[i]] = args[i];
|
|
}
|
|
return onFulfilled.call(this, result);
|
|
};
|
|
|
|
if (!onFulfilled && !onRejected) {
|
|
return this;
|
|
}
|
|
|
|
if (onFulfilled && !onRejected) {
|
|
return _then.call(this, curryArguments);
|
|
}
|
|
|
|
if (onFulfilled && onRejected) {
|
|
return _then.call(this, curryArguments, onRejected);
|
|
}
|
|
|
|
return _then.call(this, undefined, onRejected);
|
|
};
|
|
|
|
client.select = function (browserName) {
|
|
var instance = multibrowser.instances[browserName];
|
|
|
|
if (!instance) {
|
|
throw new Error('browser name "' + browserName + '" was not defined');
|
|
}
|
|
|
|
instance.isMultibrowser = false;
|
|
return instance;
|
|
};
|
|
|
|
client.sync = function () {
|
|
var bucket = multibrowser.flushPromiseBucket();
|
|
return this.call(function () {
|
|
return _promise2.default.all(bucket);
|
|
});
|
|
};
|
|
|
|
var _addCommand = client.addCommand;
|
|
client.addCommand = function (fnName, fn, forceOverwrite) {
|
|
var _this2 = this;
|
|
|
|
var args = arguments;
|
|
_addCommand.apply(this, args);
|
|
(0, _keys2.default)(multibrowser.instances).forEach(function (browserName) {
|
|
var instance = multibrowser.instances[browserName];
|
|
instance.addCommand.apply(_this2, args);
|
|
});
|
|
return this;
|
|
};
|
|
|
|
return client;
|
|
}
|
|
|
|
exports.default = Multibrowser;
|
|
module.exports = exports['default']; |