Nightmareさんとこをざっくり訳
英語わかんねっす。
Nightmare
Nightmareはハイレベルな自動ページ表示ライブラリーです。
達成したいことは、ネストが深く分かり難いコールバック地獄なしに下のことを実現する
- シンプルに書ける
- 同期処理っぽく書ける
これは、APIを持っていないサイトのE2Eテスト用に設計されています。
Electronベースでできてます。PhantomJSに似てますが、もっと早くてモダンです。
Daydream
Daydreamは@stevenmiller888さんによって作られた、Nightmareを使う際のお助けツール
chromeのエクステンションで、ブラウザ操作でNightmare用スクリプトを生成するものです。
Examples
yahooをサーチしてみよう
var Nightmare = require('nightmare');
var vo = require('vo');
vo(function* () {
var nightmare = Nightmare({ show: true });
var link = yield nightmare
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit')
.wait('.ac-21th')
.evaluate(function () {
return document.getElementsByClassName('ac-21th')[0].href;
});
yield nightmare.end();
return link;
})(function (err, result) {
if (err) return console.log(err);
console.log(result);
});
以下のコマンドで実行できます
npm install nightmare vo
node --harmony yahoo.js
もしくは mochaのテストを実行してみましょう:
var Nightmare = require('nightmare');
var expect = require('chai').expect; // jshint ignore:line
describe('test yahoo search results', function() {
it('should find the nightmare github link first', function*() {
var nightmare = Nightmare()
var link = yield nightmare
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit')
.wait('.ac-21th')
.evaluate(function () {
return document.getElementsByClassName('ac-21th')[0].href;
});
expect(link).to.equal('https://github.com/segmentio/nightmare');
});
});
全機能の例はこっち
https://github.com/segmentio/nightmare/blob/master/test/index.js
※この例はmocha-generatorsを使ってるから注意してね
動かすには
npm install
npm test
API
Nightmare(options)
Web参照できる新しいインスタンスを生成します。
指定できるオプションはこれ
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions
加えてnightmareのオプションとして
waitTimeout
.wait()
が指定の時間までにtrueを返さないとexceptionを投げます。
paths
Electronが使用するデフォルトシステムパス。
下のようにして上書き可能
var nightmare = Nightmare({
paths: {
userData: '/user/data'
}
});
switches
Chromeで使えるコマンドラインスイッチ
Electronでサポートしているのは下の通り
https://github.com/atom/electron/blob/master/docs/api/chrome-command-line-switches.md
electronPath
Electronのバイナリを指定。別バージョンのElectronでテストしたいときに使う。
.useragent(useragent)
Electronで使われるuseragentを指定する
.end()
キューを完了し、Electronのプロセスを切断、終了します。
ページ操作
.goto(url
指定したURLのページをロードします。
.back()
バックします。
.forward()
進みます
.refresh()
ページをリフレッシュします。
.click(selector)
指定したセレクタでクリックイベントを発生させます。
.mousedown(selector)
指定したセレクタでマウスダウンイベントを発生させます。
.type(selector[, text])
指定したセレクタに文字入力する。空文字やfalseを設定すると対象のセレクタの値がクリアされる
.check(selector)
.select(selector, option)
指定したdropdownセレクタのオプションを変える
.scrollTo(top, left)
スクロールする
.inject(type, file)
指定したフィアルをページにロードする。ロードできるのはjsかcss
.evaluate(fn[, arg1, arg2,...])
指定したfnを指定した引数で実行する。引数はオプショナル。実行終了後にfnの戻り値が戻り値となる。
情報を抜き取るときに便利
var selector = 'h1';
var text = yield nightmare
.evaluate(function (selector) {
// now we're executing inside the browser scope.
return document.querySelector(selector).innerText;
}, selector); // <-- that's how you pass parameters from Node scope to browser scope
.wait(ms)
指定したミリ秒待つ
.wait(selector)
指定したセレクタが存在するまで待つ(.wait('#pay-button'
)
.wait(fn[, arg1, arg2,...])
指定したfnがtrueを返すまで待つ
ページから情報を抜き取る
.exists(selector)
指定したselectorが存在するかどうか
.visible(selector)
指定したselectorが表示状態か非表示状態か
.on(event, callback)
ページのイベントを関ししてコールバックを呼ぶ。
.goto()
を呼ぶ前に読んでおかないといけない
サポートしているイベントはここ
http://electron.atom.io/docs/v0.30.0/api/browser-window/#class-webcontents
追加されているページイベント
.on('page', function(type="error", message, stack))
このイベントはページで何かしらjavascriptのエラーが起きたときに発火します。
しかし、挿入されたjavascriptコードでは発火しません。(例 .evaluate()
)そういうときはただの例外
ページのイベント
window.addEventListener('error')
, alert(...)
,prompt(...)
とかconfirm(...)
を監視します
.on('page', function(type="alert", message))
Nightmareではデフォルトでポップアップのwindow.alert
が無効です。
しかし監視できます。
.on('page', function(type="prompt", message, response))
Nightmareではデフォルトでポップアップのwindow.prompt
が無効です。
しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ
.on('page', function(type="confirm", message, response))
Nightmareではデフォルトでポップアップのwindow.prompt
が無効です。
しかし監視できます。
もし、異なるものをハンドリングしたい場合は独自のプリロードスクリプトを用意する必要があります。???なんのこっちゃ
.on('console', function(type [, arguments, ...]))
type
にはlog
,warn
もしくはerror
、そしてargumants
はコンソールから渡されてくるものです。
.on('console', function(type, errorMessage, errorStack))
このイベントはconsole.logがページ内で使われているときに発火します。しかし、injectされたscriptでは発火しません(例 console.log()の中で.evalute()
)
.screenshot([path][, clip])
現在ページのスクリーンショットを取ります。デバッグに便利。
出力はpngです。引数はどっちともオプショナルです。
pathが指定された場合、画像を指定のディレクトリに保存します。指定されてないと画像データのバッファを返します。
clipが指定された場合、下にもあるようにイメージが矩形にクリップされます。
https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback
.pdf(path, options)
指定されたパスにpdfファイルを保存します。細かいオプションについての情報は下
https://github.com/atom/electron/blob/v0.35.2/docs/api/web-contents.md#webcontentsprinttopdfoptions-callback
.title()
現在ページのタイトルを返却します。
.url()
現在ページのurlを返却します。
クッキー
.cookies.get(name)
指定した名前のクッキーを取得します。対象のurlは現在ページのurlです。
.cookies.get(query)
クエリを使って複数のクッキーを取得します。もしquery.name
が指定された場合、最初に見つかった値、もしくは配列を返します。
query.url
が指定されていない場合は現在urlになります
例)
// get all google cookies that are secure
// and have the path `/query`
var cookies = yield nightmare
.goto('http://google.com')
.cookies.get({
path: '/query',
secure: true
})
使えるプロパティは下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiesgetdetails-callback
.cookies.get()
現在ページのurlをすべて取得します。
.cookies.set(name, value)
現在ページのクッキーをセットします。
.cookies.set(cookie)
クッキーをセットします。もしcookie.urlが指定されてない場合、現在ページにセットします。
例)
yield nightmare
.goto('http://google.com')
.cookies.set({
name: 'token',
value: 'some token',
path: '/query',
secure: true
})
使えるプロパティ一覧は下
https://github.com/atom/electron/blob/master/docs/api/session.md#sescookiessetdetails-callback
.cookies.set(cookies)
一度に複数のcookieをセットします。cookies
はcookie
の配列です。
詳しくは.cookies.set(cookie)
で
Nightmareの拡張
Nightmare.action(name, action|namespace)
下の例のようにカスタムアクションをNightmareのプロトタイプに追加できます。
例)
Nightmare.action('size', function (done) {
this.evaluate_now(function() {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
return {
height: h,
width: w
}
}, done)
})
var size = yield Nightmare()
.goto('http://cnn.com')
.size()
注意:これはstatic classに追加してます。Nightmareのインスタンスに追加してるわけじゃないです。
evaluate_now
という処理を読んでいます。これはnightmare.evaluate
とは違います。
これは即時に実行されますが、nightmare.evaluate
はキューにたまります。
忘れないための簡単な方法は:evaluateについて疑問におもったとき、もしカスタムアクションを作ってるときならevaluate_nowを使ってください
なぜならすでにキューイングされたものを処理している最中に、その処理をまたキューにためてはいけないからです
またカスタムのネームスペースを作ることもできます。
nightmare.cookies.get
,nightmare.cookies.set
などで内部でも使っているように
アクションをまとめるのに便利です。しかしnightmareオブジェクトが乱雑になります。
例)
Nightmare.action('style', {
background: function (done) {
this.evaluate_now(function () {
return window.getComputedStyle(document.body, null).backgroundColor
}, done)
}
})
var background = yield Nightmare()
.goto('http://google.com')
.style.background()
.use(plugin)
nightmare.use
は一つのインスタンスでタスクを再利用するのに便利です。
nightmare-swiftlyでサンプルをチェックしてください
https://github.com/segmentio/nightmare-swiftly
Custom preload script
ウィンドウ環境起動時になにかしたいときは、プリロードスクリプトを定義できます。
どうやるかっていうと
var nightmare = Nightmare({
webPreferences: {
preload: custom-script.js
}
})
このプリロードするスクリプトは下の記述を入れておく
window.__nightmare = {};
__nightmare.ipc = require('ipc');
使い方
インストール
NightmareはNodeのmoduleなのでNode.jsは入れておく。
インストールはnpm install
で行う
$npm install --save nightmare
実行
Nightmareはnodeのスクリプトやmoduleから利用できる。
例)
var Nightmare = require('../nightmare');
var vo = require('vo');
vo(run)(function(err, result) {
if (err) throw err;
});
function *run() {
var nightmare = Nightmare();
var title = yield nightmare
.goto('http://cnn.com')
.evaluate(function() {
return document.title;
});
console.log(title);
yield nightmare.end();
}
これはcnn.jsとして保存したら下のように実行する
npm install vo nightmare
node --harmony cnn.js
デバッグ
内部で何が起きてるかをしるために3つの方法があります。
1. DEBUG=*
デバッグフラグ
1. Nightmareコンストラクタに{show:true}
を渡すと実際にウィンドウを表示する
1. specific eventsを監視する(下URL参照)
※https://github.com/segmentio/nightmare#onevent-callback
同じテストをデバッグモードで動かすときはDEBUG=nightmare node --harmony cnn.js
windowsなら(set DEBUG=nightmare & node cnn.js
)
そうすると追加情報が出力されます。
テスト
MochaとChaiを使ってテストします。どっちともnpmでインストールします。
nightmareのテストはmake test
で実行します
テストできたら下のように見えます。
make test
․․․․․․․․․․․․․․․․․․
18 passing (1m)