8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-11-30

躓きポイント

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

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

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

Cookieの削除

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

Cookieの再セット

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

当該ソースを読んでみる

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

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本家もそうなってました。うーん…

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() + "]";
  }
}
8
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?