389 lines
13 KiB
JavaScript
389 lines
13 KiB
JavaScript
var util = require('util');
|
|
var events = require('events');
|
|
var Logger = require('../util/logger.js');
|
|
var Utils = require('../util/utils.js');
|
|
|
|
module.exports = function(client) {
|
|
var Protocol = require('./protocol.js')(client);
|
|
var returnValue = {};
|
|
var elementCommands = {};
|
|
|
|
/**
|
|
* Simulates a click event on the given DOM element. Uses `elementIdClick` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.click("#main ul li a.first");
|
|
* };
|
|
* ```
|
|
*
|
|
* @method click
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdClick
|
|
* @api commands
|
|
*/
|
|
elementCommands.click = 'elementIdClick';
|
|
|
|
/**
|
|
* Clear a textarea or a text input element's value. Uses `elementIdValue` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.clearValue('input[type=text]');
|
|
* };
|
|
* ```
|
|
*
|
|
* @method clearValue
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdClear
|
|
* @api commands
|
|
*/
|
|
elementCommands.clearValue = 'elementIdClear';
|
|
|
|
/**
|
|
* Retrieve the value of an attribute for a given DOM element. Uses `elementIdAttribute` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.getAttribute("#main ul li a.first", "href", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, "#home");
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getAttribute
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {string} attribute The attribute name to inspect.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdAttribute
|
|
* @returns {*} The value of the attribute
|
|
* @api commands
|
|
*/
|
|
elementCommands.getAttribute = ['elementIdAttribute', 1];
|
|
|
|
/**
|
|
* Retrieve the value of a css property for a given DOM element. Uses `elementIdCssProperty` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.getCssProperty("#main ul li a.first", "display", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, 'inline');
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getCssProperty
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {string} cssProperty The CSS property to inspect.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdCssProperty
|
|
* @returns {*} The value of the css property
|
|
* @api commands
|
|
*/
|
|
elementCommands.getCssProperty = ['elementIdCssProperty', 1];
|
|
|
|
/**
|
|
* Determine an element's size in pixels. Uses `elementIdSize` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.getElementSize("#main ul li a.first", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value.width, 500);
|
|
* this.assert.equal(result.value.height, 20);
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getElementSize
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdSize
|
|
* @returns {{width: number, height: number}} The width and height of the element in pixels
|
|
* @api commands
|
|
*/
|
|
elementCommands.getElementSize = 'elementIdSize';
|
|
|
|
/**
|
|
* Determine an element's location on the page. The point (0, 0) refers to the upper-left corner of the page.
|
|
*
|
|
* The element's coordinates are returned as a JSON object with x and y properties. Uses `elementIdLocation` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.getLocation("#main ul li a.first", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value.x, 200);
|
|
* this.assert.equal(result.value.y, 200);
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getLocation
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdLocation
|
|
* @returns {x:number, y:number} The X and Y coordinates for the element on the page.
|
|
* @api commands
|
|
*/
|
|
elementCommands.getLocation = 'elementIdLocation';
|
|
|
|
/**
|
|
* Determine an element's location on the screen once it has been scrolled into view. Uses `elementIdLocationInView` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.getLocationInView("#main ul li a.first", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value.x, 200);
|
|
* this.assert.equal(result.value.y, 200);
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getLocationInView
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdLocationInView
|
|
* @returns {x: number, y: number} The X and Y coordinates for the element on the page.
|
|
* @api commands
|
|
*/
|
|
elementCommands.getLocationInView = 'elementIdLocationInView';
|
|
|
|
/**
|
|
* Query for an element's tag name. Uses `elementIdName` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (client) {
|
|
* client.getTagName("#main ul li .first", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, "a");
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getTagName
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdName
|
|
* @returns {number} The element's tag name, as a lowercase string.
|
|
* @api commands
|
|
*/
|
|
elementCommands.getTagName = 'elementIdName';
|
|
|
|
/**
|
|
* Returns the visible text for the element. Uses `elementIdText` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.getText("#main ul li a.first", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, "nightwatchjs.org");
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getText
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdText
|
|
* @returns {string} The element's visible text.
|
|
* @api commands
|
|
*/
|
|
elementCommands.getText = 'elementIdText';
|
|
|
|
/**
|
|
* Returns a form element current value. Uses `elementIdValue` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.getValue("form.login input[type=text]", function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, "enter username");
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method getValue
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdValue
|
|
* @returns {string} The element's value.
|
|
* @api commands
|
|
*/
|
|
elementCommands.getValue = 'elementIdValue';
|
|
|
|
/**
|
|
* Determine if an element is currently displayed. Uses `elementIdDisplayed` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.isVisible('#main', function(result) {
|
|
* this.assert.equal(typeof result, "object");
|
|
* this.assert.equal(result.status, 0);
|
|
* this.assert.equal(result.value, true);
|
|
* });
|
|
* };
|
|
* ```
|
|
*
|
|
* @method isVisible
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdDisplayed
|
|
* @api commands
|
|
*/
|
|
elementCommands.isVisible = 'elementIdDisplayed';
|
|
|
|
/**
|
|
* Move the mouse by an offset of the specified element. Uses `moveTo` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.moveToElement('#main', 10, 10);
|
|
* };
|
|
* ```
|
|
*
|
|
* @method moveToElement
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
* @param {number} yoffset Y offset to move to, relative to the top-left corner of the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see moveTo
|
|
* @api commands
|
|
*/
|
|
elementCommands.moveToElement = ['moveTo', 2];
|
|
|
|
/**
|
|
* Sends some text to an element. Can be used to set the value of a form element or to send a sequence of key strokes to an element. Any UTF-8 character may be specified.
|
|
*
|
|
* An object map with available keys and their respective UTF-8 characters, as defined on [W3C WebDriver draft spec](http://www.w3.org/TR/webdriver/#character-types), is loaded onto the main Nightwatch instance as `client.Keys`.
|
|
*
|
|
* ```
|
|
* // send some simple text to an input
|
|
* this.demoTest = function (browser) {
|
|
* browser.setValue('input[type=text]', 'nightwatch');
|
|
* };
|
|
* //
|
|
* // send some text to an input and hit enter.
|
|
* this.demoTest = function (browser) {
|
|
* browser.setValue('input[type=text]', ['nightwatch', browser.Keys.ENTER]);
|
|
* };
|
|
* ```
|
|
*
|
|
* @link /session/:sessionId/element/:id/value
|
|
* @method setValue
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {string|array} value The text to send to the element or key strokes.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see elementIdValue
|
|
* @api commands
|
|
*/
|
|
elementCommands.setValue = ['elementIdValue', 1];
|
|
|
|
/**
|
|
* Submit a FORM element. The submit command may also be applied to any element that is a descendant of a FORM element. Uses `submit` protocol command.
|
|
*
|
|
* ```
|
|
* this.demoTest = function (browser) {
|
|
* browser.submitForm('form.login');
|
|
* };
|
|
* ```
|
|
*
|
|
* @method submitForm
|
|
* @param {string} selector The CSS/Xpath selector used to locate the element.
|
|
* @param {function} [callback] Optional callback function to be called when the command finishes.
|
|
* @see submit
|
|
* @api commands
|
|
*/
|
|
elementCommands.submitForm = 'submit';
|
|
|
|
function addElementCommand(protocolAction, extraArgs) {
|
|
extraArgs = extraArgs || 0;
|
|
var expectedArgs = 3 + extraArgs;
|
|
return function commandActionFn() {
|
|
var originalStackTrace = commandActionFn.stackTrace;
|
|
var noopFn = function() {};
|
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
if (typeof args[args.length-1] !== 'function') {
|
|
args.push(noopFn);
|
|
}
|
|
|
|
var defaultUsing = client.locateStrategy || 'css selector';
|
|
if (expectedArgs - args.length === 1) {
|
|
args.unshift(defaultUsing);
|
|
}
|
|
|
|
if (args.length < expectedArgs - 1 || args.length > expectedArgs) {
|
|
throw new Error(protocolAction + ' method expects ' + (expectedArgs - 1) + ' or ' + expectedArgs + ' arguments - ' + args.length + ' given.');
|
|
}
|
|
|
|
var using = args.shift();
|
|
var value = args.shift();
|
|
var callback = args.pop();
|
|
|
|
return new CommandAction(using, value, protocolAction, args, callback, originalStackTrace);
|
|
};
|
|
}
|
|
|
|
function CommandAction(using, value, protocolAction, args, callback, originalStackTrace) {
|
|
events.EventEmitter.call(this);
|
|
|
|
var $this = this;
|
|
var el = Protocol.element(using, value, function(result) {
|
|
if (result.status !== 0) {
|
|
callback.call(client.api, result);
|
|
var errorMessage = 'ERROR: Unable to locate element: "' + value + '" using: ' + using;
|
|
var stack = originalStackTrace.split('\n');
|
|
|
|
stack.shift();
|
|
Utils.showStackTraceWithHeadline(errorMessage, stack);
|
|
|
|
client.results.errors++;
|
|
client.errors.push(errorMessage + '\n' + stack.join('\n'));
|
|
|
|
$this.emit('complete', el, $this);
|
|
} else {
|
|
result = result.value.ELEMENT;
|
|
|
|
args.push(function(r) {
|
|
callback.call(client.api, r);
|
|
});
|
|
|
|
args.unshift(result);
|
|
|
|
var c = Protocol[protocolAction].apply(Protocol, args).once('complete', function() {
|
|
$this.emit('complete', c, $this);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
util.inherits(CommandAction, events.EventEmitter);
|
|
|
|
Object.keys(elementCommands).forEach(function(commandName) {
|
|
var args = elementCommands[commandName];
|
|
if (!Array.isArray(args)) {
|
|
args = [args];
|
|
}
|
|
|
|
returnValue[commandName] = addElementCommand.apply(client.api, args);
|
|
});
|
|
|
|
// alias
|
|
returnValue.sendKeys = returnValue.setValue;
|
|
|
|
return returnValue;
|
|
};
|