theintern / intern

A next-generation code testing stack for JavaScript.
https://theintern.io/
Other
4.36k stars 311 forks source link

`click` command fails with Edge Chromium through Selenium grid #1118

Open wkeese opened 4 years ago

wkeese commented 4 years ago

Expected behavior

click() should click a button.

Current behavior

It throws an exception:

InvalidArgument: [POST .../element/.../click] invalid argument: missing command parameters

Possible solution

Based on advice in nightwatchjs/nightwatch#2118, I managed to get a minimal test case to work by changing @theintern/leadfoot/Session.js to avoid passing an empty POST to the server:

    Session.prototype.serverPost = function (path, requestData, pathParts) {
        if (!requestData) {
            requestData = {};
        }
        return this._delegateToServer('post', path, requestData, pathParts);
    };

Steps to reproduce (for bugs)

We had a trivial test like below but I'm sure you can make your own:

registerSuite("test suite", {
    loginTest: function () {
              return this.remote
        .get(intern.config.appURL)
        .findAllByCssSelector(".usernameInput").type("user").end()
        .findAllByCssSelector(".passwordInput").type("password").end()
        .findByCssSelector(".submit input").click().end();
    }
});

Environment

Intern version: 4.8.0 Node version: 10.15.3 NPM version: 6.13.7 Browser version: Edge Chromium 80

jason0x43 commented 4 years ago

What version of leadfoot are you using, and are you letting the feature tests run? With Intern 4.8.0, Leadfoot 2.3.2, Node 10.15.3, and Edge Chromium 80, clicking appears to be working properly.

My test case is:

describe('clicking', () => {
  it('should work without error', async ({ remote }) => {
    await remote.setFindTimeout(5000);
    await remote.get('/tests/functional/page.html');
    const button = await remote.findByCssSelector('#button');
    await button.click();
    // a .success element appears 1000ms after clicking the button
    await remote.findByCssSelector('.success');
  });
}
jason0x43 commented 4 years ago

It works back to leadfoot 2.3.0, which is the minimum for Intern 4.8.0, so that doesn't seem to be the issue.

jason0x43 commented 4 years ago

Skipping the feature tests also doesn't seem to be a problem.

wkeese commented 4 years ago

Weird about us getting different results.

I was using leadfoot 2.3.2 (just picked automatically for me). I was mostly testing with "fixSessionCapabilities" : false, but removing that just causes another error:

UnknownCommand: [POST http://.../moveto / {"element":"86bfe2fa-2e61-40ca-b0f5-ff0cf4d46f77","xoffset":100,"yoffset":50}] unknown command: Cannot call non W3C standard command while in W3C mode

Maybe more relevant is the version of Edge (80.0.361.50) and the msedgedriver.exe (80.0.3561.50), and that the OS was Windows 10, not OSX.

jason0x43 commented 4 years ago

I'll take a look at Windows 10.

Are you using the selenium tunnel, or talking directly to the WebDriver through a null tunnel?

wkeese commented 4 years ago

"tunnel": "null", which connects to selenium with -role hub, which then connects to selenium -role node, started as

java -Dwebdriver.edge.driver=C:\selenium\msedgedriver.exe -jar C:\selenium\selenium-server-standalone-3.14.0.jar -port 7778 -role node -hub http://...:5555/grid/register -browser "browserName=MicrosoftEdge, version=80.0.361.50, maxInstances=1, platform=WIN10, seleniumProtocol=WebDriver"
jason0x43 commented 4 years ago

It works on Windows 10 with Selenium 3.141.59, msedgedriver 80.0.361.62, and Edge 80.0.361.62 when using Intern's SeleniumTunnel. Possibly there's some issue with Selenium running in grid mode (I haven't tested that yet).

jason0x43 commented 4 years ago

I do get the InvalidArgument error when running over a grid.

jason0x43 commented 4 years ago

Clicking works with bare msedgedriver and a null tunnel, so I'm guessing that Selenium in grid mode is choking on a bodyless POST rather than msedgedriver. I haven't seen anything in the webdriver spec stating that POSTs require data (click, for example, doesn't appear to), but I could be missing something.

If sending an empty object for POSTs with no data fixes the issue with a Selenium grid and doesn't break anything else, we can implement that.

jason0x43 commented 4 years ago

Sending a {} when the requestData was empty gave me a slightly different error, but still an error:

InvalidArgument: [POST http://localhost:4444/wd/hub/session/7f2947b55b594f0b3f0e2b513ca3fb40/element/902432f4-fb73-41bc-8c81-32b42b236f53/click / "{}"] invalid argument: missing command parameters

vs

InvalidArgument: [POST http://localhost:4444/wd/hub/session/2fc7fecc0c4cc7458bb0a289bd99fa32/element/f59208c5-811d-498c-bcc9-9a9e15a4ae44/click] invalid argument: missing command parameters 
jason0x43 commented 4 years ago

Passing { id: <element.id> } as the request data for /element/<element.id>/click, as suggested in https://github.com/nightwatchjs/nightwatch/pull/2122, does appear to work.

Selenium does care about the id property (it's not just looking for some data), because passing a nonsense value for the id, like { id: "foo" } doesn't work; Selenium complains about the id being invalid.

wkeese commented 4 years ago

OK, cool.

I don't know why {} worked for me but not for you... maybe because I specified it as {} rather than a string "{}".

Also mysterious: since the problem is with selenium grid, why does it only manifest on Edge Chromium? Or maybe Microsoft Edge is a red herring as those nightwatch tickets are talking about plain chrome.

Anyway, glad you have a solution.

jason0x43 commented 4 years ago

maybe because I specified it as {} rather than a string "{}"

Good catch, maybe the id isn't necessary, even if it has to be valid if present.