1

My Code is like

async function myTestFunc(){
               let items:ElementArrayFinder = await element.all( by.xpath("./li"));
}

That code gives below error

'items' is declared but its value is never read.ts(6133)
Type 'any[] | ElementFinder[]' is not assignable to type 'ElementArrayFinder'.
Type 'any[]' is missing the following properties from type 'ElementArrayFinder': browser_, getWebElements, locator_, actionResults_, and 35 more

Docs say "element.all" returns "ElementArrayFinder".

but when "element.all" used within async/await function it seems to be returning "ElementFinder[]".

How is that possible ? because of this I can't use methods like "each()" or "get()" in "ElementArrayFinder".

What is the best possible way to use "element.all" within "ElementArrayFinder" ?

This is my package.json

"devDependencies": {
    "@types/jasmine": "^3.3.5",
    "@types/node": "^10.12.18",
    "protractor": "^5.4.2",
    "typescript": "^3.2.2"
  },
  "dependencies": {
    "@types/jasmine-data-provider": "^2.2.1",
    "jasmine-data-provider": "^2.2.0",
    "protractor-jasmine2-html-reporter": "0.0.7"
  }
AMendis
  • 1,346
  • 4
  • 18
  • 34

2 Answers2

0

What version of protractor are you using? The ElementFinder[] syntax is used internally by protractor and must have snuck out somehow. This was an issue in 5.2.0 but I believe it is fixed in the current version (5.4.2). If you look at the source code, there is a change to the function that handles this, Starting around line 550,

* @param {function(Array.<ElementFinder>)} fn
* @param {function(Error)} errorFn
*
* @returns {!webdriver.promise.Promise} A promise which will resolve to
*     an array of ElementFinders represented by the ElementArrayFinder.
*/
then<T>(
    fn?: (value: ElementFinder[] | any[]) => T | wdpromise.IThenable<T>,
    errorFn?: (error: any) => any): wdpromise.Promise<T> {
      if (this.actionResults_) {
      return this.actionResults_.then(fn, errorFn);
} else {
  return this.asElementFinders_().then(fn, errorFn);
}
}

Whereas it used to just be

@param {function(Array.<ElementFinder>)} fn
* @param {function(Error)} errorFn
*
* @returns {!webdriver.promise.Promise} A promise which will resolve to
*     an array of ElementFinders represented by the ElementArrayFinder.
*/
then<T>(fn?: (value: ElementFinder[] | any[]) => T | wdpromise.IThenable<T>, 
errorFn?: (error: any) => any): wdpromise.Promise<T>;

Long story short, what version are you on and does an upgrade help?

C. Peck
  • 3,641
  • 3
  • 19
  • 36
  • This is my package.json i'm using protractor 5.4.2 "devDependencies": { "@types/jasmine": "^3.3.5", "@types/node": "^10.12.18", "protractor": "^5.4.2", "typescript": "^3.2.2" }, "dependencies": { "@types/jasmine-data-provider": "^2.2.1", "jasmine-data-provider": "^2.2.0", "protractor-jasmine2-html-reporter": "0.0.7" } – AMendis Mar 10 '19 at 03:31
  • Darn I thought I had it. You could try adding `promise.USE_PROMISE_MANAGER = false` before your function that makes call(s) to `element.all` or `element.each`, then `promise.USE_PROMISE_MANAGER = true` afterwards. I don't know if that will adversely affect your code but it might solve this issue. – C. Peck Mar 10 '19 at 04:07
0

The answer is simple: element.all has it's own then function, declared separately.

So when you doing like so

let result = element.all();

You will get ElementArrayFinder as a result, as it specified in Returns section. ElementArrayFinder is an object, that has all the specified functions you wanned get, each and etc.

But if turn it into a promise,

let result = await element.all();

then it will return A promise which will resolve to an array of ElementFinders represented by the ElementArrayFinder. which is basically ElementFinder[] as specified in Returns section of ElementArrayFinder.prototype.then function.

Majesty
  • 2,097
  • 5
  • 24
  • 55