Showing a newline mark

viにはlistオプションというものがあり、それをオンにすると

  • 行の末尾に [cci]$[/cci] が表示されるようになる
  • タブ文字が [cci]^I[/cci] で代替表示されるようになる

となる。この内、行末尾の表示について実装したい。残念ながら、タブ文字の代替表示は難しい。

ここで行末尾を示すために文字 [cci]$[/cci] が用いられるというのは、vi が端末上のテキストエディタだからで、wasavi の場合はもうちょっと表現力があるので別の記号にしたい。

行末尾、つまり改行を示すための記号というとまあだいたいこんな感じだと思う。特に日本産のエディタでこれじゃない奴はないのではなかろうか。あと、MS Word。海外産だと行をパラグラフとみなして、Pilcrowが多いかもしれない。まあどちらでもいいけれど、とりあえず前者を使うことにしよう。

ところで、改行マークを表示することに意味があるとは特に思えない。それが役に立つのは、行末に余計な空白文字を残している、いわばダーティというか、非正規な状態の行を目視で確認したい場合くらいだろう。そういう行を正規化したいのなら目視確認なんてせずに正規表現による全置換すればいいだけの話で、改行マークを表示することに意味はない。また、正規化済みの行は空白ではないグリフの直後に改行があることが自明なわけで改行マークを表示する必要はなく、非正規な状態の行だけその旨を表示するようにすればいいのだが、非正規な行の場合でも本来強調表示すべきは行末の余計な空白文字であって、改行マークではない(vimの場合で言えばlistcharsに対してeolではなくtailだけ設定した状態)。従っていずれの場合でも改行マークを表示しなければならない積極的な理由はないように思える。

と、そう考えればそうなのだが、実は去年はあんまりwasaviの開発を進められなかったのでいまいち内部の構造を忘れかけているのであった。そのリハビリのためにあえて実装してみる。

ということでこうなった。

Old and New

調べものの途中でたまたま常用漢字の新字体と旧字体の なるものを見ていたのだが、この旧字体で文章を組むとどんな感じなのかしらん? とふと気になったので、ひとまず赤福プラスに組み込んでみた。


なかなか味わい深い。

当初は投稿時のコメントを旧字体に変換するようにしたのだが、「なんで旧字体なの」「うぜえ」などと、ID を出されて火炙りにされそうな勢いだったのでローカルでの表示のみを旧字体に変換するようにした。

この機能は開発バージョンでのみ有効で、オン・オフの設定もない。

The Space

qeema 内でデグレードしてた箇所があったのを修正。Chrome で、IME がオンの状態でスペースキーを押すと(設定によっては)いわゆる全角スペース(U+3000、IDEOGRAPHIC SPACE)が直接入力されるわけだが、それが wasavi に正しく伝達されなくなっていた。

この全角スペースの直接入力に対して Chrome が発生させるキーボードイベントは実におかしい。

  • まず keydown イベントが発生する。この時、keyCode は 229 で入力されつつある文字が全角スペースだという判断には使えない
  • 各種 Composition Events は一切発生しない
  • input イベントが発生する。このイベントは単に通知のためのもので、何が入力されたかという情報は与えてくれない

という感じに実におかしい。Firefox であれば正しく Composition Events が発生する。IME まわりは Firefox の方が Chrome よりずっと真っ当だ。

対応策として、input 内でなんとかするしかなく、実際そうしている。keydown でその時点での対象の要素の値を保存しておき、input で差分を取ってイベントを生成させる。デグレードしたのはその処理が正しく呼ばれていなかった。

Testing with selenium javascript binding #5

ところで Opera ではどうなのだろうか。Blink Opera でも operadriver というものを経由してテストすることになっている。これはつまりchromedriver のフォークだ。じゃあ、だいたい Chrome のように動くと考えていいのかな。

と思ってやってみたらまるでさっぱり動かない。Opera 自体は起動するものの、
exception: Error: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:46266
なる例外が発生してテストが始まらない。

