3

I have a situation in protractor where I want to store ElementArrayFinder getTexts in Array and return array from method. I have written the method so far like this:

static getAllTexts(elements: ElementArrayFinder) {
    const data: string[] = [];
    elements.each(function(elem) {
        elem.getText().then(function (text) {
            data.push(text);
        });
    });
    return data;
}

Here the method is returning blank array but if I print array content inside promise, it is showing the correct data. Can anyone please help me to rewrite the method so it returns all the array data instead of returning null.

2
  • the methods are asynchronous, you have to find a way to wait for all of them to finish before returning. Commented Jan 31, 2018 at 16:13
  • If your NodeJS supports async/await, you can try, github.com/angular/protractor/blob/master/docs/async-await.md Commented Jan 31, 2018 at 19:09

2 Answers 2

2
static async getAllTexts(elements: ElementArrayFinder): Promise<string[]> {
    return await elements.map(async (element: ElementFinder) => {
       await element.getText();
    }
}

NOTE: you should turn off Control Flow in your protractor.conf.ts: SELENIUM_PROMISE_MANAGER: false

Sign up to request clarification or add additional context in comments.

2 Comments

thx. I see this error : Type 'Promise<{}[]>' is not assignable to type 'string[]'. Property 'includes' is missing in type 'Promise<{}[]>'.
Because elements.map return a Pomise array, but you declare the function return a string[], so the actual return value type not matched the declare type.
1

The root cause return empty array is return data is executed sync, but data.push(text) is executed async. so when getAllTexts() execution completed data.push(text) have not start execute, so you got an empty array.

To fix your code issue, please see below Option 3

Option 1) call getText() on elements directly

static getAllTexts(elements: ElementArrayFinder) {
   // directly return raw text
   return elements.getText();

   // or do some formater
   return elements.getText().then(function(txts){
      return txts.map(function(txt){
          return txt.replace('%', '').trim();
      });
   })
}

Option 2) use map()

static getAllTexts(elements: ElementArrayFinder) {

   return elements.map(function(item){

      // directly return raw text
      return item.getText();

      // or do some formater
      return item.getText().then(function(txt){
         return txt.replace('%', '').trim();
      });
   });
}

Option 3) user each()

static getAllTexts(elements: ElementArrayFinder) {
   var txts = [];

   return elements.each(function(item){
      return item.getText().then(function(txt){

        // directly return raw text
        txts.push(txt);

        // or do some formater
        txts.push(txt.replace('%', '').trim());
      });

   }).then(function(){
      return txts;
   });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.