0

I want to build a custom method which will wait for the element and return the element.all(by by)

I used the return type as ElementArrayFinder but it's throwing error as shown in screenshot, can anybody guide what's the problem here? I am using async / await with this method

static async getElements(byEl: any): ElementArrayFinder{
    await browser.wait(Util.EC.presenceOf(element(byEl)), 30000, 'Element not found');
    return await element.all(byEl);
}

ypescript

sunpat
  • 389
  • 2
  • 7
  • 28
  • Async functions should always return promises. So, `Promise` in your case, I suppose. – VLAZ Apr 29 '20 at 12:17
  • Tried that one, but got the following error on the return await ... line as '''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.ts(2322)''' – sunpat Apr 29 '20 at 12:21
  • Then you're not returning the correct thing... – VLAZ Apr 29 '20 at 12:34
  • That is my question, where am I missing? how to wait for element.all(...) and return that element.all(...) – sunpat Apr 29 '20 at 12:59
  • doesn't `element.all` return *multiple* things? I'm not aware of the API but this is what it sounds like, to me. And the error message from TS does suggest that's exactly what happens. So, if you want to return a *single* element, either extract it or use a different method that returns one thing, not multiple. – VLAZ Apr 29 '20 at 13:01
  • element.all returns an `elementArrayFinder` but when you await an elementArrayFinder it become and array of `elementFinder` objects. The difference is subtle but I elaborated more on the distinction [here](https://stackoverflow.com/questions/60165939/when-should-element-alllocator-thenthenfunction-or-element-alllocator-be-u/60170389#60170389). Try VLAZs first suggestion, removing the await – DublinDev Apr 29 '20 at 13:05
  • @DublinDev I don't really suggest removing the `await`. It really doesn't matter - in either case an async function always returns a promise. And promises are auto-flattened, so the result can *only* be `Promise` regardless of what you return. However, if the return type is declared as a *single* item and you return an *array*, then that clashes with the declaration. – VLAZ Apr 29 '20 at 13:21

2 Answers2

0

Hope this helps your needs.

public getAllElements(locator: Locator): ElementArrayFinder {
    return element.all(locator);
}

public async waitForAllElements(elements: ElementArrayFinder) {
    const elFinders: ElementFinder[] = await elements.asElementFinders_();
    for (const [index, el] of elFinders.entries()) {
        await browser.wait(ExpectedConditions.presenceOf(el), 30000, 'Element not found for index ' + index);
    }
}

public async test() {
    const allElements = this.getAllElements(by.css('something'));
    await this.waitForAllElements(allElements);
}
Infern0
  • 2,565
  • 1
  • 8
  • 21
0

Here is what I made it - Single method to wait with return the element.all() and worked out fine.

static async getElements(byEl: any): Promise<ElementFinder[]>{
    await browser.wait(Util.EC.presenceOf(element(byEl)), 30000, 'Element taking too long to appear in the DOM');
    return await element.all(byEl).asElementFinders_();
}

and as a consumer we can use -

static async size(byEl: any): Promise<number>{
    return (await this.getElements(byEl)).length;
}

Thanks everyone, for spending time!

sunpat
  • 389
  • 2
  • 7
  • 28