简体   繁体   中英

Protractor - Chromium 89 - w3c compliance and browser.actions

I have a test which needs to click on a checkbox. If I simply do $('.my-cb').click() I get Element <input type="checkbox" > is not clickable at point (...). Other element would receive the click: <div>...</div> Element <input type="checkbox" > is not clickable at point (...). Other element would receive the click: <div>...</div>

That's why I do

browser.actions().mouseMove($('.my-cb')).click().perform()

Because of using browser.actions I needed to disable w3c compliance for chrome, as it's started failing back then with a version 75.X. At this time it has worked fine.

config.capabilities = {
  browserName: 'chrome',
  chromeOptions: {
    args: ['--disable-web-security', '--ignore-certificate-errors'],
    w3c: false,
  },
  ...
}

Now I've updated Chrome 75 -> 89. While this works on my local Windows environment, it fails on the linux CI with Failed: unknown command: Cannot call non W3C standard command while in W3C mode

So in fact what I need is to disable w3c compliance (as the above config stopped working) or to replace browser.actions() calls. I've been searching for other ways of disabling w3c compliance in Chrome 89, but found nothing useful. Only other people experiencing the same problem.

"@angular/core": "^10.2.4",
"protractor": "~7.0.0",

chromedriver_89.0.4389.23

---------- EDIT ----------

  1. It turned out that my selenium server was upgraded and now the proper way to pass the chrome config was to use 'goog:chromeOptions' insted of chromeOptions . This way I was able to disable w3c compliance again.
    'goog:chromeOptions': {
      args: ['--disable-web-security', '--ignore-certificate-errors'],
      w3c: false,
    },
  1. In the meantime, combining @Sergey Pleshakov answer with some other answers like https://stackoverflow.com/a/44595703/1913596 , I was able to achieve pretty good results switching from browser.actions usage to plain browser.executeScript usage. The jsClick proposed by @Sergey Pleshakov worked nice for the checkboxes, but for the dropdowns I needed to do much more. As my test is clicking through a big form, with multiple tabs, waiting for the options to roll down and roll up was necessary. In the end I've finished with such code:
export const jsClick = $element =>
  browser.executeScript('return arguments[0].click();', $element.getWebElement())

export const jsMove = async $element => {
  await browser.executeScript(
    `if(document.createEvent) {
      var evObj = document.createEvent('MouseEvents');
      evObj.initEvent('mouseover', true, false);
      arguments[0].dispatchEvent(evObj); 
    } else if (document.createEventObject) { 
      arguments[0].fireEvent('onmouseover'); 
    }`,
    $element.getWebElement()
  )
  return browser.sleep(1000)
}

export const scrollIntoView = function(el) {
  return browser.executeScript(function(el) {
    el.scrollIntoView()
  }, el.getWebElement())
}
await scrollIntoView(input)
await jsMove(input)
await browser.wait(until.elementToBeClickable(input), 5000, WAITING_TOO_LONG_FOR_ELEMENT)
await input.click()

const optionByCss = by.cssContainingText('mat-option .mat-option-text', value);
await browser.wait(until.visibilityOf(element(optionByCss)), 5000, WAITING_TOO_LONG_FOR_ELEMENT)
const option = await element(optionByCss)
await jsMove(option)
await option.click()
await browser.wait(until.invisibilityOf(element(optionByCss)), 5000, WAITING_TOO_LONG_FOR_ELEMENT)

However this is pretty sad to do such over complication while one could just use browser.actions().mouseMove($('.cls')).click().perform() in Chrome. I don't really understand why this API is not ported to other browsers.

Thanks a lot for the time spent.

Your problem is because on top of your element there is a wrapping element. It can even be invisible. But protractor can't click on it. What you can do is top declare js click (inject script in console). and then just click any element directly. This jsClick doesn't care about interactivity and visibility of the element you're clicking

    let jsClick = ($element) => browser.executeScript(
        "arguments[0].click();",
        $element.getWebElement()
    );

    let $option = $("option[value='395']");

    await jsClick($option);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM