fantoccini icon indicating copy to clipboard operation
fantoccini copied to clipboard

firstMatch vs alwaysMatch Capabilities

Open brianbruggeman opened this issue 3 years ago • 3 comments

Am I correct in assuming that fantoccini only supports sending alwaysMatch?

The ClientBuilder struct itself only provides a way to add "capabilities", which I would have expected follows the webdriver standard: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities

As noted on that page, the general structure looks like this for always match:

{
  "capabilities": {
    "alwaysMatch": {
      "browserName": "firefox",
      "browserVersion": "60"
    }
  }
}

And looks like this for first match:

{
  "capabilities": {
    "firstMatch": [
      {"platformName": "macos"},
      {"platformName": "linux"}
    ]
  }
}

And of course, the two can be combined:

{
  "capabilities": {
    "alwaysMatch": {
      "browserName": "firefox",
      "moz:firefoxOptions": {
        "profile": "<base64 encoded profile>",
        "args": ["-headless"],
        "prefs": {"dom.ipc.processCount": 8},
        "log":{"level": "trace"}
      }
    },
    "firstMatch": [
      {"platformName": "macos"},
      {"platformName": "linux"}
    ]
  }
}

But digging in the Session code and ClientBuilder code, it seems that fantoccini only provides a way of setting: capabilities -> alwaysMatch.

I was kind of hoping for something more like this:

...
let client = ClientBuilder::native()
    .with_always_match(always_match_capabilities)
    .with_first_match(first_match_capabilities)
    .connect(&url)
    .await?;
...

or alternatively:

let client = ClientBuilder::native()
    .with_capabilities(r#"""
    {
      "capabilities": {
        "alwaysMatch": {
          "browserName": "firefox",
          "moz:firefoxOptions": {
            "profile": "<base64 encoded profile>",
            "args": ["-headless"],
            "prefs": {"dom.ipc.processCount": 8},
            "log":{"level": "trace"}
          }
        },
        "firstMatch": [
          {"platformName": "macos"},
          {"platformName": "linux"}
        ]
      }
    }
    """)
    .connect(&url)
    .await?;

brianbruggeman avatar Mar 19 '21 20:03 brianbruggeman

Yes, you're right, currently you can only provide alwaysMatch. Part of the reason for that is that we have to match both the old Selenium-based "spec" and the official WebDriver spec, and they don't entirely agree on how these capabilities should work :sweat_smile: But I suspect it's probably doable to find a nice abstraction to cover both.

I'm not a huge fan of the version where you give the raw JSON, since it makes it harder for us to inject our own parameters, which is sometimes needed. We could parse it and then inject, but I don't know that that's really any nicer. A sort of builder API for capabilities might work really well though! Want to take a stab at implementing that?

jonhoo avatar Mar 21 '21 00:03 jonhoo

Thanks for getting back to me. I'm trying to automate a vaccine signup page, and I want it to run on Windows, Mac and Linux with various versions of Firefox (given multiple end-users).

I think the builder would be rather straight-forward to update and it could be updated in a way that it doesn't change compatibility with the current API. That said, it may be a bit before I have some time to work on this.

That said, when I was working with this over the weekend, I kind of wanted 100% control so I could sideline any extra pieces that fantoccini adds, which is why I mention that second interface. Some of that is because this is all new for me, and I don't know where the edges are. Some of it is so I can isolate my configuration and know that I didn't add it correctly. As an example, I couldn't seem to find a way to get the moz::firefoxOptions to work with headless and/or profile, even though Google seemed to think they should. I was left trying to answer the question: did I make a mistake or is this unsupported? I still don't really have an answer there.

brianbruggeman avatar Mar 22 '21 20:03 brianbruggeman

All good --- take your time!

In general, fantoccini doesn't really do anything special with the capabilities you pass in beyond passing them wrapped in whatever the appropriate context are for session creation (see the Selenium spec vs the WebDriver spec).

jonhoo avatar Mar 23 '21 02:03 jonhoo