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

Commit 98bce7e

Browse files
committedNov 13, 2013
feat(locators): add the ability to add custom element locators with by.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.
1 parent 60602ad commit 98bce7e

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed
 

‎lib/locators.js

+37-14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,29 @@ var WebdriverBy = function() {};
1919
WebdriverBy.prototype = webdriver.By;
2020
util.inherits(ProtractorBy, WebdriverBy);
2121

22+
/**
23+
* Add a locator to this instance of ProtractorBy. This locator can then be
24+
* used with element(by.<name>(<args>)).
25+
*
26+
* @param {string} name
27+
* @param {function|string} script A script to be run in the context of
28+
* the browser. This script will be passed an array of arguments
29+
* that begins with the element scoping the search, and then
30+
* contains any args passed into the locator. It should return
31+
* an array of elements.
32+
*/
33+
ProtractorBy.prototype.addLocator = function(name, script) {
34+
this[name] = function(varArgs) {
35+
return {
36+
findElementsOverride: function(driver, using) {
37+
return driver.findElements(
38+
webdriver.By.js(script), using, varArgs);
39+
},
40+
message: 'by.' + name + '("' + varArgs + '")'
41+
}
42+
};
43+
};
44+
2245
/**
2346
* Usage:
2447
* <span>{{status}}</span>
@@ -31,7 +54,7 @@ ProtractorBy.prototype.binding = function(bindingDescriptor) {
3154
webdriver.By.js(clientSideScripts.findBindings),
3255
using, bindingDescriptor);
3356
},
34-
message: 'by.binding(' + bindingDescriptor + ')'
57+
message: 'by.binding("' + bindingDescriptor + '")'
3558
};
3659
};
3760

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

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

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

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

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

@@ -137,24 +160,24 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
137160
webdriver.By.js(clientSideScripts.findAllRepeaterRows),
138161
using, repeatDescriptor);
139162
},
140-
message: 'by.repeater(' + repeatDescriptor + ')',
163+
message: 'by.repeater("' + repeatDescriptor + '")',
141164
row: function(index) {
142165
return {
143166
findElementsOverride: function(driver, using) {
144167
return driver.findElements(
145168
webdriver.By.js(clientSideScripts.findRepeaterRows),
146169
using, repeatDescriptor, index);
147170
},
148-
message: 'by.repeater(' + repeatDescriptor + ').row(' + index + ')',
171+
message: 'by.repeater(' + repeatDescriptor + '").row("' + index + '")"',
149172
column: function(binding) {
150173
return {
151174
findElementsOverride: function(driver, using) {
152175
return driver.findElements(
153176
webdriver.By.js(clientSideScripts.findRepeaterElement),
154177
using, repeatDescriptor, index, binding);
155178
},
156-
message: 'by.repeater(' + repeatDescriptor + ').row(' + index +
157-
').column(' + binding + ')'
179+
message: 'by.repeater("' + repeatDescriptor + '").row("' + index +
180+
'").column("' + binding + '")'
158181
};
159182
}
160183
};
@@ -166,17 +189,17 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
166189
webdriver.By.js(clientSideScripts.findRepeaterColumn),
167190
using, repeatDescriptor, binding);
168191
},
169-
message: 'by.repeater(' + repeatDescriptor + ').column(' + binding +
170-
')',
192+
message: 'by.repeater("' + repeatDescriptor + '").column("' + binding +
193+
'")',
171194
row: function(index) {
172195
return {
173196
findElementsOverride: function(driver, using) {
174197
return driver.findElements(
175198
webdriver.By.js(clientSideScripts.findRepeaterElement),
176199
using, repeatDescriptor, index, binding);
177200
},
178-
message: 'by.repeater(' + repeatDescriptor + ').column(' + binding
179-
+ ').row(' + index + ')'
201+
message: 'by.repeater("' + repeatDescriptor + '").column("' +
202+
binding + '").row("' + index + '")'
180203
};
181204
}
182205
};

‎spec/basic/lib_spec.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,23 @@ describe('protractor library', function() {
4747
expect(protractor.Key.RETURN).toEqual('\uE006');
4848
});
4949

50-
// it('should allow adding custom locators', function() {
51-
// by.addLocator();
52-
53-
// });
50+
it('should allow adding custom locators', function() {
51+
var findMenuItem = function() {
52+
var using = arguments[0]; // unused
53+
var itemName = arguments[1];
54+
var menu = document.querySelectorAll('.menu li');
55+
for (var i = 0; i < menu.length; ++i) {
56+
if (menu[i].innerText == itemName) {
57+
return [menu[i]];
58+
}
59+
}
60+
};
61+
62+
by.addLocator('menuItem', findMenuItem);
63+
64+
expect(by.menuItem).toBeDefined();
65+
66+
expect(element(by.menuItem('repeater')).isPresent());
67+
expect(element(by.menuItem('repeater')).getText()).toEqual('repeater');
68+
});
5469
});

0 commit comments

Comments
 (0)
This repository has been archived.