Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(locators): add the ability to add custom element locators with b…
Browse files Browse the repository at this point in the history
…y.addLocator

Custom locators can now be added using by.addLocator(<name>, <script>), where
script is a self-contained snippet to be executed on the browser which returns
an array of elements. Closes #236.
  • Loading branch information
juliemr committed Nov 13, 2013
1 parent 60602ad commit 98bce7e
Showing 2 changed files with 56 additions and 18 deletions.
51 changes: 37 additions & 14 deletions lib/locators.js
Original file line number Diff line number Diff line change
@@ -19,6 +19,29 @@ var WebdriverBy = function() {};
WebdriverBy.prototype = webdriver.By;
util.inherits(ProtractorBy, WebdriverBy);

/**
* Add a locator to this instance of ProtractorBy. This locator can then be
* used with element(by.<name>(<args>)).
*
* @param {string} name
* @param {function|string} script A script to be run in the context of
* the browser. This script will be passed an array of arguments
* that begins with the element scoping the search, and then
* contains any args passed into the locator. It should return
* an array of elements.
*/
ProtractorBy.prototype.addLocator = function(name, script) {
this[name] = function(varArgs) {
return {
findElementsOverride: function(driver, using) {
return driver.findElements(
webdriver.By.js(script), using, varArgs);
},
message: 'by.' + name + '("' + varArgs + '")'
}
};
};

/**
* Usage:
* <span>{{status}}</span>
@@ -31,7 +54,7 @@ ProtractorBy.prototype.binding = function(bindingDescriptor) {
webdriver.By.js(clientSideScripts.findBindings),
using, bindingDescriptor);
},
message: 'by.binding(' + bindingDescriptor + ')'
message: 'by.binding("' + bindingDescriptor + '")'
};
};

@@ -46,7 +69,7 @@ ProtractorBy.prototype.select = function(model) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findSelects), using, model);
},
message: 'by.select(' + model + ')'
message: 'by.select("' + model + '")'
};
};

@@ -61,7 +84,7 @@ ProtractorBy.prototype.selectedOption = function(model) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findSelectedOptions), using, model);
},
message: 'by.selectedOption(' + model + ')'
message: 'by.selectedOption("' + model + '")'
};
};

@@ -77,7 +100,7 @@ ProtractorBy.prototype.input = function(model) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findInputs), using, model);
},
message: 'by.input(' + model + ')'
message: 'by.input("' + model + '")'
};
};

@@ -92,7 +115,7 @@ ProtractorBy.prototype.model = function(model) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findInputs), using, model);
},
message: 'by.model(' + model + ')'
message: 'by.model("' + model + '")'
};
};

@@ -107,7 +130,7 @@ ProtractorBy.prototype.textarea = function(model) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findTextareas), using, model);
},
message: 'by.textarea(' + model + ')'
message: 'by.textarea("' + model + '")'
};
};

@@ -137,24 +160,24 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
webdriver.By.js(clientSideScripts.findAllRepeaterRows),
using, repeatDescriptor);
},
message: 'by.repeater(' + repeatDescriptor + ')',
message: 'by.repeater("' + repeatDescriptor + '")',
row: function(index) {
return {
findElementsOverride: function(driver, using) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findRepeaterRows),
using, repeatDescriptor, index);
},
message: 'by.repeater(' + repeatDescriptor + ').row(' + index + ')',
message: 'by.repeater(' + repeatDescriptor + '").row("' + index + '")"',
column: function(binding) {
return {
findElementsOverride: function(driver, using) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findRepeaterElement),
using, repeatDescriptor, index, binding);
},
message: 'by.repeater(' + repeatDescriptor + ').row(' + index +
').column(' + binding + ')'
message: 'by.repeater("' + repeatDescriptor + '").row("' + index +
'").column("' + binding + '")'
};
}
};
@@ -166,17 +189,17 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
webdriver.By.js(clientSideScripts.findRepeaterColumn),
using, repeatDescriptor, binding);
},
message: 'by.repeater(' + repeatDescriptor + ').column(' + binding +
')',
message: 'by.repeater("' + repeatDescriptor + '").column("' + binding +
'")',
row: function(index) {
return {
findElementsOverride: function(driver, using) {
return driver.findElements(
webdriver.By.js(clientSideScripts.findRepeaterElement),
using, repeatDescriptor, index, binding);
},
message: 'by.repeater(' + repeatDescriptor + ').column(' + binding
+ ').row(' + index + ')'
message: 'by.repeater("' + repeatDescriptor + '").column("' +
binding + '").row("' + index + '")'
};
}
};
23 changes: 19 additions & 4 deletions spec/basic/lib_spec.js
Original file line number Diff line number Diff line change
@@ -47,8 +47,23 @@ describe('protractor library', function() {
expect(protractor.Key.RETURN).toEqual('\uE006');
});

// it('should allow adding custom locators', function() {
// by.addLocator();

// });
it('should allow adding custom locators', function() {
var findMenuItem = function() {
var using = arguments[0]; // unused
var itemName = arguments[1];
var menu = document.querySelectorAll('.menu li');
for (var i = 0; i < menu.length; ++i) {
if (menu[i].innerText == itemName) {
return [menu[i]];
}
}
};

by.addLocator('menuItem', findMenuItem);

expect(by.menuItem).toBeDefined();

expect(element(by.menuItem('repeater')).isPresent());
expect(element(by.menuItem('repeater')).getText()).toEqual('repeater');
});
});

0 comments on commit 98bce7e

Please sign in to comment.