Retrieving text from an array of elements using Protractor

Hello everyone, this is my first post so please be gentle with me. :)

I am a newcomer to protractor and I could really use your assistance. I have been tasked with writing a test for the following code snippet:

<div class="content ps-container ps-active-y expand" ng-class={hide:items.length === 2}" ng-transclude="" csf-product-navigator-content="" csf-scrollbar="" style="">
 <div class="product-wrp prod-active" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">
  <div class="product-wrp odd" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">
   <div class="product-item animate-hide" ng-click="onDropdowmItemClick()" ng-transclude="" csf-product-navigator-anim-item="">
    <div class="ng-scope" ng-repeat="product in accounts" csf-product-navigator-item="">
     <div class="navigator-view ng-hide" ng-show="active">
      <div class="" ng-hide="active">
       <div class="product-choice ng-scope" ng-if="product.type !== 'SM'">
        <section class="product-name">
         <header class="ng-scope" ng-if="product.name">
          <p class="product-details" ng-show="product.type">
           <span class="ng-binding" ng-bind="product.no">PL84 9101 0003 2001 0006 1883 0004</span>
          </p>
        </section>
        <section class="product-amount">
       </div>
      </div>
     </div>
    </div>
   </div>
  <div class="product-wrp even" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">
  <div class="product-wrp even" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">
  <div class="product-wrp odd" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">
  <div class="product-wrp even" ng-class="{'prod-active' : active, 'odd' : (odd === true && !active), 'even' : (odd !== true && !active)}" ng-repeat="product in accounts" csf-product-navigator-item="">

My objective is to determine the number of products on the dropdown list.

Therefore, I believe that obtaining all elements in the container and then iterating through them using a function could help achieve this goal.

Here's the code I've come up with:

Features (iOwe):

var iOwe = function () {
  this.accNo = element(by.className('content ps-container ps-active-y expand')).all(by.className('product-item animate-hide'))
}

Spec (iOwe):

it('should display account numbers on the dropdown list', function () {
  expect(iOwe.accNo.count()).not.toBe(0);
  iOwe.accNo.each(function(elem) {
    elem.element(by.className('product-details')).getText()
    .then
    (function (text){
        console.log(text);
    });
  });

The issue I'm encountering is that every time I run the tests, the output in the console varies. It only displays the first 3 or 4 strings instead of all 7, leaving the rest empty.

Thank you for your assistance.

EDIT: To understand what exactly happens during the test, I added browser.sleep(5000); each time a string is printed in the console. Surprisingly, I discovered that I need to visually see the following account in the browser in order for the test to read it correctly.

Answer №1

The objective is to determine the quantity of products listed in the dropdown menu.

An effective method to achieve this is by utilizing the by.repeater() locator:

var productItems = element.all(by.repeater("item in products"));
expect(productItems.count()).toEqual(7);

Alternatively, it can also be done using a CSS selector:

var productItems = $$("div.product-info");
expect(productItems.count()).toEqual(7);

In case there are timing issues, you can implement a function to wait for a specific count of elements matching a certain locator:

function waitForElementCount(elements, expectedCount) {
    return elements.count().then(actualCount) {
        return actualCount >= expectedCount;
    });
}

browser.wait(waitForElementCount($$("div.product-info"), 7), 5000);

Answer №2

After seeking a solution to my question, I discovered that the issue was not with selectors/matchers.

Through this informative Article, I learned that in order to retrieve text using .getText(), the element must actually be visible in the browser; otherwise, it will return an empty string.

To work around this limitation, I opted to use:

.getAttribute()

to extract the desired string.

In essence, I modified :

elem.element(by.css('span.ng-binding')).getText()

to

elem.element(by.css('span.ng-binding')).getAttribute('outerHTML')

This approach successfully returned the string containing the account number.

However, it did not fully meet my requirements.

I wanted to verify if the element was truly visible in the browser, making the previous solution ineffective.

Subsequently, I came across this relevant Question which provided insights on scrolling down to the desired element in the browser.

With this new knowledge, I adjusted my code as follows:

it('should display accounts numbers on dropdown list', function () {
  expect(iOwe.accNo.count()).not.toBe(0);
  iOwe.accNo.each(function(elem) {
    browser.executeScript('arguments[0].scrollIntoView()', elem.getWebElement()) //Scroll down to element
    .then
    elem.element(by.className('product-details')).getText()
    .then
    (function (text){
      console.log(text);
    });
});

Thus, this serves as the resolution to my initial query.

Grateful for the assistance!

Answer №3

Consider trying out a similar approach:

describe('checking if account numbers are visible in dropdown list', function () {
it('should verify that there are account numbers displayed', function () {
expect(accountList.accountNumbers.count()).not.toEqual(0);
accountList.accountNumbers.each(function(element) {
expect(element.element(by.css('p.product-details')).isDisplayed()).toBe(true);
element.element(by.css('span.ng-binding')).getText().then(function (text){
    console.log(text);
});
});
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

It is no longer recommended to use getPreventDefault(). Instead, defaultPrevented should be used

Is there a way to automatically print the receipt page when loaded in Firefox? While attempting to do so, Firefox displays the following error: Use of getPreventDefault() is deprecated. Please use defaultPrevented instead. Error source line: src.getPrev ...

What methods does reCAPTCHA 3 use to detect if I am utilizing Selenium or chromedriver?

I am intrigued about the inner workings of reCAPTCHA v3, particularly its browser fingerprinting techniques. After conducting tests against reCAPTCHA 3 using Selenium/chromedriver and launching an instance of Chrome, I consistently receive a score of 0.1. ...

What's the most effective method for isolating elements in HTML to prevent one element from impacting another?

I recently created a password form in HTML with some nice functions. However, after making a small adjustment, the CSS is causing the elements to shift when clicking on different input boxes. This results in the labels on the form moving slightly up and do ...

Looking for advice on automating Facebook integration testing?

Given the widespread use of Facebook login/connect for website authentication, is there a standard recommendation from Facebook or other sources on automating the process? This would involve clicking the Facebook button to bring up a popup, switching to th ...

Finding a document in MongoDB that meets specific array size criteria

Consider the structure of the document below: { _id : Mongo ID, data : [someData1, someData2, ..., someDataN] } To retrieve documents where the size of data falls between a and b (where a < b), one might initially think to use $size. However, acco ...

Creating arrays with string indices dynamically in PHP

Here's a scenario I'm dealing with: $str = "eat.fruit.apple.good"; The objective is to manipulate an array in this format: $arr["eat"]["fruit"]["apple"]["good"] = true; I'm unsure how to achieve this dynamically. Appreciate any guidance. ...

Utilize JQuery's ajax .load() method to correctly link to the specific URL

I currently have a local server with multiple projects, and for this specific project in VS2010 properties->web->use local IIS web server = 'localhost/project4/'. (I'm unable to utilize the regular debug VS Development Server due to ce ...

JestJS: Async testing isn't halted

I am facing two issues with my jest test: Is there a way to define the Content collection only once instead of repeating it inside the test? I encountered this error: Jest did not exit one second after the test run has completed. This usually indicates ...

Customize div background with an image captured by a camera

I am currently working on developing a mobile application using PhoneGap for Android. One of the tasks I am trying to accomplish is setting the background of a div element to the photo captured using the device's camera. The camera functionality is w ...

Sustain information across two pages using Next.js

Recently, I have been considering reorganizing my Next.js webapp to allocate different pages for handling various screens. Currently, I have a component that manages multiple states to determine the screen being displayed. Within the jsx section, I utilize ...

Issue with Adding Additional Property to react-leaflet Marker Component in TypeScript

I'm attempting to include an extra property count in the Marker component provided by react-leaflet. Unfortunately, we're encountering an error. Type '{ children: Element; position: [number, number]; key: number; count: number; }' is n ...

What could be the reason my ImageMapster jquery plugin is not functioning in the Power Apps portal's code editor?

I'm attempting to add hover effects to an image map within my Power Apps portal site using the code editor. However, when I include the script: <script type="text/javascript">$('img').mapster();</script> for the desire ...

Having trouble clicking on an element in Selenium Webdriver with Python? It seems like the property 'click' is returning null

Encountering an error when attempting to execute this command: driver.find_element_by_link_text("Confirm").click() selenium.common.exceptions.WebDriverException: Message: unknown error: Element <a href="javascript:void(0);" class="c-button u-fontSize1 ...

Transitioning from Event-driven Object Oriented design to Redux structure

I currently have a structure that is mostly object-oriented and I am considering migrating to React/Redux due to handling issues with events. I have various modules with objects structured like this: User { getName() getSurname() etc... } These obj ...

Manually adjust rotation in Three.js by clicking

I am looking to initiate an animated rotation of an object by clicking a button. I have a basic understanding that the render function operates as an infinite loop and that adding 0.1 to cylinder.rotation.x continuously rotates the object. My goal is to ...

Tips for using jQuery to send a file to the connect-busboy module in nodejs

Successfully sending a file to connect-busboy can be achieved by utilizing an HTML form's action attribute in the following manner: <form ref='uploadForm' method="post" action="http://localhost:3000/fileupload" enctype="multipart/form-da ...

Obtain the nth key from a PHP associative array

Is there a way to retrieve the key of a specific entry in an associative PHP array without knowing its value beforehand? Let's say I want to access the key of the second entry in the array. For instance: $array = array('customer' => &ap ...

What is the best way to manage the "open link in a new tab" action?

I am currently working on a project that involves displaying a series of resources on a web page. Each resource is stored as a record in a database with two fields: "url" and "visited." One issue I have encountered is that when a user clicks on a resource ...

Cookies are swiftly dispatched with headers and securely stored, only to disappear upon reloading

I have extensively researched various topics related to this issue, but I still haven't been able to resolve the problem. The Set-Cookie is present in the response headers as shown below, albeit with a minor warning. Since I am using HTTP, I am requir ...

Best Practices for Organizing Files in a Node.js Application

In order to create a more organized and efficient App with duplex communication and database access using Node.js (utilizing socket.io and mysql modules), I am seeking advice on how to source out specific functionalities into separate files. My goal is to ...