## 🚀 Feature Proposal

Add support for the WebAuthn Automation API, a standard WebDriver extension that allows developers to create virtual authenticators to test websites using WebAuthn.

https://w3c.github.io/webauthn/#sctn-automation

_note: the above link may not work until https://github.com/w3c/webauthn/pull/1340 is merged_

## Motivation

At the moment there is no practical way to write e2e tests for pages using WebAuthn. Since this is a standard WebDriver API, the cost of implementing a layer on java is low.

## Example

For a page like this

```html
<button id="signup">Sign up with webauthn</button>
<span id="result"></span>
```

```javascript
document.getElmentById("signup").addEventListener("click", () => {
  navigator.credentials.create({...}).then(credentials => {
    document.getElementById("result").innerText = "Success!";
  })
});
```

A test could be written like so:

```java
// HasVirtualAuthenticator is an interface that augments a RemoteWebDriver.
HasVirtualAuthenticator virtualAuthenticatorManager = ((HasVirtualAuthenticator) driver);
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions();
VirtualAuthenticator authenticator =
    virtualAuthenticatorManager.addVirtualAuthenticator(options);
driver.findElement(By.id("signup")).click();
WebElement result = driver.findElement(By.id("result"));
new WebDriverWait(driver, 60, 1000).until(
    driver -> !result.getText().equals(""));
assertThat(result.getText()).isEqualTo("Success!");
```

## Implementation

We can implement the AddVirtualAuthenticator and RemoveVirtualAuthenticator methods first since they're the most useful and follow up with the others in subsequent PRs.
defineCommand(GET_CURRENT_URL, get("/session/:sessionId/url"));
    defineCommand(GET, post("/session/:sessionId/url"));
    defineCommand(GO_BACK, post("/session/:sessionId/back"));
    defineCommand(GO_FORWARD, post("/session/:sessionId/forward"));
    defineCommand(REFRESH, post("/session/:sessionId/refresh"));
    defineCommand(SET_ALERT_CREDENTIALS, post("/session/:sessionId/alert/credentials"));
    defineCommand(UPLOAD_FILE, post("/session/:sessionId/file"));
    defineCommand(SCREENSHOT, get("/session/:sessionId/screenshot"));
    defineCommand(ELEMENT_SCREENSHOT, get("/session/:sessionId/element/:id/screenshot"));
    defineCommand(GET_TITLE, get("/session/:sessionId/title"));
    defineCommand(FIND_ELEMENT, post("/session/:sessionId/element"));
    defineCommand(FIND_ELEMENTS, post("/session/:sessionId/elements"));
    defineCommand(GET_ELEMENT_PROPERTY, get("/session/:sessionId/element/:id/property/:name"));
    defineCommand(CLICK_ELEMENT, post("/session/:sessionId/element/:id/click"));
    defineCommand(CLEAR_ELEMENT, post("/session/:sessionId/element/:id/clear"));
    defineCommand(
        GET_ELEMENT_VALUE_OF_CSS_PROPERTY,
        get("/session/:sessionId/element/:id/css/:propertyName"));
    defineCommand(FIND_CHILD_ELEMENT, post("/session/:sessionId/element/:id/element"));
    defineCommand(FIND_CHILD_ELEMENTS, post("/session/:sessionId/element/:id/elements"));
    defineCommand(IS_ELEMENT_ENABLED, get("/session/:sessionId/element/:id/enabled"));
    defineCommand(ELEMENT_EQUALS, get("/session/:sessionId/element/:id/equals/:other"));
    defineCommand(GET_ELEMENT_RECT, get("/session/:sessionId/element/:id/rect"));
    defineCommand(GET_ELEMENT_LOCATION, get("/session/:sessionId/element/:id/location"));
    defineCommand(GET_ELEMENT_TAG_NAME, get("/session/:sessionId/element/:id/name"));
    defineCommand(IS_ELEMENT_SELECTED, get("/session/:sessionId/element/:id/selected"));
    defineCommand(GET_ELEMENT_SIZE, get("/session/:sessionId/element/:id/size"));
    defineCommand(GET_ELEMENT_TEXT, get("/session/:sessionId/element/:id/text"));
    defineCommand(SEND_KEYS_TO_ELEMENT, post("/session/:sessionId/element/:id/value"));
    defineCommand(GET_ALL_COOKIES, get("/session/:sessionId/cookie"));