stefan
stefan

Reputation: 23

How to develop a custom protractor locator?

I have an angular-application where I put custom html-attributes ("data-testid='saveButton'") for identification on e.g. buttons, inputs etc. Protractor has no built-in locator for this: the xpath-way does not work as this will always search from the document root (to overcome this limitation I would have to do quite a lot of string-magic to build the xpath-string, so I discarded this variant).

So I wanted to write my own locator, and consulted the official Protractor Documentation.

The documentation leaves me with an important question: What methods are available on the parent-element-object? In their example they use using.querySelectorAll('button'); but how do they know they can use this?

I searched for 'querySelectorAll' in the protractor-documentation to see if it is maybe a method of ElementFinder or WebElement, but I didn't find it.

Also I found no way to debug the locator (only stop the protractor-test by browser.pause()), so I can't look at runtime to see what I can do with the given parent-element.

So does anybody know how I can get information about what methods the parent-element has?

Upvotes: 1

Views: 1450

Answers (1)

Delian Mitankin
Delian Mitankin

Reputation: 3691

The parent-element, which is essentially the context of the selector is a DOM element that gets handled by the browser - it can use whatever DOM function there is, in this case Element.querySelectorAll. As the addLocator's example says about the function you pass to it:

This function will be serialized as a string and will execute in the browser.

Also, keep in mind that there is a way to provide context to the xpath selectors thus avoiding the search from root:

var context = element(by.css('.some-parent-element-class'));
var divDirectDescendants = context.element(by.xpath('div'));
var divAllDescendants = context.element(by.xpath('.//div'));

With CSS these would be:

var divDirectDescendants = element(by.css('.some-parent-element-class > div'));
var divAllDescendants = element(by.css('.some-parent-element-class  div'));

Also, there's a way to achieve what you want with a CSS selector (which is what querySelectorAll is, after all):

var everyElementWithMyAttr = element.all(by.css('[data-testid="saveButton"]'));

Upvotes: 2

Related Questions