Analyzing angular grid column cell content in TypeScript by comparing it with an array of strings

I have recently started working with TypeScript and I am trying to extract a list of values from an ag-grid column in order to compare them with a string array. Below is the function I created for this purpose. However, it appears that my ActualRatingsValues.push(text); line is not populating the ActualRatingsValues array as expected. I am unsure if this issue has something to do with promises. Can someone explain how promises work?

validateRatingsValues() {
   const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];
   const ActualRatingsValues: Array<string> = [];
   const wrapper = element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
            .getText()
            .then(text => {
                ActualRatingsValues.push(text);
            });

    let match = true;
    if (ExpectedRatingsValues != null && ActualRatingsValues != null) {
        if (ExpectedRatingsValues.length !== ActualRatingsValues.length) {
            match = false;

        } else {
            for (let i = 0; i < ActualRatingsValues.length; i++) {
                if (ActualRatingsValues[i].toString !== 
                    ExpectedRatingsValues[i].toString) {
                    match = false;
                    break;
                }
            }
        }
    } else {
        match = false;
    }

    expect(match).toBeTruthy();
}

Answer №1

I have identified two issues in the code snippet provided.

1) In order to resolve the first issue, you need to replace ActualRatingsValues.push(text) with ActualRatingsValues.concat(text).

This change is necessary because the function element.all().getText() returns a promise that resolves to an array of strings, not just a string.

2) The second issue revolves around the fact that wrapper is a promise and assigning a value to ActualRatingsValues within a promise won't work as expected. To properly consume the data stored in ActualRatingsValues, you must do so inside the promise using the then() method.

validateRatingsValues() {
    const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];
    const wrapper = element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
            .getText();

    let match = wrapper.then(function(ActualRatingsValues) {
        let length = ExpectedRatingsValues.length;

        for(let i=0;i<length;i++) {
            let find = ActualRatingsValues.includes(ExpectedRatingsValues[i]);
            if (find === false) {
                return find;
            }           
        }

        return true;     
    });

    // The variable 'match' is also a promise which eventually resolves to a boolean value.
    // The reason why the expect statement doesn't consume 'match' inside then() is that Jasmine can detect it's a promise and handles the assertion internally.
    expect(match).toBeTruthy();
}

Answer №2

It's quite surprising that you're not encountering an error while attempting to push to ActualRatingsValues given that it is a const.

The issue at hand is that the lines after your getText() call are being executed before all the promises are resolved. This creates the illusion that it's not functioning as intended. One possible solution would be to utilize async/await.

Below is how you could implement async/await, with some code cleanup included:

async validateRatingsValues() {
    const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];

    // this will wait for all the promises to resolve before continuing
    const wrapper = await element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
              .getText()

    wrapper.forEach(item => {
        expect(ExpectedRatingsValues.indexOf(item)).toBeGreaterThan(-1);

        // this approach should also work
        expect(ExpectedRatingsValues).toContain(item);
    }

    expect(wrapper.length).toEqual(ExpectedRatingsValues.length);
}

There are alternative methods to address this without resorting to async/await. I attempted to demonstrate one briefly but realized it wouldn't suffice. For better insight, consider reviewing the question/answer mentioned by Matt in the comments - it contains valuable information.

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

Creating a diagonal effect on a table using jQuery

I am interested in adding a diagonal effect to my table. For instance, if I have a 5x5 table, I want to highlight the first row and set the background color of the corresponding column in that row to red. The same should be done for each subsequent row. ...

Determine if a variable contains only one digit in Angular 6 using Typescript

I have a specific value that I want to discuss: this.value.day It gives me a numerical output ranging from 1 to 31. My requirement is to add a leading zero if the number is less than 10. Can anyone guide me on achieving this? ...

Tips for executing a series of getJSON requests sequentially, depending on the outcome of the preceding request

Within my project, I am in the process of collecting data from two distinct sources. Initially, it must iterate through an internal JSON file using loop.each to check if the data is available. If not, it then needs to initiate a second request using $.getj ...

Using Angular's ui-router to nest ui-views inside of one another

Currently, I am working on an application using AngularJS UI routes and despite hours of searching online, I am still struggling to resolve my issue. Here is the code I am working with. Any help would be greatly appreciated. I am trying to figure out how ...

