cabbie-sync
Version:
A synchronous webdriver client
647 lines (453 loc) • 22.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _selectorTypes = require('./enums/selector-types');
var _selectorTypes2 = _interopRequireDefault(_selectorTypes);
var _driver = require('./driver');
var _driver2 = _interopRequireDefault(_driver);
var _options = require('./flow-types/options');
var _depd = require('depd');
var _depd2 = _interopRequireDefault(_depd);
var _url = require('url');
var _alert = require('./alert');
var _alert2 = _interopRequireDefault(_alert);
var _addDebugging = require('./add-debugging');
var _addDebugging2 = _interopRequireDefault(_addDebugging);
var _element = require('./element');
var _element2 = _interopRequireDefault(_element);
var _frame = require('./frame');
var _frame2 = _interopRequireDefault(_frame);
var _globalMouse = require('./global-mouse');
var _globalMouse2 = _interopRequireDefault(_globalMouse);
var _globalTouch = require('./global-touch');
var _globalTouch2 = _interopRequireDefault(_globalTouch);
var _navigator = require('./navigator');
var _navigator2 = _interopRequireDefault(_navigator);
var _baseWindow = require('./base-window');
var _baseWindow2 = _interopRequireDefault(_baseWindow);
var _windowHandle = require('./window-handle');
var _windowHandle2 = _interopRequireDefault(_windowHandle);
var _waitFor = require('./utils/wait-for');
var _waitFor2 = _interopRequireDefault(_waitFor);
var _flowRuntime = require('flow-runtime');
var _flowRuntime2 = _interopRequireDefault(_flowRuntime);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var Options = _flowRuntime2.default.tdz(function () {
return _options.Options;
}); /**
*
* This file is generated automatically, run npm run build to re-generate.
**/
var Driver = _flowRuntime2.default.tdz(function () {
return _driver2.default;
});
var SelectorType = _flowRuntime2.default.tdz(function () {
return _selectorTypes.SelectorType;
});
var deprecate = (0, _depd2.default)('cabbie');
/*
* This is an object representing the currently active window. You can access the navigation for that window,
* touch and mouse objects for interacting via screen coordinates, and (most imporatantly) getElement and getElements.
*/
var ActiveWindow = function (_BaseWindow) {
(0, _inherits3.default)(ActiveWindow, _BaseWindow);
/*
* Get the Alert object.
*/
/*
* Get the Navigator object.
*
* @private
*/
/*
* The global-touch object.
*/
function ActiveWindow(driver /*: Driver*/, options /*: Options*/) {
(0, _classCallCheck3.default)(this, ActiveWindow);
var _driverType = _flowRuntime2.default.ref(Driver);
var _optionsType = _flowRuntime2.default.ref(Options);
_flowRuntime2.default.param('driver', _driverType).assert(driver);
_flowRuntime2.default.param('options', _optionsType).assert(options);
var _this = (0, _possibleConstructorReturn3.default)(this, (ActiveWindow.__proto__ || (0, _getPrototypeOf2.default)(ActiveWindow)).call(this, driver, 'current'));
_this.touch = new _globalTouch2.default(_this.driver);
_this.mouse = new _globalMouse2.default(_this.driver);
_this.navigator = new _navigator2.default(_this.driver, options);
_this.frame = new _frame2.default(_this.driver);
_this.alert = new _alert2.default(_this.driver);
_this._options = options;
deprecate.property(_this, 'navigator', 'All properties of navigator are now directly available on the ActiveWindow object');
return _this;
}
/*
* Get a handle for the current window
*/
/*
* Get the Frame object.
*/
/*
* Get the global-mouse object.
*/
(0, _createClass3.default)(ActiveWindow, [{
key: 'getWindowHandle',
value: function getWindowHandle() /*: WindowHandle*/ {
var _returnType = _flowRuntime2.default.return(_flowRuntime2.default.ref(_windowHandle2.default));
var windowHandle = this.driver.requestJSON('GET', '/window_handle');
return _returnType.assert(new _windowHandle2.default(this.driver, windowHandle));
}
/*
* Execute a script on the browser and return the result.
*
* Source should be either a function body as a string or a function.
* Keep in mind that if it is a function it will not have access to
* any variables from the node.js process.
*/
}, {
key: 'execute',
value: function execute(script /*: string | Function*/) /*: any*/ {
var args /*: Array<any>*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var _scriptType = _flowRuntime2.default.union(_flowRuntime2.default.string(), _flowRuntime2.default.function());
var _argsType = _flowRuntime2.default.array(_flowRuntime2.default.any());
var _returnType2 = _flowRuntime2.default.return(_flowRuntime2.default.any());
_flowRuntime2.default.param('script', _scriptType).assert(script);
_flowRuntime2.default.param('args', _argsType).assert(args);
return _returnType2.assert(this.driver.requestJSON('POST', '/execute', { script: codeToString(script), args: args }));
}
/*
* Execute a script asynchronously on the browser.
*
* Source should be either a function body as a string or a function.
* Keep in mind that if it is a function it will not have access to
* any variables from the node.js process.
*/
}, {
key: 'asyncExecute',
value: function asyncExecute(script /*: string | Function*/) /*: void*/ {
var args /*: Array<any>*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var _scriptType2 = _flowRuntime2.default.union(_flowRuntime2.default.string(), _flowRuntime2.default.function());
var _argsType2 = _flowRuntime2.default.array(_flowRuntime2.default.any());
var _returnType3 = _flowRuntime2.default.return(_flowRuntime2.default.void());
_flowRuntime2.default.param('script', _scriptType2).assert(script);
_flowRuntime2.default.param('args', _argsType2).assert(args);
this.driver.requestJSON('POST', '/execute_async', { script: codeToString(script), args: args });
}
/*
* Type a string of characters into the browser
*
* Note: Modifier keys is kept between calls, so mouse interactions can be performed
* while modifier keys are depressed.
*/
}, {
key: 'sendKeys',
value: function sendKeys(str /*: string | Array<string>*/) /*: void*/ {
var _strType = _flowRuntime2.default.union(_flowRuntime2.default.string(), _flowRuntime2.default.array(_flowRuntime2.default.string()));
var _returnType4 = _flowRuntime2.default.return(_flowRuntime2.default.void());
_flowRuntime2.default.param('str', _strType).assert(str);
this.driver.requestJSON('POST', '/keys', { value: Array.isArray(str) ? str : [str] });
}
/*
* Take a screenshot of the current page
*
* This returns the result as a buffer containing the binary image data
*/
}, {
key: 'takeScreenshot',
value: function takeScreenshot() /*: Buffer*/ {
var _returnType5 = _flowRuntime2.default.return(_flowRuntime2.default.ref('Buffer'));
var base64data = this.driver.requestJSON('GET', '/screenshot');
return _returnType5.assert(Buffer.from ? Buffer.from(base64data, 'base64') : new Buffer(base64data, 'base64'));
}
/*
* Get the element on the page that currently has focus
*/
}, {
key: 'getActiveElement',
value: function getActiveElement() /*: Element*/ {
var _returnType6 = _flowRuntime2.default.return(_flowRuntime2.default.ref(_element2.default));
var elementHandle = this.driver.requestJSON('POST', '/element/active');
return _returnType6.assert(new _element2.default(this.driver, this.driver, '<active>', elementHandle));
}
/*
* Get an element via a selector.
* Will throw an error if the element does not exist.
*/
}, {
key: 'getElement',
value: function getElement(selector /*: string*/) /*: Element*/ {
var _this2 = this;
var selectorType /*: SelectorType*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _selectorTypes2.default.CSS;
var _selectorType = _flowRuntime2.default.string();
var _selectorTypeType = _flowRuntime2.default.ref(SelectorType);
var _returnType7 = _flowRuntime2.default.return(_flowRuntime2.default.ref(_element2.default));
_flowRuntime2.default.param('selector', _selectorType).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType).assert(selectorType);
var elementHandle = (0, _waitFor2.default)(function () {
return _this2.driver.requestJSON('POST', '/element', { using: selectorType, value: selector });
});
return _returnType7.assert(new _element2.default(this.driver, this.driver, selector, elementHandle));
}
/*
* Get an element via a selector.
* Will return null if the element does not exist
*/
}, {
key: 'tryGetElement',
value: function tryGetElement(selector /*: string*/) /*: Element | null*/ {
var selectorType /*: SelectorType*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _selectorTypes2.default.CSS;
var _selectorType2 = _flowRuntime2.default.string();
var _selectorTypeType2 = _flowRuntime2.default.ref(SelectorType);
var _returnType8 = _flowRuntime2.default.return(_flowRuntime2.default.union(_flowRuntime2.default.ref(_element2.default), _flowRuntime2.default.null()));
_flowRuntime2.default.param('selector', _selectorType2).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType2).assert(selectorType);
try {
var elementHandle = this.driver.requestJSON('POST', '/element', { using: selectorType, value: selector });
return _returnType8.assert(new _element2.default(this.driver, this.driver, selector, elementHandle));
} catch (ex) {
if (ex.code === 'NoSuchElement' || ex.code === 'ElementNotVisible' || ex.code === 'ElementIsNotSelectable') {
return _returnType8.assert(null);
}
throw ex;
}
}
/*
* Get elements via a selector.
*/
}, {
key: 'getElements',
value: function getElements(selector /*: string*/) /*: Array<Element>*/ {
var _this3 = this;
var selectorType /*: SelectorType*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _selectorTypes2.default.CSS;
var _selectorType3 = _flowRuntime2.default.string();
var _selectorTypeType3 = _flowRuntime2.default.ref(SelectorType);
var _returnType9 = _flowRuntime2.default.return(_flowRuntime2.default.array(_flowRuntime2.default.ref(_element2.default)));
_flowRuntime2.default.param('selector', _selectorType3).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType3).assert(selectorType);
var elementHandles = this.driver.requestJSON('POST', '/elements', { using: selectorType, value: selector });
return _returnType9.assert(elementHandles.map(function (elementHandle) {
return new _element2.default(_this3.driver, _this3.driver, selector, elementHandle);
}));
}
/*
* Get elements by its text content, optionally narrowed down using a selector.
*
* N.B. this is **much** slower than getting elements by ID or css selector.
*/
}, {
key: 'getElementsByTextContent',
value: function getElementsByTextContent(textContent /*: string*/) /*: Array<Element>*/ {
var selector /*: string*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
var selectorType /*: SelectorType*/ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _selectorTypes2.default.CSS;
var _textContentType = _flowRuntime2.default.string();
var _selectorType4 = _flowRuntime2.default.string();
var _selectorTypeType4 = _flowRuntime2.default.ref(SelectorType);
var _returnType10 = _flowRuntime2.default.return(_flowRuntime2.default.array(_flowRuntime2.default.ref(_element2.default)));
_flowRuntime2.default.param('textContent', _textContentType).assert(textContent);
_flowRuntime2.default.param('selector', _selectorType4).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType4).assert(selectorType);
if (selector === 'a' && (selectorType === _selectorTypes2.default.CSS || selectorType === _selectorTypes2.default.TAG)) {
selector = _selectorType4.assert(textContent);
selectorType = _selectorTypeType4.assert(_selectorTypes2.default.PARTIAL_LINK_TEXT);
}
textContent = _textContentType.assert(textContent.trim());
var elements = this.getElements(selector, selectorType);
var elementsToReturn = [];
for (var i = 0; i < elements.length; i++) {
if (textContent === elements[i].getText().trim()) {
elementsToReturn.push(elements[i]);
}
}
return _returnType10.assert(elementsToReturn);
}
/*
* Get elements by its text content, optionally narrowed down using a selector.
*
* N.B. this is **much** slower than getting elements by ID or css selector.
*/
}, {
key: 'getElementByTextContent',
value: function getElementByTextContent(textContent /*: string*/) /*: Element*/ {
var _this4 = this;
var selector /*: string*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
var selectorType /*: SelectorType*/ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _selectorTypes2.default.CSS;
var _textContentType2 = _flowRuntime2.default.string();
var _selectorType5 = _flowRuntime2.default.string();
var _selectorTypeType5 = _flowRuntime2.default.ref(SelectorType);
var _returnType11 = _flowRuntime2.default.return(_flowRuntime2.default.ref(_element2.default));
_flowRuntime2.default.param('textContent', _textContentType2).assert(textContent);
_flowRuntime2.default.param('selector', _selectorType5).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType5).assert(selectorType);
var element = (0, _waitFor2.default)(function () {
return _this4.tryGetElementByTextContent(textContent, selector, selectorType);
});
if (element) {
return _returnType11.assert(element);
}
var err = new Error('Could not find an element with the text content: ' + textContent);
err.name = 'NoSuchElement';
_flowRuntime2.default.any().assert(err).code = 'NoSuchElement';
throw err;
}
/*
* Get elements by its text content, optionally narrowed down using a selector.
*
* N.B. this is **much** slower than getting elements by ID or css selector.
*/
}, {
key: 'tryGetElementByTextContent',
value: function tryGetElementByTextContent(textContent /*: string*/) /*: Element | null*/ {
var selector /*: string*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
var selectorType /*: SelectorType*/ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _selectorTypes2.default.CSS;
var _textContentType3 = _flowRuntime2.default.string();
var _selectorType6 = _flowRuntime2.default.string();
var _selectorTypeType6 = _flowRuntime2.default.ref(SelectorType);
var _returnType12 = _flowRuntime2.default.return(_flowRuntime2.default.union(_flowRuntime2.default.ref(_element2.default), _flowRuntime2.default.null()));
_flowRuntime2.default.param('textContent', _textContentType3).assert(textContent);
_flowRuntime2.default.param('selector', _selectorType6).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType6).assert(selectorType);
if (selector === 'a' && (selectorType === _selectorTypes2.default.CSS || selectorType === _selectorTypes2.default.TAG)) {
selector = _selectorType6.assert(textContent);
selectorType = _selectorTypeType6.assert(_selectorTypes2.default.PARTIAL_LINK_TEXT);
}
textContent = _textContentType3.assert(textContent.trim().toLowerCase());
var elements = this.getElements(selector, selectorType);
for (var i = 0; i < elements.length; i++) {
if (textContent === elements[i].getText().trim().toLowerCase()) {
return _returnType12.assert(elements[i]);
}
}
return _returnType12.assert(null);
}
/*
* Does a specific element exist?
*/
}, {
key: 'hasElement',
value: function hasElement(selector /*: string*/) /*: boolean*/ {
var selectorType /*: SelectorType*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _selectorTypes2.default.CSS;
var _selectorType7 = _flowRuntime2.default.string();
var _selectorTypeType7 = _flowRuntime2.default.ref(SelectorType);
var _returnType13 = _flowRuntime2.default.return(_flowRuntime2.default.boolean());
_flowRuntime2.default.param('selector', _selectorType7).assert(selector);
_flowRuntime2.default.param('selectorType', _selectorTypeType7).assert(selectorType);
var elements = this.getElements(selector, selectorType);
return _returnType13.assert(elements.length > 0);
}
/*
* Close the current window
*/
}, {
key: 'close',
value: function close() /*: void*/ {
var _returnType14 = _flowRuntime2.default.return(_flowRuntime2.default.void());
this.driver.requestJSON('DELETE', '/window');
}
/*
* Get the current page title
*/
}, {
key: 'getTitle',
value: function getTitle() /*: string*/ {
var _returnType15 = _flowRuntime2.default.return(_flowRuntime2.default.string());
return _returnType15.assert(this.driver.requestJSON('GET', '/title'));
}
/*
* Get the current page source
*/
}, {
key: 'getSource',
value: function getSource() /*: string*/ {
var _returnType16 = _flowRuntime2.default.return(_flowRuntime2.default.string());
return _returnType16.assert(this.driver.requestJSON('GET', '/source'));
}
/*
* Navigate forwards in the browser history, if possible.
*/
}, {
key: 'goForward',
value: function goForward() /*: void*/ {
var _returnType17 = _flowRuntime2.default.return(_flowRuntime2.default.void());
this.driver.requestJSON('POST', '/forward');
}
/*
* Navigate backwards in the browser history, if possible.
*/
}, {
key: 'goBackward',
value: function goBackward() /*: void*/ {
var _returnType18 = _flowRuntime2.default.return(_flowRuntime2.default.void());
this.driver.requestJSON('POST', '/back');
}
/*
* Refreshes the browser
*/
}, {
key: 'refresh',
value: function refresh() /*: void*/ {
var _returnType19 = _flowRuntime2.default.return(_flowRuntime2.default.void());
this.driver.requestJSON('POST', '/refresh');
}
/*
* Get the current url that the browser is displaying
*/
}, {
key: 'getUrl',
value: function getUrl() /*: string*/ {
var _returnType20 = _flowRuntime2.default.return(_flowRuntime2.default.string());
return _returnType20.assert(this.driver.requestJSON('GET', '/url'));
}
/*
* Navigates the browser to the specified path
*
* - if `path` begins with a "/" it is relative to `options.base`
* - if `path` begins with "http" it is absolute
* - otherwise it is relative to the current path
*/
}, {
key: 'navigateTo',
value: function navigateTo(path /*: string*/) /*: void*/ {
var _pathType = _flowRuntime2.default.string();
var _returnType21 = _flowRuntime2.default.return(_flowRuntime2.default.void());
_flowRuntime2.default.param('path', _pathType).assert(path);
if (path[0] === '/') {
var base = this._options.base;
if (!base) {
throw new Error('You must provide a "base" option to use urls starting with "/"');
}
path = _pathType.assert(base.replace(/\/$/, '') + path);
} else if (path.indexOf('http') !== 0) {
var _base = this.getUrl();
this.navigateTo((0, _url.resolve)(_base, path));
return _returnType21.assert();
}
this.driver.requestJSON('POST', '/url', { url: path });
}
}]);
return ActiveWindow;
}(_baseWindow2.default);
/*
* Convert code to string before execution
*/
function codeToString(code /*: string | Function*/) /*: string*/ {
var _codeType = _flowRuntime2.default.union(_flowRuntime2.default.string(), _flowRuntime2.default.function());
var _returnType22 = _flowRuntime2.default.return(_flowRuntime2.default.string());
_flowRuntime2.default.param('code', _codeType).assert(code);
if (typeof code === 'function') {
// $FlowFixMe: intentionally concatenating string onto end of code
return 'return (' + code + ').apply(null, arguments);';
} else {
return _returnType22.assert(code);
}
}
_flowRuntime2.default.annotate(codeToString, _flowRuntime2.default.function(_flowRuntime2.default.param('code', _flowRuntime2.default.union(_flowRuntime2.default.string(), _flowRuntime2.default.function())), _flowRuntime2.default.return(_flowRuntime2.default.string())));
(0, _addDebugging2.default)(ActiveWindow);
exports.default = ActiveWindow;