Protractor: browser.actions().click() does not work with async/await

Created on 8 Nov 2017  路  11Comments  路  Source: angular/protractor

Hi,
I am converting my protractor tests from Promises to async/await and I found something weird with browser actions click. The problem is that the click() does not execute, but the mouseMove does.
The click() works when test is written as a promise not async/await

Here is the test and the browser.actions function

  it('When entering selection state selection toolbar should appear', async () => {
    const page = new SingleObjectPage();
    await page.get('barchart', 'PWFwr', 'select=clearall');
    await page.activateSelectionMode($(barlayer));
    await browser.wait(EC.visibilityOf($(SingleObjectPage.selectors.object.confirmButton)), timeout, 'Confirm button did not appear');
  });

  activateSelectionMode(element) {
    return browser.actions()
      .mouseMove(element, {
        x: 20,
        y: 75,
      })
      .click()
      .perform();
  }

I found a workaround to get it to work.

  activateSelectionMode(element) {
    return browser.actions()
      .mouseMove(element, {
        x: 20,
        y: 75,
      })
      .perform().then(() => browser.actions()
        .click()
        .perform());
  }

Bug report

Most helpful comment

Note: I am using a wrapper class for element. Replace this.webElement with your element variable.

This is how I am doing it with async and await:

await browser.actions()
             .mouseMove(this.webElement.getWebElement(), {x: 10, y: 10,})
             .perform();

return  await browser.actions().doubleClick().perform();

All 11 comments

Have you tried the following?
async activateSelectionMode(element) { return await browser.actions() .mouseMove(element, { x: 20, y: 75, }) .click() .perform(); }

The reason why your work around works is because perform() and click() return promises. In you work around you do .perform().then(function() {...} which handles the perform promise and then does the click action.
If you make the method async/await it'll wait for the promises to be resolved before going back and continuing.

@Haseeb90 Thanks for your input, unfortunately it did not work.

I have had a same problem. @pontusnyman thank you. Your work around worked.

@Haseeb90 unfortunently it did not work.

Using workflow, every thing was fine. Through using async/await, it was not.

Hi everyone.
Same issue here. Thank you @pontusnyman for your workaround which works for me.

any updates on this? My codebase is in limbo state due to this.

@arjunUnniumbath You could always migrate back to using promises. That's what I've done in my project. The lack of this support is a deal breaker for me. Using browser.actions() is the only way I've been able to "swipe left" and delete a row with Ionic.

// delete the holding - https://forum.ionicframework.com/t/move-ion-item-sliding-by-protractor/106918
browser.actions().mouseDown(addedHolding)
  .mouseMove({x: -50, y: 0})
  .mouseMove({x: -50, y: 0})
  .mouseMove({x: -50, y: 0})
  .mouseUp()
  .perform();

homePage.deleteButton.click();
element.all(by.css('.message')).then((message) => {
  expect(message.length).toBe(1);
});

Hi, @pontusnyman ! Try this workaround. Hope it'll help you!

Note: I am using a wrapper class for element. Replace this.webElement with your element variable.

This is how I am doing it with async and await:

await browser.actions()
             .mouseMove(this.webElement.getWebElement(), {x: 10, y: 10,})
             .perform();

return  await browser.actions().doubleClick().perform();

I'm doing this in an 'actions wrapper':

await browser.actions().mouseMove(elementToClick).perform();
await browser.actions().click(elementToClick).perform();

Which is lame sauce because the docs for ActionSequence.click() say:

If an element is provided, the mouse will first be moved to the center
of that element. This is equivalent to:

     sequence.mouseMove(element).click()

Trying to move away from control flow as that seems like the recommended approach, this is an obstacle to that.

Hi,
I'm also stuck in this situation and I'm using selenium-webdriver. I tried everything in this thread but no luck. My last approach is as follows but it does not click the required element. Can you please help.

exports.clickOnMiddle = (el) => {
var actionChain = driver.actions({ bridge: true });
return actionChain.move({ origin: el, x: 5, y: 5 })
.perform().then(() => actionChain.click()
.perform());
};

  • My browser is chrome.

came here after wasting half a day on browser.actions().dragAndDrop not working. @pontusnyman , thank you for reporting your workaround! The following works for me using Angular Material drag and drop :

private dragAndDrop(element: WebElement, destination: WebElement) {
    return browser.actions().mouseDown(element).perform()
      .then(() => browser.actions().mouseMove(destination).perform())
      .then(() => browser.actions().mouseUp(destination).perform());
  }

Also, the async version works:

private async dragAndDrop(element: WebElement, destination: WebElement) {
    await browser.actions().mouseDown(element).perform();
    await browser.actions().mouseMove(destination).perform();
    await browser.actions().mouseUp(destination).perform();
  }

But change anything ever so slightly and it falls apart. Also, destination is found using css selector .cdk-drop-list. Hope it helps someone.

Was this page helpful?
0 / 5 - 0 ratings