Selenium のライブラリと *driver との接続は http による REST だ。つまり、operadriver 側でリモートコントロールのための接続の listen をしてくれないということなのか?

とそういうわけで現在のところの各ブラウザの selenium 対応は Chrome、Firefox、Opera の順で甲乙丙のようだ。

Testing with selenium javascript binding #4

そういうわけで Linux 上では WebExtensions 版の wasavi の、Selenium による、Firefox 上の機能テストを一通り通せるようになったのだが、結局これを Windows 上ではできていない。過去の記事で何度か書いているが Windows では既存のプロファイルでもって Firefox を起動させることができず、かつ新規プロファイルに WebExtensions ベースの拡張を登録させつつ Firefox を起動させることもできない。両方できないと身動きが取れない。

実を言うと Linux 上でもテストが問題なく滞りなくできてるわけではない。例えば:

  • なにかが leak してますよ〜的なログがいっぱい出る。
    (node) warning: possible EventEmitter memory leak detected. 11 listeners added.
    云々。このエラー自体は書いてあるとおりのそのままの意味なんだろうけど、Chrome でテストする際は出ないので Selenium 内の Firefox とのやり取りをするコードにおける問題だと思う
  • wasavi でテストする際は当然ながら様々なキーストロークを発生させる必要がある。で、[cci]selenium.Key.chord()[/cci] というものがあり、[cci]chord(Key.CONTROL, ‘c’)[/cci] などと呼ぶと ctrl+C を押されたとブラウザに振る舞わせるような擬似的なキーストロークを生成する。Key[なんとか] は、型自体は普通の string で、Unicode の Private Use Area 内の文字である。chord 自体は単に引数を全部 join(”) したものに Key.NULL をくっつけたものを返す。したがって擬似的なキーストロークもまた単純な文字列である。さてそういうルールのもとに構成された chord を送出したあと、geckodriver かあるいは Firefox 本体が例えば前述の例だとそれを ctrl+C としてデコードしてくれないと困るわけなのだが。困ったことに、誰もデコードしてくれない。そのまんま PUA が入力され、テストは失敗する。ひどい
  • テスト中 Web Content なるプロセスが生成されて、これが60〜80%の CPU パワーを消費する。同時に Firefox 自体のプロセスが残りの CPU パワーを消費する。そんなわけでテスト中は待ってる以外にほとんど何もできないし、そもそも端末以外のアプリケーションを全て落とした状態じゃないとテスト自体がうまく始まらない。Chrome を起動しながらとか成功した試しがないのである。そして CPU パワーはめちゃくちゃ食いまくる割にテストの進行は Chrome でのそれより 2 割増しくらいで遅い

前述のプロファイル関連の不具合と合わせて、どーにもこーにも…… Firefox が絡む Selenium のテスト環境はいつも質が悪い、質が低いと言わざるを得ない。どうなってんのかなあこれ……。この辺が快適になってくれないと、Firefox 向けの拡張を作るという事自体にくじけてしまいそうなのだけど。

Testing with selenium javascript binding #3

テストを開始しても、Chrome は起動するもののテストページへのナビゲーションが発生せず、そのままタイムアウトで失敗してしまうことがたまにある。これの原因がよくわからない。とりあえずエラーメッセージとしては “unable to discover open pages” というものが返される。

原因はよくわからない。テスト用とは別の常用の Chrome を起動している状態でテストを開始すると、そういう状況が発生することがあるが、しないこともある。常用の Chrome を落とした状態でも発生することがある。また youtube とかの動画を再生中だと発生する確率が上がるような気がしないでもない。要するに chromedriver が Chrome を起動するものの、複数ある Chrome のうち自分が起動させたものを見失うことがある、というような感じなのだが……そんなわけあるかいな。

上記のエラーメッセージでググっても特にこれだというものもない。謎。

