Navigating through the map function within Protractor

In my Angular application, I have implemented a timeline that displays event dates with their respective descriptions. Below is the HTML source code for this feature:

  <!-- timeline -->
  <h4 class="font-thin m-t-lg m-b-lg text-primary-lt">Historical Timeline</h4>
  <p></p>
  <div id="timeline"class="timeline m-l-sm m-r-sm b-info b-l">
    <div  ng-repeat = "timeline in formattedTimelineData | orderBy : '-eventDate'">
      <div class = "tl-item">
        <i class="pull-left timeline-badge {{timeline.class}} "></i>
        <div class="m-l-lg">
          <div id="eventDate{{$index}}" class="timeline-title">{{timeline.eventDate}}</div>
          <p id="eventDescription{{$index}}" class="timeline-body">{{timeline.description}}</p>
        </div>
      </div>
    </div>
  </div>
  <!-- / timeline -->

I am currently utilizing Protractor to verify that each event date corresponds correctly to its description. To achieve this, I decided to use a map function in my test script. The challenge I encountered was determining how many events there are since they are dynamically generated based on the HTML code provided above. Here's the test code snippet I wrote:

it('FOO TEST', function(){


    var x = 0;
    while(x<4){
   var timeline = element.all(by.css('#timeline')).map(function (timeline) {
       return {
          date: timeline.element(by.css('#eventDate'+x)).getText(),
          events: timeline.element(by.css('#eventDescription'+x)).getText()
     }

   });
      x++
  }

   timeline.then(function (Value) {
    console.log(Value);  
  });

});

The issue I am facing is that when I run the test in the command line, it only prints the details of the last event out of multiple events (5 in this case). It fails to display information about other events. As I am new to working with promises, any suggestions or advice regarding this problem would be greatly appreciated. My goal is to conduct individual tests for each event within the timeline.

Answer №1

The issue lies in the timeline locator: the selector #timeline matches the timeline container instead of the individual timeline blocks. To address this, you can use the following approach:

var timeline = element.all(by.repeater('timeline in formattedTimelineData')).map(function (item) {
    return {
        date: item.element(by.binding('timeline.eventDate')).getText(),
        events: item.element(by.binding('timeline.description')).getText()
    }
});

timeline.then(function (data) {
    console.log(data);
});

You can then iterate over the items like so:

timeline.then(function (data) {
    for (var i = 0; i < data.length; ++i) {
        // perform actions with data[i]
    }
});

Alternatively, you can validate the entire timeline variable as a promise using expect, resolving it implicitly into an array of objects, for example:

expect(timeline).toEqual([
    {
        date: "First date",
        events: "Nothing happened"
    },
    {
        date: "Second date",
        events: "First base"
    },
    {
        date: "Third date",
        events: "Second base"
    }, 
]);

Answer №2

It is not recommended to include logic in your tests, as discussed in this article: .

Using a while loop involves logic.

Before writing your specifications, you should determine the number of events that will be in your timeline, which is 4 in this example case. Your specs should then look like:

element.all(by.css("#timeline")).then(function(events){
    expect(events.count).toEqual(4);
    expect(events[0].someThing()).toEqual(expectedValue0);
    expect(events[1].someThing()).toEqual(expectedValue1);
...
    expect(events[3].someThing()).toEqual(expectedValue3);
 })

Answer №3

I'm encountering a problem with the repeater in my situation due to the large number of elements it contains. My Protractor spec is timing out while looping through all these elements. How can I limit the loop to only run for the first 10 elements of the repeater? I've tried various approaches but haven't been successful. Is there a way to iterate through just the first 10 elements of a repeater when using map()?

In the example above, the timeline variable retrieves data for every element in the repeater. Is there a way to modify this so that the timeline variable only captures data for the first 10 elements of the repeater? Looping through thousands of entries in the repeater is causing my Protractor spec to timeout, so limiting it to the first 10 would be more efficient.

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

Launching the node application using `node` as the starting command is successful, however, using `/usr/bin/node` as the starting

My goal is to configure a node application as a service. To start the service, I must initiate node with an absolute path, specifically using usr/bin/node. However, my application seems to malfunction when launched with this absolute path for unknown rea ...

Ionic's select feature fails to include an object in the options

I'm experiencing an issue where I cannot successfully add a mongoose object to another mongoose object using a select bar within a form. Surprisingly, all the other key-value pairs are inserting correctly, including the checkbox bool. However, for som ...

What causes Jest to throw ReferenceErrors?

Question Does anyone know why I am encountering this error? ● Test suite failed to run ReferenceError: Cannot access 'mockResponseData' before initialization > 1 | const axios = require('axios'); ...