Proper method to update the outdated R70 threejs code for compatibility with the latest version

I've encountered an issue with a piece of code that throws an error, although it functions perfectly in this jsfiddle. The goal is to rotate a cube and pan it using trackball controls. It works in the fiddle, but when I bring it into visual studio, Ch ...

Callback function for asynchronous operations on the client side with Meteor

Is there a way to retrieve the value returned by an asynchronous callback in the client-side of Meteor before the stack continues executing? Here is code snippet as an example: var result=function(str){ Meteor.call("getSearch",str,function(err,res){ ...

`Even though I specified `{cache: $templateCache}` in the $http call, the directive is still showing $templateCache as

I have two HTML pages named snippet1.html and snippet2.html. I want to use them within my directive in order to add multiple templates using a single directive. To achieve this, I initially tried adding the HTML templates within <script> tags and as ...

Is there a way for me to detect variations in the input and subsequently alter the text?

I'm facing a situation with my HTML code: <label for="date">START DATE: <input id="date" name="date" type="number"> <span>days</span> <label> I am looking for a way to change the text inside the span element based o ...

Utilizing HTML/CSS with React/Bootstrap: A Comprehensive Guide

Looking for help with integrating HTML/CSS code into React/Bootstrap? I need assistance with coding in React using Bootstrap. How do I effectively use components and props? Even after installing bootstrap, I am encountering errors. Is it possible to dire ...

Frequent occurrence when a variable is utilized prior to being assigned

I am currently working with a module import pino, { Logger } from 'pino'; let logger: Logger; if (process.env.NODE_ENV === 'production') { const dest = pino.extreme(); logger = pino(dest); } if (process.env.NODE_ENV === &apo ...

Is there a way to identify the browser version that is being used?

I've been on the lookout for a specific code snippet that can help me identify whether the user visiting my website is using Firefox 3 or 4. Thus far, I have only come across code to determine the type of browser without indicating the version. Is th ...

Find a partial match in the regular expression

I am currently working on filtering a list of names using regular expressions (regex). The data is stored in the following format: [ { "firstName": "Jhon", "lastName": "Doe", }, ... ] Users have the option t ...

Error: Value not defined in the (Node, Express, Pug, JQuery) environment

I'm encountering a common issue as a beginner and could really use some assistance. I have tried multiple solutions but still can't resolve the error "ReferenceError: $ is not defined" when attempting to use jQuery. My project structure looks lik ...

Implementing Object-Oriented Programming (OOP) to insert data into a database in PHP

Seeking a method to insert data into a MySQL database without the need to refresh the page and ensuring no security vulnerabilities. After several hours of experimenting and researching, I have come up with this solution: <form name="form1" action="" ...

a guide on using ajax to distribute retrieved data among various td elements

After the user presses a button, the data is saved into the database. Upon success, I need to retrieve the data from the database and place it in the appropriate td (in the same row as the clicked td). I've been able to successfully retrieve the data, ...

Can next.js rewrites be configured with environment variables?

Currently, I am in the process of developing my application with a next.js frontend and express.js backend. During development, I simply run the relevant dev servers in the terminal. However, now I am looking to deploy my app using Docker for production. I ...

Issue with reCAPTCHA callback in Firebase Phone Authentication not functioning as expected

I have been working on integrating phone authentication into my NextJS website. I added the reCAPTCHA code within my useEffect, but for some reason, it does not get triggered when the button with the specified id is clicked. Surprisingly, there are no erro ...

Vue - Troubleshooting why components are not re-rendering after data updates with a method

Check out this simple vue component I created: <template> <div class="incrementor"> <p v-text="counter"></p> <button v-on:click="increment()">Increment</button> </div> </template> <script lan ...

I encountered a MISSING_MESSAGE error while using the next-intl npm package in my next.js application

import { useEffect } from "react"; import type { AppProps } from "next/app"; import Script from "next/script"; import { SWRConfig } from "swr"; import { useRouter } from "next/router" import { AppContext } ...

Unable to access the current state within an asynchronous function in React.js

I have encountered an issue with updating state in the top-level component (App) and accessing the updated state in an asynchronous function defined within useEffect(). Here are more details: The problem arises when I try to retrieve the state of the cons ...