ちなみに Linux 版の Chrome で UI のロケールを任意のものにするには、[cci]LANGUAGE=en google-chrome[/cci] などとする。LANG でも LC_ALL でもなく、LANGUAGE。また、[cci]–lang[/cci] スイッチは効かない。

 * * *

というわけで、とりあえずすべての機能テストを java から javascript へ移植した。疲れた。次にこれを Windows 上の Firefox にて通してテストする。とその前に、Linux 上でも動かしてみよう。

ナウい Firefox で Selenium のテストをするには、geckodriver が必要なので、これをパスの通ったところに置いておく。


var options = new firefox.Options();
options.setProfile(profilePath);
result = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.firefox())
.setFirefoxOptions(options)
.build()

こんな感じで起動。これは既存のプロファイルを利用するような動作を意図しているが、どうも既存のプロファイルを /tmp あたりにまるごとコピーしてから起動するような感じがする。そのため実際に Firefox のウィンドウが表示されるまでは結構待たされる。

それから、webdriver.actions().sendKeys().perform() が未実装なのだそうでエラーになる。その代わり WebElement#sendKeys() を使う。geckodriver 自体が新しいプロジェクトなので、すべての想定された機能が実装されるまでにはもうちょっとかかる雰囲気。

 * * *

結局のところ wasavi でテストするには

  1. [cci]npm install -g selenium-webdriver[/cci]
  2. [cci]npm install -g chromedriver geckodriver operadriver[/cci]
  3. [cci]npm install -g mocha[/cci]
  4. [cci]npm install[/cci]

と入れて、[cci]make run-chrome[/cci] としてとりあえずテスト用プロファイルでもって起動し、開発者モードで wasavi を組み込み、ついでに dropbox などに wasavi からアクセスして認証を得ておき、ブラウザを閉じてから [cci]make test-chrome[/cci] とする……という感じ。ただし Firefox に関しては、過去の記事の通りオンザフライで WebExtensions ベースの拡張を登録するのが現在のところできないので、wasavi をビルドした上で xpi を登録したプロファイルを用意する必要がある。

Testing with selenium javascript binding #2

mocha のテストをすべて終えると最後に結果が表示される。こんなふうに:

basic test -- 2 tests, 50.00%
--------------------

1 passing (2s)
1 failing

1) basic test should get the title of test frame page:

AssertionError: 'wasavi test frame' == 'wasavi test frame?'
+ expected - actual

-wasavi test frame
+wasavi test frame?

at Object.eq (src/wd-tests/src/all-tests.js:359:10)
at Context. (src/wd-tests/src/basic-test.js:11:10)
at Generator.next ()
at pump (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:3221:25)
at callNext (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:3207:7)
at ManagedPromise.invokeCallback_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:1366:14)
at TaskQueue.execute_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2970:14)
at TaskQueue.executeNext_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2953:27)
at asyncRun (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2813:27)
at /home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:676:7
at process._tickCallback (internal/process/next_tick.js:103:7)
From: Task: basic test should get the title of test frame page
at Context.ret (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/testing/index.js:185:10)
at /home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/testing/index.js:104:5
at ManagedPromise.invokeCallback_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:1366:14)
at TaskQueue.execute_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2970:14)
at TaskQueue.executeNext_ (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2953:27)
at asyncRun (/home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:2813:27)
at /home/akahuku/.nvm/versions/node/v7.2.1/lib/node_modules/selenium-webdriver/lib/promise.js:676:7
at process._tickCallback (internal/process/next_tick.js:103:7)

見てのとおり殆どがスタックトレースの情報なのだ。こんなのいらないよ…。いや役に立つときはあるにはあるだろうけど、少なくとも mocha や selenium 内部のスタックトレースは普通はいらない。

そんなわけで、アサートを単に assert.equal() を呼ぶのではなく、

try {
assert.equal(actual, expected);
}
catch (ex) {
ex.stack = ex.stack.replace(/* cute regexp */, '');
throw ex;
}