How can the dot badge in Material-UI be enlarged?

I'm in need of a badge component that serves as an indicator without displaying any values. I opted for the dot variant, but it's too small for my liking. I tried modifying it with CSS, but it doesn't seem to be working as expected. Any sugg ...

Removing a Request with specified parameters in MongoDB using NodeJS

Working with Angular 4 and MongoDB, I encountered an issue while attempting to send a delete request. My goal was to delete multiple items based on their IDs using the following setup: deleteData(id) { return this.http.delete(this.api, id) } In order ...

Using Vue.js, separate the values that are separated by commas

I am looking to extract values from a string and store them in an array for use in displaying values in a dropdown format within Vuejs String str = "abc,123,676,uuu". Once I have iterated through the values <li v-for = "value i ...

What is the best way to smoothly scroll to another page using a specific id?

My website consists of multiple pages and I am looking for a code that will allow for smooth scrolling navigation to another page when loading on a specific id or section. For example, in the navbar I have multiple pages with links. When clicking on a lin ...

How can I confirm that all elements have been properly reset to their original positions prior to making any further adjustments to them?

In need of some creative brainstorming, I'm working on a website design featuring ten overlapping cards. When the mouse hovers over a card, it expands while others move away. My goal is for each card to return to its original position once the cursor ...

Is there a method similar to insertBefore that works with arrays and/or HTMLCollections?

Is there a vanilla JavaScript or jQuery function that works like Node.insertBefore(), but for arrays and/or HTMLCollections? An example of what I'm looking for: var list = document.getElementsByClassName("stuff"); var nodeToMove = list[0]; var other ...

Avoid requesting Chrome Camera permission if it has already been granted during a previous WebRTC call

Our web-conference application utilizes a Flash client for video and audio communication. Video is handled through the Red5 Media Server, while audio is managed using WebRTC. When attempting to access the microphone or camera in Flash, users are required ...

In client.js, learn how to retrieve the value of an input tag (Name) from a login form

Let me explain the situation at hand: I'm currently in the process of developing a chat application using socket.io and NodeJS (Express). Initially, I had a simple prompt that asked for the user's name, easily accessible through const name = pro ...

Is there a way to align my two tables next to each other using CSS?

.page { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; } .items { float: left; } .secondItem { vertical-align: text-top; float: right; } .page-header table, th, td { border: 1px solid; display: block; background-color: ...

Angular 1: Handling Multiple Conditions and Exclusions Based on Other Conditions

I have currently added an additional span to accommodate one condition. <div ng-repeat="(key, resultLinks) in resultGroup.resultLinks"> <div ng-if="key < 4 || viewMore" ng-repeat="(subKey, linksWrap) in resultLinks.linksWrap"> & ...

Reposition picture "overlays" additional HTML components

I am struggling with rotating an image by clicking on a button as the image overlaps the buttons. Can anyone provide guidance on how to achieve this without overlapping? For reference, here is my code and an example: here (http://jsfiddle.net/jj03b17n/5/) ...

Are two identical directives conflicting with each other?

In order to identify the bug I am experiencing, I decided to create two instances of the same directive in my view : <criterion-news state="ctrl.state"> </criterion-news> <criterion-news state="null"> </criterion-news> The fir ...

Exploring AngularJS concepts with a focus on understanding view problems (ng-if, ng-switch)

As a beginner diving into the world of AngularJS and JavaScript, I find myself facing a challenge that I hope to get some advice on today. The issue revolves around displaying an input block with or without the "readonly" attribute. To better explain my pr ...

Flask Server produces a response with a considerable delay when accessed through AJAX

I am currently running 2 servers on localhost, each with different ports. One of them is a basic flask server in Python and its code is provided below: from flask import Flask,jsonify from flask_cors import CORS app = Flask(__name__) CORS(app) @app.rout ...

The marriage of Vue 2.0 and Rails 5: Shifting from Reactive to Declarative Rendering

As I make my way through the Vue guide with a Rails 5 app, I've noticed that although I am able to update my Vue js object, the DOM doesn't behave as described in the Declarative Rendering section. The data and the DOM are supposed to be linke ...

Understanding information in Backbone.js

I have multiple backbone models with nested sub-models. Here's how I've approached the solution: Models.Base = Backbone.Model.extend ({ relatedModels: {}, /** * Parses data based on the list of related models. * * @since ...

Unable to bring in the Firebase Firestore Colletion

When working on my next app, I encountered an error while trying to call a Firestore Collection. The specific error message that appeared when I ran the app was: FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicat ...