Protractor – Core APIS(CONTD…)

In this chapter, let us learn some more core APIs of Protractor.

Elements API

Element is one of the global functions exposed by protractors. This function takes a locater and returns the following −

  • ElementFinder, that finds a single element based on the locator.
  • ElementArrayFinder, that finds an array of elements based on the locator.

Both the above support chaining methods as discussed below.

Chaining functions of ElementArrayFinder and their descriptions

The Followings are the functions of ElementArrayFinder −

element.all(locator).clone

As the name suggests, this function will create a shallow copy of the array of the elements i.e. ElementArrayFinder.

element.all(locator).all(locator)

This function basically returns a new ElementArrayFinder which could be empty or contain the children elements. It can be used for selecting multiple elements as an array as follows

Example

element.all(locator).all(locator)
elementArr.all(by.css(‘.childselector’));
// it will return another ElementFindArray as child element based on child locator.

element.all(locator).filter(filterFn)

As the name suggests, after applying the filter function to each element within ElementArrayFinder, it returns a new ElementArrayFinder with all elements that pass the filter function. It is basically having two arguments, the first is ElementFinder and the second is an index. It can also be used in page objects.

Example

View

<ul class = "items">
   <li class = "one">First</li>
   <li class = "two">Second</li>
   <li class = "three">Third</li>
</ul>

Code

element.all(by.css('.items li')).filter(function(elem, index) {
   return elem.getText().then(function(text) {
      return text === 'Third';
   });
}).first().click();

element.all(locator).get(index)

With the help of this, we can get an element within the ElementArrayFinder by index. Note that the index starts at 0 and negative indices are wrapped.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let list = element.all(by.css('.items li'));
expect(list.get(0).getText()).toBe('First');
expect(list.get(1).getText()).toBe('Second');

element.all(locator).first()

As the name suggests, this will get the first element for ElementArrayFinder. It will not retrieve the underlying element.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let first = element.all(by.css('.items li')).first();
expect(first.getText()).toBe('First');

element.all(locator).last()

As the name suggests, this will get the last element for ElementArrayFinder. It will not retrieve the underlying element.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let first = element.all(by.css('.items li')).last();
expect(last.getText()).toBe('Third');

element.all(locator).all(selector)

It is used to find an array of elements within a parent when calls to $$ may be chained.

Example

View

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

Code

let items = element(by.css('.parent')).$$('li');

element.all(locator).count()

As the name suggests, this will count the number of elements represented by ElementArrayFinder. It will not retrieve the underlying element.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let list = element.all(by.css('.items li'));
expect(list.count()).toBe(3);

element.all(locator).isPresent()

It will match the elements with the finder. It can return true or false. True, if there are any elements present that match the finder and False otherwise.

Example

expect($('.item').isPresent()).toBeTruthy();

element.all(locator).locator

As the name suggests, it will return the most relevant locator.

Example

$('#ID1').locator();
// returns by.css('#ID1')
$('#ID1').$('#ID2').locator();
// returns by.css('#ID2')
$$('#ID1').filter(filterFn).get(0).click().locator();
// returns by.css('#ID1')

element.all(locator).then(thenFunction)

It will retrieve the elements represented by the ElementArrayFinder.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

element.all(by.css('.items li')).then(function(arr) {
   expect(arr.length).toEqual(3);
});

element.all(locator).each(eachFunction)

As the name suggests, it will call the input function on each ElementFinder represented by the ElementArrayFinder.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

element.all(by.css('.items li')).each(function(element, index) {
   // It will print First 0, Second 1 and Third 2.
   element.getText().then(function (text) {
      console.log(index, text);
   });
});

element.all(locator).map(mapFunction)

As the name suggests, it will apply a map function on each element within the ElementArrayFinder. It is having two arguments. The First would be the ElementFinder and the second would be the index.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let items = element.all(by.css('.items li')).map(function(elm, index) {
   return {
      index: index,
      text: elm.getText(),
      class: elm.getAttribute('class')
   };
});
expect(items).toEqual([
   {index: 0, text: 'First', class: 'one'},
   {index: 1, text: 'Second', class: 'two'},
   {index: 2, text: 'Third', class: 'three'}
]);

element.all(locator).reduce(reduceFn)

As the name suggests, it will apply a reduce function against an accumulator and every element found using the locator. This function will reduce every element into a single value.

Example

View

<ul class = "items">
   <li>First</li>
   <li>Second</li>
   <li>Third</li>
</ul>

Code

let value = element.all(by.css('.items li')).reduce(function(acc, elem) {
   return elem.getText().then(function(text) {
      return acc + text + ' ';
   });
}, '');
 
expect(value).toEqual('First Second Third ');

element.all(locator).evaluate

As the name suggests, it will evaluate the input whether it is in the scope of the current underlying elements or not.

Example

View

<span class = "foo">{{letiableInScope}}</span>

Code

let value = 
element.all(by.css('.foo')).evaluate('letiableInScope');

element.all(locator).allowAnimations

As the name suggests, it will determine whether the animation is allowed on the current underlying elements or not.

Example

element(by.css('body')).allowAnimations(false);

Chaining functions of ElementFinder and their descriptions

Chaining functions of ElementFinder and their descriptions −

element(locator).clone

As the name suggests, this function will create a shallow copy of the ElementFinder.

element(locator).getWebElement()

It will return the WebElement represented by this ElementFinder and a WebDriver error will be thrown if the element does not exist.

Example

View

<div class="parent">
   some text
</div>

Code

// All the four following expressions are equivalent.
$('.parent').getWebElement();
element(by.css('.parent')).getWebElement();
browser.driver.findElement(by.css('.parent'));
browser.findElement(by.css('.parent'));

element(locator).all(locator)

It will find an array of elements within a parent.

Example

View

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

Code

let items = element(by.css('.parent')).all(by.tagName('li'));

element(locator).element(locator)

It will find elements within a parent.

Example

View

<div class = "parent">
   <div class = "child">
      Child text
      <div>{{person.phone}}</div>
   </div>
</div>

Code

// Calls Chain 2 element.
let child = element(by.css('.parent')).
   element(by.css('.child'));
expect(child.getText()).toBe('Child text\n981-000-568');
 
// Calls Chain 3 element.
let triple = element(by.css('.parent')).
   element(by.css('.child')).
   element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');

element(locator).all(selector)

It will find an array of elements within a parent when calls to $$ may be chained.

Example

View

<div class = "parent">
   <ul>
      <li class = "one">First</li>
      <li class = "two">Second</li>
      <li class = "three">Third</li>
   </ul>
</div>

Code

let items = element(by.css('.parent')).$$('li'));

element(locator).$(locator)

It will find elements within a parent when calls to $ may be chained.

Example

View

<div class = "parent">
   <div class = "child">
      Child text
      <div>{{person.phone}}</div>
  </div>
</div>

Code

// Calls Chain 2 element.
let child = element(by.css('.parent')).
   $('.child'));
expect(child.getText()).toBe('Child text\n981-000-568');
 
// Calls Chain 3 element.
let triple = element(by.css('.parent')).
   $('.child')).
   element(by.binding('person.phone'));
expect(triple.getText()).toBe('981-000-568');

element(locator).isPresent()

It will determine whether the element is presented on the page or not.

Example

View

<span>{{person.name}}</span>

Code

expect(element(by.binding('person.name')).isPresent()).toBe(true);
// will check for the existence of element
 
expect(element(by.binding('notPresent')).isPresent()).toBe(false); 
// will check for the non-existence of element

element(locator).isElementPresent()

It is same as element(locator).isPresent(). The only difference is that it will check whether the element identified by sublocation is present rather than the current element finder.

element.all(locator).evaluate

As the name suggests, it will evaluate the input whether it is on the scope of the current underlying elements or not.

Example

View

<span id = "foo">{{letiableInScope}}</span>

Code

let value = element(by.id('.foo')).evaluate('letiableInScope');

element(locator).allowAnimations

As the name suggests, it will determine whether the animation is allowed on the current underlying elements or not.

Example

element(by.css('body')).allowAnimations(false);

element(locator).equals

As the name suggests, it will compare an element for equality.

Locators(by) API

It is basically a collection of element locator strategies that provide ways of finding elements in Angular applications by binding, model, etc.

Functions and their descriptions

The functions of ProtractorLocators API are as follows −

by.addLocator(locatorName,fuctionOrScript)

It will add a locator to this instance of ProtrcatorBy which further can be used with the element(by.locatorName(args)).

Example

View

<button ng-click = "doAddition()">Go!</button>

Code

