Keeping data external to promises in protractor

In my angular app, I have a timeline feature that displays the names and descriptions of players. All player names are under the common class player-title.ng-binding, while all player descriptions share the class .player-description.ng-binding

To retrieve the names and descriptions, I used the following code:

  element.all(by.css('.player-title.ng-binding')).getText().then(function(name){
        //prints name of first player
        console.log(name[0]);
  });


  element.all(by.css('.player-description.ng-binding')).getText().then(function(description){
        //prints description of first player
        console.log(description[0]);
  });

However, I'm struggling to verify that each player has the correct description. For example, using

expect(name[0]).toEqual(description[0]);
. I'm new to promises and would appreciate any advice on this issue.

Additionally, when I tried the following code, it printed undefined:

  var name = element.all(by.css('.player-title.ng-binding')).getText().then(function(name){

  });

  console.log(name[0]);

Below is the HTML code for displaying players:

 <!-- player -->
  <h4 class="font-thin m-t-lg m-b-lg text-primary-lt">Sponsor player</h4>
  <p></p>
  <div class="player m-l-sm m-r-sm b-info b-l">
    <div  ng-repeat = "player in formattedplayerData | orderBy : '-Name'">
      <div class = "tl-item">
        <i class="pull-left player-badge {{player.class}} "></i>
        <div class="m-l-lg">
          <div class="player-title">{{player.Name}}</div>
          <p class="player-description">{{player.description}}</p>
        </div>
      </div>
    </div>
  </div>
  <!-- / player -->

Any insights or suggestions on this topic would be greatly appreciated.

Answer №1

If you wish to verify whether the name matches the description:

var name = element.all(by.css('.player-title.ng-binding'))
  .first()
  .getText();

var description = element.all(by.css('.player-description.ng-binding'))
  .first()
  .getText();

var compareNameDesc = Promise.all([name, description]).then(function(info) {
  var name = info[0], description = info[1];
  return name === description;
});

expect(compareNameDesc).toBe(true);

To validate each name and description individually:

var correctNames = [...];
var correctDescriptions = [...];
var names = element.all(by.css('.player-title.ng-binding'));
var descriptions = element.all(by.css('.player-title.ng-binding'));
for (var i = 0; i < correctNames.length; i++) {
  expect(names.get(i).getText()).toEqual(correctNames[i]);
  expect(descriptions.get(i).getText()).toEqual(correctDescriptions[i]);
}

For more details, visit ElementArrayFinder#get

EDIT: To ensure that all names match all descriptions (as requested in comment):

var names = element.all(by.css('.player-title.ng-binding'))
  .map(getText);
var descriptions = element.all(by.css('.player-title.ng-binding'))
  .map(getText);

var namesMatchDescriptions = Promise.all([names, descriptions])
  .then(function(results) {
    return results[0].every(function(name, index) {
      return name === results[1][index];
    });
  });

expect(namesMatchDescriptions).toBe(true);

This approach utilizes map as recommended by @alecxe, in conjunction with Array#every

Additional Information:

Remember that promises operate asynchronously, so when using your last code block, accessing console.log(name[0]), name is a promise instance without a property 0, resulting in undefined.

In protractor, expect handles promises, enabling evaluation of actual values by unwrapping promises provided to expect().

Promises also unwind, meaning if a promise is returned within a then() call, the original promise-assigned variable will be fulfilled with that value.

Therefore, you can return both name and description from separate promises, subsequently applying these promises to expect.

Moreover, consider implementing first instead of utilizing then with an index.

var name = element.all(by.css('.player-title.ng-binding'))
  .first()
  .getText();

var description = element.all(by.css('.player-description.ng-binding'))
  .first()
  .getText();

expect(name).toEqual('name');
expect(description).toEqual('description');

Key Insights:

  • Although promises may be intricate, correctly employing them simplifies management.
  • ElementArrayFinder methods facilitate access to various elements within collections
  • Promise.all enables synchronization of promise completions
  • Operations like every, some, and reduce within lists can generate insights into the relationship between two collections; ideally this process should be more straightforward!

Answer №2

One approach that can be considered more elongated is by utilizing the map() function:

var players = element.all(by.css("div.tl-item")).map(function (player) {
    return {
        name: player.element(by.css("div.player-title")).getText(),
        description: player.element(by.css("p.player-description")).getText()
    }
});

The variable players would hold a promise that will eventually yield an array of player objects. To view the actual content of players, resolve the promise:

players.then(function (playersValue) {
    console.log(playersValue);
});

Alternatively, you can compare it to an expected array:

expect(players).toEqual([
    {name: "Player 1", description: "Player description 1"},
    {name: "Player 2", description: "Player description 2"}
]);

You also have the option to access players by index:

players.then(function (playersValue) {
    expect(playersValue[0].name).toEqual("Player 1");
    expect(playersValue[0].description).toEqual("Player description 1");
});

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

How to Fetch a Singular Value from a Service in Angular 4 Using a Defined Pattern

