こんにちは。
2020年と2021年は例年と違い新しい生活様式を求められたり、リモートワークが当たり前になりつつも、日々感染者数の増減に一喜一憂しながら仕事やプライベートを過ごしているかと思います。
最近の仕事の状況を振り返ってみると、○月は...○期は...と一定のリズムで繁閑期があったように思いますが、その傾向もこれまでの傾向を元に予測が難しくなり、急に繁忙期がきたかと思うと急に閑散期がきたりと緩急が激しい日々が続いています。
そんな短期的に来るチャンスを漏れなく掴むためにも、自動化や業務効率化などがより一層求められてきており、エンジニアの役割が重要になってきているように感じています。
そんな中、私もSeleniumを使いE2Eテスト自動化や業務効率化周りで社内の業務改善や効率化に奔走していますが、ある程度システムが増えてきた段階でクラウド化を検討している際にヘッドレス化の部分でぶち当たった問題について備忘メモとして残していきます。
起きたこと
任意のディレクトリにファイルをダウンロードできるようにdownload.default_directory
でパスを指定して通常のモードで実行すると問題なく動作するが、ヘッドレスモードで実行したところ指定した設定が効かずにデフォルトのダウンロードディディレクトリにダウンロードされた。
const driver = new Builder()
.forBrowser("chrome")
.setChromeOptions(
new Options()
.addArguments(
"--no-sandbox",
"--disable-gpu"
).setUserPreferences({
"download.default_directory": "./downloads/"
})
)
.build()
環境
下記の環境で実行しています。
macOS Catalina 10.15.x
typescript 4.0.x
ts-node 9.0.x
v14.15.x
chromedriver 87.2.x ※ブラウザバージョンと合わせている
selenium-webdriver 4.0.0-alpha.7
結論
ChromeのDevToolsCommandを使って設定を行う必要がある。
Seleniumの場合、Executorを使ってSelenium側でカスタムコマンドとして定義されているsendDevToolsCommand
を実行することでDevToolsCommandを実行することができる。
const driver = new Builder()
.forBrowser("chrome")
.build()
const session = await this.driver.getSession()
driver.getExecutor().execute(
new Command("sendDevToolsCommand").setParameters({
sessionId: session.getId(),
cmd: "Browser.setDownloadBehavior",
params: {
behavior: "allow",
downloadPath: path.join(process.cwd(), "downloads")
}
})
)
もう少し詳しく
Driverクラスにメソッド定義されている?
最初に色々と探していたときに公式ドキュメントによるとDriverクラスのメソッドにあるような書きっぷりだったけど、GitHubのソースコードを見に行った限りだとメソッドの定義がされていなさそうだった。
ただ、引数などはこちらと同じみたいなので部分的に参考にすると良さそう
https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Driver.html#sendDevToolsCommand
Page.setDownloadBehaviorは非推奨になっている
色々と調べている中でPage.setDownloadBehavior
を使っている記事が多く、私も同じように使ってやった!動いたーとテンション上がっていたんですがよくよく確認してみると、実験的かつ非推奨になっている...
Seleniumを裏で使っているようなフレームワークのPuppeteerのGitHub上のイシューにPage.setDownloadBehavior no longer works for me (07/21/2020).
と書いている人がいたので、つい最近非推奨になったみたいですね。
https://github.com/puppeteer/puppeteer/issues/1478
DevToolsのプロトコルが記載されているサイトは こちら
Browser.setDownloadBehaviorが代替みたいだけどこれも実験的な位置付け
上記のGitHub上に記載されている内容を見る限りですと、代替はBrowser.setDownloadBehavior
を使うみたいですね。
ただ、こちらも実験的な位置付けなのでいつ大幅な仕様変更があるか分からないので時々確認してく方が良さそうですね。
ビジネス利用する際は、慎重に検討した方が良さそうですね。