Chrome App という、Chrome Extension の延長上にあるスタンドアロンアプリを作れる仕組みがある。これは、しばしば出てくる HTML + JavaScript でスタンドアロンアプリを作れるやつの Chrome 版にあたる。

結構いろいろとAPIが整備されていて面白いんだけど、いまいちテストを書く方法がわからなくていろいろ試した。Chrome の API を使っている場合、どうしても Chrome のコンテキストで実行する必要があり、なかなか面倒くさい。

protractor (webdriver-js ラッパ) を使う

protractor は Angular.JS 用のエンドトゥーエンドテストフレームワークで、いろいろ環境を一発でつくるのが便利なので使ってる。Angular.JS も使ってるから丁度いい。

コマンドラインから Chrome App を起動すると、まず1つ普通のChromeのウィンドウが開き、次にアプリケーションのウィンドウが開くという挙動をする。なので、アプリケーションのウィンドウが起動するのを待って、そっちにスイッチする必要がある。

403 Forbidden このあたりに書いてあるのをなおして、以下のようなのを書いた。

function switchToAppWindow (nth) {
	function _switchToAppWindow (n) {
		if (n <= 0) throw "failed to switch to app window";

		browser.driver.getAllWindowHandles().then(function (handles) {
			if (handles.length <= nth) {
				_switchToAppWindow(n--);
			} else {
				browser.driver.switchTo().window(handles[nth]);
			}
		});
	}
	_switchToAppWindow(1000);
}

switchToAppWindow(1) で2番目に生成されたウィンドウにスイッチできる。

これで、Angular.JS レベルでの E2E テストは書けるようになる

Unit テストを書く

しかし、E2E テストだと Chrome 向けに Chrome 専用の API を使ったライブラリのテストが書きにくいので、普通の Unit Test みたいなのも書きたくなる。

いろいろ試したけど、結局以下のようにした。

  • テスト用の .html を用意する
  • E2E テスト用のスクリプトから、executeScript でテスト用の .html を開き、テストを実行する

Jasmine を読みこませてテストを実行させ、自力でテスト結果を取得して表示してる。

ただ、罠があって、Jasmine が eval を使っててそのままだと Content Security Policy にひっかかって実行できない。これはmanifest.json に sandbox 指定することでも解決するけど、これだと本来の目的の API がたぶん使えないので、jasmine を書きかえて治す必要がある。global オブジェクトを取得しようとして eval を使っているので (なんで?) そこだけ自分で変えたら動く (Edge バージョンだと eval するコードがないので普通に動きそう)。

スケルトンプロジェクト

をつくった

  1. トップ
  2. tech
  3. Chrome App をテストする