なんてコードが考えられる。これはこれですごく嫌らしいコードなのだが(stack プロパティが書き換えられていいの?)、これでやってみてもスタックトレースは空にならない。上記の [cci]From: Task:[/cci] で始まる行以降の部分は、すでに selenium が stack に追記済みなのである。なので、stack を操作して再度 throw してもそれを selenium がまたいじるので、スタックトレースは空にならない。selenium にそのへんを何とかするオプションがあるのかはまだ調べてない。

ということで、とりあえずのワークアラウンドは
mocha --timeout=60000 --reporter=almost-min src/wd-tests/src/all-tests.js | sed -e '/^\\s*at\\s*/d' -e '/^\\s*From:\\s*Task:/d'
てな感じに、すべてのテストが完了した後に sed で削ぎ落とすことくらいしか思いつかない。これだと、mocha ならではの色とりどりのテスト結果ではなくなってしまうが、まあ個人的にはあれはちょっと華美すぎだと思うので、これはこれでいいかな…。

Testing with selenium javascript binding

wasaviの機能テストは今javaで書いているのだがjavaでなければならない理由は別にない。なぜjavaを選択したのかといえば、かつてはwasaviのビルドにantを使っていたのでそのへんの相性だとか、Seleniumのコード例として割とjavaが多く検索に引っかかるとか、公式のAPIリファレンスがjavadocだったからとか、その程度の理由だ。

しかし機能テストの個数が増えてくるとjavaだと困ったことにコンパイルにもそれなりに時間がかかってくるわけでなかなかストレスフルだ。それ以前にテストが全体的に遅い。ブラウザを起動する速度すら遅い。これを期に、スクリプト言語に移行したい。wasavi場合それ自体をJavascriptで書いているのだから、Javascriptに移行するのが自然だ。なによりJavascriptへのバインディングはSeleniumが公式でメンテしているのであんしんあんぜんということだ。ちなみに実はビルドの際に呼び出されるちまちましたスクリプト群も以前はRubyで書いていたのだが全部Javascriptに書きなおした。

ということでJavascriptによるテストコードの基盤を書いているのだが。基盤とはなんのこっちゃというと、各々の記述されたテストはページ上のtextarea、あるいは時にはdiv要素に対してwasaviが起動していることを前提としている。なのでテストの前段階でCtrl+Enterを送出してwasaviを起動させ、実際に起動したことを確認するコード、後段階でwasaviを終了させるコードを挟む必要があるのだ。そういったことをするために、基本的には


@test
public void testFoo () {
startWasavi();
// test body
;
closeWasavi();
}

なんてふうにテスト自体の先頭の末尾に何がしかの処理を挟むことになる。しかしこれはめんどくさいわけで、もうちょっと賢く特定の処理を割りこませたい。

となると次の案としては当然setUp()とtearDown()を定義してそこでwasaviを開いたり閉じたりすればよいのである。ここまでは実に普通だ。めんどくさいのはここからだ。

テストの中には、textarea要素ではなくcontenteditableなdiv要素とか、あるいはセクション・パラグラフ・センテンスをテストするために予めそのための初期本文が必要であるとか、初期化のタイプにもいくつかのバリエーションがある。そのへんもテスト本体に手を入れることなく1箇所で面倒を見たい。たとえばセクションに対するテストであればtestSectionなんとか、ってメソッド名なので、それを利用すればいい。あるいはアノテーションでもまあいい。しかし…困ったことにsetUp()にはそういったテスト自体のメタ情報は渡されないのであった。そのかわり、JUnitの場合TestWatcherというクラスがあってテストスイートの進行具合を観測することができるので、これを使う。

さて、これがJUnitからmochaへ移行するとどうなるか。setUp()とtearDown()は、beforeEach()とafterEach()という同機能が用意されているので単にそれを使えばいい。しかしやはり困ったことにこれらのメソッドにもテスト自体のメタ情報は渡されないのであった。というわけでTestWatcherの代替品を探さないといけないのだが、ない。