// Adding the custom locator.
by.addLocator('buttonTextSimple', function(buttonText, opt_parentElement, opt_rootSelector) {
   var using = opt_parentElement || document,
   buttons = using.querySelectorAll('button');
   return Array.prototype.filter.call(buttons, function(button) {
      return button.textContent === buttonText;
   });
});
element(by.buttonTextSimple('Go!')).click();// Using the custom locator.

by.binding

As the name suggests, it will find an element by text binding. A partial match will be done so that any elements bound to the variables containing the input string will be returned.

Example

View

<span>{{person.name}}</span>
<span ng-bind = "person.email"></span>

Code

var span1 = element(by.binding('person.name'));
expect(span1.getText()).toBe('Foo');
 
var span2 = element(by.binding('person.email'));
expect(span2.getText()).toBe('foo@bar.com');

by.exactbinding

As the name suggests, it will find an element by exact binding.

Example

View

<spangt;{{ person.name }}</spangt;
<span ng-bind = "person-email"gt;</spangt;
<spangt;{{person_phone|uppercase}}</span>

Code

expect(element(by.exactBinding('person.name')).isPresent()).toBe(true);
expect(element(by.exactBinding('person-email')).isPresent()).toBe(true);
expect(element(by.exactBinding('person')).isPresent()).toBe(false);
expect(element(by.exactBinding('person_phone')).isPresent()).toBe(true);
expect(element(by.exactBinding('person_phone|uppercase')).isPresent()).toBe(true);
expect(element(by.exactBinding('phone')).isPresent()).toBe(false);

by.model(modelName)

As the name suggests, it will find an element by ng-model expression.

Example

View

<input type = "text" ng-model = "person.name">

Code

var input = element(by.model('person.name'));
input.sendKeys('123');
expect(input.getAttribute('value')).toBe('Foo123');

by.buttonText

As the name suggests, it will find a button by text.

Example

View

<button>Save</button>

Code

element(by.buttonText('Save'));

by.partialButtonText

As the name suggests, it will find a button by partial text.

Example

View

<button>Save my file</button>

Code

element(by.partialButtonText('Save'));

by.repeater

As the name suggests, it will find an element inside an ng-repeat.

Example

View

<div ng-repeat = "cat in pets">
   <span>{{cat.name}}</span>
   <span>{{cat.age}}</span>
<</div>
<div class = "book-img" ng-repeat-start="book in library">
   <span>{{$index}}</span>
</div>
<div class = "book-info" ng-repeat-end>
   <h4>{{book.name}}</h4>
   <p>{{book.blurb}}</p>
</div>

Code

var secondCat = element(by.repeater('cat in 
pets').row(1)); // It will return the DIV for the second cat.
var firstCatName = element(by.repeater('cat in pets').
   row(0).column('cat.name')); // It will return the SPAN for the first cat's name.

by.exactRepeater

As the name suggests, it will find an element by the exact repeater.

Example

View

<li ng-repeat = "person in peopleWithRedHair"></li>
<li ng-repeat = "car in cars | orderBy:year"></li>

Code

expect(element(by.exactRepeater('person in
peopleWithRedHair')).isPresent())
   .toBe(true);
expect(element(by.exactRepeater('person in
people')).isPresent()).toBe(false);
expect(element(by.exactRepeater('car in cars')).isPresent()).toBe(true);

by.cssContainingText

As the name suggests, it will find the elements, containing exact string, by CSS

Example

View

<ul>
<li class = "pet">Dog</li>
<li class = "pet">Cat</li>
</ul>

Code

var dog = element(by.cssContainingText('.pet', 'Dog')); 
// It will return the li for the dog, but not for the cat.

by.options(optionsDescriptor)

As the name suggests, it will find an element by ng-options expression.

Example

View

<select ng-model = "color" ng-options = "c for c in colors">
   <option value = "0" selected = "selected">red</option>
   <option value = "1">green</option>
</select>

Code

var allOptions = element.all(by.options('c for c in colors'));
expect(allOptions.count()).toEqual(2);
var firstOption = allOptions.first();
expect(firstOption.getText()).toEqual('red');

by.deepCSS(selector)

As the name suggests, it will find an element by CSS selector within the shadow DOM.

Example

View

<div>
   <span id = "outerspan">
      <"shadow tree">
         <span id = "span1"></span>
      <"shadow tree">
      <span id = "span2"></span>
   </>
   </>
</div>

Code

var spans = element.all(by.deepCss('span'));
expect(spans.count()).toEqual(3);

Leave a Reply