I am currently working on developing a service in Angular 4 (supported by a C# RESTful API) that will facilitate the storage and retrieval of web-application wide settings. Essentially, it's like a system for key-value pair lookups for all common appl ...

Using JavaScript to calculate dimensions based on the viewport's width and height

I have been trying to establish a responsive point in my mobile Webview by implementing the following JavaScript code: var w = window.innerWidth-40; var h = window.innerHeight-100; So far, this solution has been working effectively. However, I noticed th ...

How can I dynamically assign ngModel in AngularJS?

I've created a directive with an isolate scope that maps a list of objects to inputs for modifying a specific property. However, I now aim to make this component more universal by allowing it to bind to deeply nested properties within each object. Fo ...

Karma issue: The application myApp has not been defined

Currently, I am attempting to run tests on the Angular seed project using a fresh installation of Karma in a separate directory. I have not made any modifications to the Angular seed project. However, I am encountering an issue where both myApp and myApp.V ...

Combining two elements in Angular 2

I am looking to find the intersection of two objects. My goal is to compare these objects and if they have matching values on corresponding keys, then I want to add them to a new object. obj1 = { "Projects": [ "test" ], "Companies": [ "facebook", "google ...

The event "subscriptionRemoved" is not being triggered when a password change is made on the Microsoft Graph API

Utilizing the Microsoft Graph API, I have set up subscriptions to receive notifications for calendar events through Node.js. As per the guidelines outlined in the documentation on Enhancing notification reliability for Outlook resources (preview), it speci ...

React state change is causing a functional component to not re-render

When attempting to map out a nested array from the data retrieved by an http request in a functional component, you may encounter a frustrating error: "TypeError: Cannot read property 'map' of undefined". Even though the state is updated correctl ...

Utilize AJAX and jQuery to seamlessly submit a form

I am attempting to use jQuery and AJAX to submit a form in order to add a row to a table called cadreSante (which is in French). The code I am using for this operation is provided below. Can someone please identify any errors in the code and suggest ways t ...

Tips for retrieving data from a Node.js server with a POST request in a React application

I'm currently working on a MERN authentication project, but I've hit a roadblock. Whenever the information is submitted on my register page, it triggers an add user function on the front end. async function addUser(user) { const config = { ...

Exploring the Node.js Connector: Utilizing Collection.remove

I can't wrap my head around the meaning of this: w, {Number/String, > -1 || ‘majority’ || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = ‘majority’ or tag acknowledges the ...

Utilizing Three.js Texture with shaderMaterial

I'm encountering an issue where I can't seem to load a texture onto my shader material, resulting in just black dots appearing. Here's the code snippet from my shader.js: THREE.ShaderLib['cloud'] = { uniforms: { textu ...

Retrieve information from subcategories in the Realtime Database using Firebase

Trying to access message inputs from ALL users has been a challenge. While it can be done for a specific user, the goal is to do so for all users by specifying in the code. Each UID is unique, adding complexity to the process. The Realtime Database struct ...

How to access and utilize parent directive methods effectively in AngularJS

Looking for advice on the best way to utilize parent directive methods in its child directive. Option one: Pass it as a scope parameter in the HTML where you initialize the child directive. Option two: Make the parent directive required and gain ...

What methods can be used to ensure the document in mongoose is not deleted by updating the expires property on the createdAt field?

I have implemented account verification in this app and created a user account that is set to delete itself after 30 seconds if not verified. createdAt: { type: Date, default: Date.now, index: { expires: 30, }, }, However, I am now searching f ...

Steps for finding an element in Selenium

I am having trouble clicking on an icon between two icons because they both have the same class name. Even though they have different xpaths, the findElement(By.xpath()) method is not working due to lack of a handler in the xpath. Here is the HTML code sho ...

Using a JavaScript "for each" loop instead of having several "if

Could you please provide guidance on where to proceed? There are multiple input rows, with each row containing a field with the class row_changed If the value in the field is greater than 0, ajax will send the entire row to PHP. Each row is wrapped in a ...

What is the reason for being unable to remove the event listener from a sibling element?

function show1() { console.log("ok1"); document.getElementById("a2").removeEventListener("click", delegate); } function show2() { console.log("ok2"); } function show3() { console.log("ok3"); } function delegate(event) { var flag = event.target ...

How can I address multiple buttons with various events using jQuery?

I am new to learning jQuery and I'm currently working on some exercises. However, I've run into an issue with two buttons in the DOM that are supposed to perform different actions. I can't seem to figure out how to assign different functions ...

Creating a JavaScript function for a custom timed traffic light sequence

Currently, I am facing a challenge with my high school project of creating a timed traffic light sequence using JavaScript for my upcoming exams. Unfortunately, I feel quite lost and unsure about how to proceed. My initial plan involves formatting the valu ...

Error in Firefox when converting a string to a date in JavaScript using the format mm-dd-yyyy

Hi, I am encountering an issue with converting a string in the format mm-dd-yyyy into a date object. While it works perfectly fine in Internet Explorer and Chrome, it does not work in Firefox as it returns an invalid date at times. I have also tried using ...