無理やり代替品を2つ考えてみると、まずReporterというものがありこれがテスト結果を表示する。これが内包するリスナはテストランナーから送出される各種イベントを受信して、その中にはテストのメタ情報が含まれる。なのでそれを使ってテストスイートへリダイレクトする。これのconsは好きなReporterを使えなくなるという点。

もうひとつは、テストの定義にit()を使うのでそれをラップして、

var testNames = [];
var originalIt = it;
it = function (should, fn) {
testName.push(should);
return originalIt.apply(undefined, arguments);
};

あとは beforeEach()内で[cci]testNames[/cci]から順々に表明を取り出せばそれは個々のテストを区別できる。これのconsは、必ずしもテストがit()の呼び出し順で実行されるとは限らないという点。

というわけでどちらもイマイチな点がある。うーむ。

 * * *

もうひとつ。JavascriptのSeleniumバインディングは、ほぼすべてのAPIがPromiseを返す仕様なのだ。だから、Javaであれば同期的に

WebElement el = driver.findElement(By.id("foobar"));
el.click();

などと何も考えずに書いていたコードは

driver
.findElement(By.id('foobar'))
.then(el => {el.click()});

というような感じになる。やることがシーケンシャルなのであれば.then()の羅列でいいのだがしかし分岐やループが入ってくるととたんに面倒くさくなってくる。それで、WebDriver.promise オブジェクトが用意されていてこれがジェネレータを引数に取り、ジェネレータがyieldしなくなるまで呼び出し続け、最後にresolve()するというナイスな関数consume()を持っているので

WebDriver.promise.consume(function*() {
var el = yield driver.findElement(By.id('foobar'));
yield el.click();
});

てな具合に同期的っぽく書ける。というかこれを使わないととてもじゃないけど書いてられない。気をつけないといけないことが一つあり、WebDriver.promiseはdeprecateである。なので将来的にはこれはasync/await版にしないといけない。

Add-on SDK to WebExtensions #5

ところが結局、Windows 上の Firefox で Selenium によるテストを行うところまで至っていない。現状では

  • Windows 上で
  • 任意の拡張を一時的に読み込ませつつ
  • そのプロファイルを使うよう Selenium に指示する

という術がないように思える。となるとテストのために一旦 xpi をビルドして、署名して、それを使うしかない。

ちなみに Selenium は現在 version 3 になっていて、Firefox に関しては Chrome の chromedriver.exe と同様 geckodriver.exe を介在させるようになっている。そのためにシステムプロパティ webdriver.gecko.driver に geckodriver.exe へのフルパスを書いておく必要がある。

ということで試してみたところ

File p = new File("C:\\path\\to\\profile");
WebDriver driver = new FirefoxDriver(p);

の呼び出し中に

Java heap space
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at org.openqa.selenium.remote.ProtocolHandshake.amendOssParamters(ProtocolHandshake.java:183)
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:61)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:141)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:82)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:601)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:241)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:128)
at org.openqa.selenium.firefox.FirefoxDriver.(FirefoxDriver.java:259)
at org.openqa.selenium.firefox.FirefoxDriver.(FirefoxDriver.java:247)
at org.openqa.selenium.firefox.FirefoxDriver.(FirefoxDriver.java:242)
at org.openqa.selenium.firefox.FirefoxDriver.(FirefoxDriver.java:238)
at org.openqa.selenium.firefox.FirefoxDriver.(FirefoxDriver.java:131)
at WasaviTest.WasaviTest.createDriver(Unknown Source)
at WasaviTest.WasaviTest.beforeClass(Unknown Source)

……どうしろというのか。

 * * *

