Preface
I'm trying to write a few extensions for selenium-webdriver, like so:
var webdriver = require('selenium-webdriver');
var fs = require('fs');
var resumer = require('resumer');
webdriver.WebDriver.prototype.saveScreenshot = function(filename) {
return this.takeScreenshot().then(function(data) {
fs.writeFile(filename, data.replace(/^data:image\/png;base64,/,''), 'base64', function(err) {
if(err) throw err;
});
});
};
webdriver.WebDriver.prototype.streamScreenshot = function() {
var stream = resumer();
this.takeScreenshot().then(function(data) {
stream.queue(new Buffer(data.replace(/^data:image\/png;base64,/,''), 'base64')).end();
});
return stream;
};
module.exports = webdriver;
And then I just include my extended webdriver, instead of the official one:
var webdriver = require('./webdriver.ext');
I think that's the proper way to extend things in Node JS.
Problem
The issue I'm having is with adding a custom Locator Strategy. The strategies look like this in the source:
/**
* Factory methods for the supported locator strategies.
* @type {Object.<function(string):!webdriver.Locator>}
*/
webdriver.Locator.Strategy = {
'className': webdriver.Locator.factory_('class name'),
'class name': webdriver.Locator.factory_('class name'),
'css': webdriver.Locator.factory_('css selector'),
'id': webdriver.Locator.factory_('id'),
'js': webdriver.Locator.factory_('js'),
'linkText': webdriver.Locator.factory_('link text'),
'link text': webdriver.Locator.factory_('link text'),
'name': webdriver.Locator.factory_('name'),
'partialLinkText': webdriver.Locator.factory_('partial link text'),
'partial link text': webdriver.Locator.factory_('partial link text'),
'tagName': webdriver.Locator.factory_('tag name'),
'tag name': webdriver.Locator.factory_('tag name'),
'xpath': webdriver.Locator.factory_('xpath')
};
goog.exportSymbol('By', webdriver.Locator.Strategy);
I'm trying to add a new one by injecting it into that object:
webdriver.By.sizzle = function(selector) {
driver.executeScript("return typeof Sizzle==='undefined'").then(function(noSizzle) {
if(noSizzle) driver.executeScript(fs.readFileSync('sizzle.min.js', {encoding: 'utf8'}));
});
return new webdriver.By.js("return Sizzle("+JSON.stringify(selector)+")[0]");
};
This actually works fine for simple scripts where driver is defined (notice that I'm using a global variable).
Is there a way to access the "current driver" inside my function? Unlike the methods at the top, this isn't a prototypical method, so I don't have access to this.
I don't know how those factory_s work; I was just guessing that I could inject a function directly.