[Selenium] WebDriverでaddCookieするとき単位はミリ秒にしないといけない

# 躓きポイント

取ってきたCookieを削除してもう1回すぐセットするだけのコードを書いたつもりが、何故か2回目のセットで失敗してしまう。ところが`expiry`だけ無視すると正常にセットされた。Cookieオブジェクトでは秒単位なのに、addCookieの引数は**ミリ秒**単位になっているという意味不明な実装が原因だった。

#### Cookieをオブジェクトとして取得

```js
var cookie = await driver.manage().getCookie('PHPSESSID');
```

#### Cookieの削除

```js
await driver.manage().deleteCookie('PHPSESSID');
```

#### Cookieの再セット

```js:BAD
await driver.manage().addCookie(
    cookie.name,
    cookie.value,
    cookie.path,
    cookie.domain,
    cookie.secure,
    cookie.expiry
);
```

```js:GOOD
await driver.manage().addCookie(
    cookie.name,
    cookie.value,
    cookie.path,
    cookie.domain,
    cookie.secure,
    cookie.expiry * 1000
);
```

# 当該ソースを読んでみる

ググっても全然同様の質問が見当たらなかったので自分でソース読んで見るまで気づきませんでした。何でこうなってるんだろう…

```js
webdriver.WebDriver.Options.prototype.addCookie = function(
    name, value, opt_path, opt_domain, opt_isSecure, opt_expiry) {
  // We do not allow '=' or ';' in the name.
  if (/[;=]/.test(name)) {
    throw Error('Invalid cookie name "' + name + '"');
  }

  // We do not allow ';' in value.
  if (/;/.test(value)) {
    throw Error('Invalid cookie value "' + value + '"');
  }

  var cookieString = name + '=' + value +
      (opt_domain ? ';domain=' + opt_domain : '') +
      (opt_path ? ';path=' + opt_path : '') +
      (opt_isSecure ? ';secure' : '');

  var expiry;
  if (goog.isDef(opt_expiry)) {
    var expiryDate;
    if (goog.isNumber(opt_expiry)) {
      expiryDate = new Date(opt_expiry);
    } else {
      expiryDate = /** @type {!Date} */ (opt_expiry);
      opt_expiry = expiryDate.getTime();
    }
    cookieString += ';expires=' + expiryDate.toUTCString();
    // Convert from milliseconds to seconds.
    expiry = Math.floor(/** @type {number} */ (opt_expiry) / 1000);
  }

  return this.driver_.schedule(
      new webdriver.Command(webdriver.CommandName.ADD_COOKIE).
          setParameter('cookie', {
            'name': name,
            'value': value,
            'path': opt_path,
            'domain': opt_domain,
            'secure': !!opt_isSecure,
            'expiry': expiry
          }),
      'WebDriver.manage().addCookie(' + cookieString + ')');
};
```

Node.jsだけでなく、Java本家もそうなってました。うーん…

```java
public class AddCookie extends WebDriverHandler<Void> implements JsonParametersAware {

  private volatile Map<String, Object> rawCookie;

  public AddCookie(Session session) {
    super(session);
  }

  @Override
  public Void call() throws Exception {
    Cookie cookie = createCookie();

    getDriver().manage().addCookie(cookie);

    return null;
  }

  @SuppressWarnings({"unchecked"})
  public void setJsonParameters(Map<String, Object> allParameters) throws Exception {
    if (allParameters == null) {
      return;
    }
    rawCookie = Maps.newHashMap((Map<String, Object>) allParameters.get("cookie"));
  }

  protected Cookie createCookie() {
    if (rawCookie == null) {
      return null;
    }

    String name = (String) rawCookie.get("name");
    String value = (String) rawCookie.get("value");
    String path = (String) rawCookie.get("path");
    String domain = (String) rawCookie.get("domain");
    Boolean secure = (Boolean) rawCookie.get("secure");
    if (secure == null) {
        secure = false;
    }

    Number expiryNum = (Number) rawCookie.get("expiry");
    Date expiry = expiryNum == null ? null : new Date(
        TimeUnit.SECONDS.toMillis(expiryNum.longValue()));

    return new Cookie.Builder(name, value)
        .path(path)
        .domain(domain)
        .isSecure(secure)
        .expiresOn(expiry)
        .build();
  }

  @Override
  public String toString() {
    return "[add cookie: " + createCookie() + "]";
  }
}
```