FirefoxDriver のコンストラクタに独自のプロファイルを与えるのではなくデフォルトのそれを使用するようにすると(要するに何も引数を与えないと)起動した。なにそれ。テストのためのツールである Selenium ががろくにテストされてない…。真面目にやってくださいよ本当に。

 * * *


FirefoxProfile p = new FirefoxProfile();
p.addExtension("/path/to/wasavi.xpi");
driver = new FirefoxDriver(p);

とやるととりあえず OutOfMemoryError で落ちることはないのだが、拡張を登録する処理で「アーカイブの中に install.rdf がないよ〜」的なエラーになる。この場合の wasavi.xpi は WebExtensions ベースの拡張なので install.rdf ではなく manifest.json を見に行ってくれないといけないのだが、Selenium 側がまだ WebExtensions ベースの拡張を知らない状態なのだろう。

うーん! だめじゃん。WebExtensions の拡張を Selenium でテストするのは時期尚早なのか。

Add-on SDK to WebExtensions #4

というわけで、Firefox 版の wasavi も WebExtensions の基盤のもとで動かしてみて、とりあえず起動することは確認したのだが。すべての機能が正しく動作するかどうかは、機能テストを通して動かさないと保証できない。

従来この機能テストというのは Windows7 マシンで行っていた。しかし過去の記事のとおり、このマシンには Windows10 を新規インストールしたので過去の環境はさっぱり残っていないのであった。なので、新しく構築しないといけない。

wasavi の機能テストは Selenium を使っていたのだが、この環境を新たに構築するのはものすごく面倒くさい。Java SDK を入れて、Ant を入れて、Selenium の java バインディングを入れて、JUnit を入れて、OperaDriver を入れて、ChromeDriver を入れて、適当な www サーバを入れて、make を入れて、ソースを rsync して……という具合だ。ものすごく面倒くさい。ものすごく面倒くさい。インストールした後も更に面倒くさい。Selenium や ChromeDriver は割とちょくちょくアップデートされていて、しかも最新の組み合わせじゃないと動かなかったりするからだ。アップデート作業に煩わされたくないし、そもそももはや Windows マシンは開発には使ってなくて、時々地デジのテレビを見るためのものでしかない。余計なものを入れて不安定にさせたくない。

とはいえ機能テストはせざるを得ない。なんとかせめてインストールとアップデート作業だけでも楽に出来ないだろうか……。ということで調べてみたら、なんと Windows10 では OneGet、あるいは PackageManagement という標準のパッケージシステムが用意されているという。それが従来からある、chocolatey などの MS 公式ではないパッケージシステムを取り込む仕組みになっているという。ほー、これはなかなか野心的でいいんじゃないの。

というわけで試してみた。ちなみにこの文書がよくまとまっていてわかりやすい。…のだが。しかし使ってみてまだなんとも洗練されてないなという感じがした。件の文書のとおり動作が不確実なところがあったり機能が足りなかったりする。それからたとえば JDK であれば 32bit、64bit のどれを入れるかみたいな細かい指定がどうすればいいのかわかんない。chocolatey であればそういうスイッチが用意されているが PackageManagement でそれが有効なのかよくわからなかった。あと基本的に PowerShell で作業するのだが、PowerShell いいと思うけどおっそいんだよね……。

そんなわけで chocolatey を直接使うことにした。これの管理のもとで入れるのは:

  • jdk8
  • ant
  • selenium-all-drivers
  • node.js
  • googlechrome
  • opera
  • firefox

など。不思議なことに、Selenium の公式のクライアントライブラリの 1 つである java バインディングは chocolatey に登録されていない。それからこの辺はよく知らないのだけど java で JSON は標準では使えないようなので、適当にググッて json-20140107.jar なるものを調達してこないといけない……等々、いくつかのものは個別に入れる必要がある。うーん java バインディングも chocolatey の管理下になんとかならないものかな。

あとは Cygwin 側で

  • make
  • wget

が必要。

それから npm で

  • web-ext

を入れる。

いやはや大変だ。