page-chauffeur
Version:
A cross browser library for writing functional tests using webdriver
462 lines (386 loc) • 12.7 kB
JavaScript
var inherits = require('util').inherits,
fs = require("fs"),
Driver = require('../driver'),
ERROR_MSGS = require('../errors'),
webdriver = require('selenium-webdriver');
function WebDriverJS(config) {
var browserName = config.desiredCapabilities.browserName;
this._remoteDriverBuilder = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities[browserName]());
}
inherits(WebDriverJS, Driver);
WebDriverJS.prototype = {
_delegate: function _delegate(selector, callback, method, methodArgs) {
var context;
methodArgs = methodArgs || [];
context = this._remoteDriver.findElement(webdriver.By.css(selector));
context
.then(function(element) {
element[method](methodArgs)
.then(function(value) {
callback(null, value);
})
.then(null, function errorDelegating(err) {
callback(err);
});
})
.then(null, function errorFindingElement(err) {
callback(err);
});
return context;
},
init: function init(cb) {
this._remoteDriver = this._remoteDriverBuilder.build(); //move to constructor?
cb();
},
goTo: function goTo(url) {
this._remoteDriver.get(url);
},
getTitle: function getTitle(cb) {
this._remoteDriver.getTitle()
.then(function(title) {
cb(null, title);
})
.then(null, function(err) {
cb(err);
});
},
location: function location(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.LOCATION_MISMATCH, selector),
['x','y'],
coerceFn,
cb
);
this.ctxt = this._delegate(selector, callback, 'getLocation');
},
size: function size(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.SIZE_MISMATCH, selector),
['width','height'],
coerceFn,
cb
);
this.ctxt = this._delegate(selector, callback, 'getSize');
},
width: function width(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.WIDTH_MISMATCH, selector),
null,
coerceFn || parseFloat,
cb
).bind(this);
this.ctxt = this.cssProperty(selector, 'width', callback);
},
color: function color(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.COLOR_MISMATCH, selector),
null,
coerceFn || function(v) {
var re = /, /gi;
return v.replace(re, ',');
},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getCssValue', 'color');
},
visible: function visible(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.VISIBLE_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'isDisplayed');
},
invisible: function invisible(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
false,
ERROR_MSGS.resolve(ERROR_MSGS.INVISIBLE_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'isDisplayed');
},
wait: function wait(delay) {
this._remoteDriver.wait(function(v){return true;}, delay);
},
klick: function klick(selector, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.CLICK_UNSUCCESSFUL, selector),
null,
function(v) { return v === "" || true;},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'click');
},
doubleklick: function doubleklick(selector, expectation, coerceFn, cb) {
var element;
element = this._remoteDriver.findElement(webdriver.By.css(selector));
this.ctxt = new webdriver.ActionSequence(this._remoteDriver)
.doubleClick(element)
.perform();
},
clear: function clear(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.CLEARANCE_UNSUCCESSFUL, selector),
null,
coerceFn || function(v) {
return v === "" || true;
},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'clear');
},
nodeName: function nodeName(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.NODENAME_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getTagName');
},
text: function text(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.TEXT_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getText');
},
selected: function selected(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.SELECTED_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'isSelected');
},
unselected: function unselected(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
false,
ERROR_MSGS.resolve(ERROR_MSGS.UNSELECTED_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'isSelected');
},
submit: function submit(selector, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.SUBMIT_UNSUCCESSFUL, selector),
null,
function(v) { return v === "" || true;},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'submit');
},
value: function value(selector, expectation, coerceFn, cb) {
this.attr(selector, 'value', expectation, coerceFn, cb);
},
attr: function attr(selector, attrName, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.ATTRIBUTE_MISMATCH, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getAttribute', attrName);
},
setValue: function setValue(selector, expectation, coerceFn, cb) {
this.clear(selector, null, null, function() {
var element = this._remoteDriver.findElement(webdriver.By.css(selector));
this.ctxt = new webdriver.ActionSequence(this._remoteDriver)
.click(element)
.sendKeys(expectation)
.perform();
}.bind(this)
);
},
exists: function exists(selector, expectation, coerceFn, cb) {
var shouldExist = (expectation === undefined) ? true : expectation,
shouldExistErr = (shouldExist) ? ERROR_MSGS.EXISTENCE_MISMATCH : ERROR_MSGS.NON_EXISTENCE_MISMATCH,
callback = Driver._getExpectationCallback(
shouldExist,
ERROR_MSGS.resolve(shouldExistErr, selector),
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._remoteDriver.findElement(webdriver.By.css(selector))
.then(function(value) {
callback(null, true);
})
.then(null, function(err) {
if (err && err.state == 'no such element') {
callback(null, false);
}
else {
callback(err);
}
});
},
elements: function elements(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.resolve(ERROR_MSGS.INCORRECT_NUMBER_FOUND),
null,
coerceFn,
cb
).bind(this);
var context = this._remoteDriver.findElements(webdriver.By.css(selector));
context.then(function(result) {
callback(null, result.length);
})
.then(null, function(err) {
if (err && err.state == 'no such element') {
callback(null, false);
}
else {
callback(err);
}
});
return context;
},
hasntClass: function hasntClass(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.HASNT_CLASS_MISMATCH, selector),
null,
function hasntClassCoerceFn(result) {
if (result.split) {
return (result.split(' ').indexOf(expectation) === -1);
}
return result;
},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getAttribute', 'class');
},
hasClass: function hasCass(selector, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
true,
ERROR_MSGS.resolve(ERROR_MSGS.HAS_CLASS_MISMATCH, selector),
null,
function hasClassCoerceFn(result) {
if (result.split) {
return (result.split(' ').indexOf(expectation) !== -1);
}
return result;
},
cb
).bind(this);
this.ctxt = this._delegate(selector, callback, 'getAttribute', 'class');
},
moveTo: function moveTo(selector) {
var element;
element = this._remoteDriver.findElement(webdriver.By.css(selector));
this.ctxt = new webdriver.ActionSequence(this._remoteDriver)
.mouseMove(element)
.perform();
},
hover: function hover(selector) {
this.moveTo(selector);
},
back: function back() {
var navigation = new webdriver.WebDriver.Navigation(this._remoteDriver);
this.ctxt = navigation.back();
},
forward: function forward(selector, expectation, coerceFn, cb) {
var navigation = new webdriver.WebDriver.Navigation(this._remoteDriver);
this.ctxt = navigation.forward();
},
executeScript: function executeScript(script, expectation, coerceFn, cb) {
var callback = Driver._getExpectationCallback(
expectation,
ERROR_MSGS.SCRIPT_RESULT_MISMATCH,
null,
coerceFn,
cb
).bind(this);
this.ctxt = this._remoteDriver.executeScript(script)
.then(function(result) {
callback(null, result);
})
.then(null, function(err) {
callback(err);
});
},
cssProperty: function cssProperty(selector, property, callback) {
return this._delegate(selector, callback, 'getCssValue', [property]);
},
end: function end() {
if (this.ctxt && this.ctxt.isPending()) {
this.ctxt.thenFinally(function () {
this._closeWhenFinished();
}.bind(this));
}
else {
this._closeWhenFinished();
}
},
endAll: function end() {
this._closeWhenFinished();
},
getWindow: function getWindow() {
return new webdriver.WebDriver.Window(this._remoteDriver);
},
setSize: function setSize(windowSize) {
var window;
window = this.getWindow();
window.setSize(windowSize.width, windowSize.height);
},
getSize: function getSize(callback) {
var window = this.getWindow();
window.getSize()
.then(function(result) {
callback(null, {width: result.width, height: result.height});
});
},
takeScreenshot: function takeScreenshot(imagePath) {
this._remoteDriver.takeScreenshot()
.then(function(base64_png) {
fs.writeFile(imagePath, base64_png, 'base64', function(err) {
if (err) {
ERROR_MSGS.resolve(
Driver._errorOut(ERROR_MSGS.SCREENSHOT_UNSUCCESSFUL, err)
);
}
});
})
.then(null, function(err) {
ERROR_MSGS.resolve(
Driver._errorOut(ERROR_MSGS.SCREENSHOT_UNSUCCESSFUL, err)
);
});
},
_closeWhenFinished: function _closeWhenFinished() {
if (this._remoteDriver.session_) {
this._remoteDriver.quit()
.then(function() {
this.ctxt = null;
Driver.resolve();
}.bind(this));
}
else {
Driver.resolve();
}
}
};
module.exports = WebDriverJS;