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)
実践Node.jsプログラミングのマルチルームチャットアプリの構築を写経した時のメモ
世界にはまだまだ知らないことだらけ。Node.jsのサーバサイドについても把握せねば。
環境
- node v4.2.3
- mime 1.3.4 (本では1.2.7)
- socket.io 1.3.7 (本では0.9.6)
単純に動かなかった2点
1点目 chat_server.js l50~l60あたり
//var usersInRoom = io.sockets.clients(room);
// ↑だとclientsなんぞ知らん。というエラーが起きる
var usersInRoom = findClientsSocket(room);
// 以下のメソッドを別途追加
function findClientsSocket(roomId, namespace) {
var res = []
, ns = io.of(namespace ||"/"); // the default namespace is "/"
if (ns) {
for (var id in ns.connected) {
if(roomId) {
var index = ns.connected[id].rooms.indexOf(roomId) ;
if(index !== -1) {
res.push(ns.connected[id]);
}
} else {
res.push(ns.connected[id]);
}
}
}
return res;
}
2点目 chat_server.js l20~l30あたり
//socket.emit('rooms', io.sockets.manager.rooms);
// ↑だと「TypeError: Cannot read property 'rooms' of undefined」というエラーが起きる
socket.emit('rooms', io.sockets.rooms);
なぜ動かなかったか?
APIが変わったから。
どうやらsocket.ioの1.0になったときにいろいろ変わったらしいですね
ふぅ。
Server側復習
server.js => ほぼstaticなwebサーバに関する記述
chat_server => socket.ioに関するところだけ抜き出して意味を調べてみる
io = socketio.listen(server)
API docsより
Server#listen
Synonym of Server#attach.
Server#attach(srv:http#Server, opts:Object):Server
Attaches the Server to an engine.io instance on srv with the
supplied opts (optionally).
engine.ioとはなんぞや?
https://github.com/socketio/engine.io
socket.io用のトランスポート層で双方向通信するための実装ということか?
これをhttpサーバにアタッチすることでリクエストをインターセプトする
io.set('log level', 1);
意図がわからない。log levelを1にするということはログを多くすることなのか?少なくすることなのか?ログを無くしたいのか?
そしてversion1.0以降はなにやら変わっているらしい。このログレベルの設定自体が不要なのか?
http://socket.io/docs/logging-and-debugging/
↓で何やら説明があった。
http://socket.io/docs/migrating-from-0-9/
Options like log-level are gone.
ごーん
socket.emit('eventName', obj);
対象のsocketに対してイベントを発火させる。
渡したいものはobjに詰めておく
socket.join(room)
API docsより
Socket#join(name:String[, fn:Function]):Socket
Adds the socket to the room, and fires optionally a callback fn
with err signature (if any).
The socket is automatically a member of a room identified with its
session id (see Socket#id).
The mechanics of joining rooms are handled by the Adapter
that has been configured (see Server#adapter above), defaulting to
socket.io-adapter.
roomに追加してoptionのコールバックを発火。
roomとはなにものか?
デフォルトではセッションID名のroomに自動的に入れられているってことか
socket.leave
joinの反対で良い模様
socket.broadcast.to(room).emit('message', {...})
ブロードキャスト。
そして↓のように書いても動いた。
socket.to(room).emit('message', {...}
違いはなんだろう?
socket.on('イベント名', function(パラメータ){ハンドリング処理});
見ての通りのイベントハンドリング処理の模様
io.of(...)
カスタムのネームスペースを作れるらしい。
デフォルトは"/"
socket.id
API docsより
Socket#id:String
A unique identifier for the socket session, that comes from the
underlying Client.
はい。
Client側復習
io
おもむろに登場するグローバルオブジェクト。
socket.on('イベント名’, function(パラメータ){ハンドリング})
イベントのハンドリング
socket.emit('イベント名', パラメータ)
イベントの発火
クライアントはハンドリングと発火だけなのでシンプル
vuejsの作者さんが考えたvuejsにマッチするflux?
vuexを動かしてみる
動機:githubで見つけて単純にDLして動かそうとしたら動かなかったから
環境メモ
- babelは5系
- nodejsは4.2.2
- npmは3.5
- .vueファイルを使わない(ただの個人的な好み)
作業順
- ディレクトリを作る
- npm でいろいろインストール
- vuexをプロジェクトの中に
- exampleにあるcounterを移植して動かしてみる
- testを移植して動かしてみる
[ディレクトリを作る]
# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir -p build test src/{components,views,assets/{js,css}}
[npm でいろいろインストール]
# npm で必要なものをあつめてくる
npm init
npm i -g webpack webpack-dev-server mocha babel-loader@^5.3
npm i -S vue
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader html-loader mocha mocha-loader chai
[vuexをプロジェクトの中に]
今回は/src/assets/vuexというディレクトリを用意してその中にgithubから持ってきたvuexのsrc配下を入れる
[exampleにあるcounterを移植して動かしてみる]
build/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vuex counter example</title>
</head>
<body>
<counter></counter>
<script src="js/app.js"></script>
</body>
</html>
src/assets/js/main.js(vuexのexampleのままimportのパスを変えただけ)
import Vue from 'vue'
import Counter from '../../components/counter/index'
new Vue({
el: 'body',
components: { Counter }
})
src/assets/js/vuex.js(vuexのexampleのcounter内にあるvuex.jsをそのままもってきてimportのパスだけ変更)
import Vue from 'vue'
import Vuex from '../vuex'
~省略
src/components/counterにCounter.vueを分割して2ファイル
index.js
import vuex from '../../assets/js/vuex'
export default {
template: require('./template.html'),
computed: {
count () {
return vuex.state.count
}
},
methods: vuex.actions
}
template.html
<div>
Clicked: {{ count }} times
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">Increment if odd</button>
<button @click="incrementAsync">Increment async</button>
</div>
サーバを起動して確認
webpack-dev-server -d --inline
[testを移植して動かしてみる]
testディレクトリにあるtest.jsをそのまま移植してimportのパスだけ直す
mocha --compilers js:babel-core/register
通りました。これでいろいろ試せるかな
見ないふりをしてたけど、eslintを入れて動かすとなんか警告が出る。けどなんの警告だかはわかってない
findConfigFileの引数が変わってます。
完全に元のエントリーの内容残って無いけど、うそんこタイトル残しとくよりマシかな!という判断で書き直し
20151124版のtypescript1.8.0-dev.20151124のfindConfigFileメソッドは第2引数にfileのexistsを確認するための関数を渡さなければいけなくなった。
※具体的にいつのリリースでそういう仕様になったかはわからないけれど、つい最近なんだろうなーと想像
そのために、既存のfindConfigFileを利用していたライブラリはそれに対応しないとエラーが発生するようになっている。
2015年11月24日時点でespower-typescript-babelを利用しようとすると当該のエラーにぶつかった。
findConfigFileメソッドを利用している箇所をルートパス+"tsconfig.json"をセットするように変更してしまえば動いた。けど、ちゃんと対応するなら第2引数にisExistsをわたしてあげないとか?
そもそも1.6系使えば動きそうだからわざわざ1.8の安定してないやつ使う必要がなくなったのでは?
まだ書いてないけど
もやもやポイント書き出し
TypeScriptでVue.jsを使うサンプル(前半)
【計画】前半と後半に分ける
前半
プロジェクトの作成と簡単なアプリ作成
後半
vue-router組み込み
主要な使用技術
- TypeScript 1.6.2
- vue 1.0.8
- vue-router 0.7.5
- vue-class-component 2.0.0
- TypescriptのコンパイルオプションはES6
大まかな手順
- プロジェクト作成と環境の準備
- TypeScriptまわりの準備
- vueの簡単なサンプル作り
- vue-router挑戦
プロジェクト作成と環境の準備
# ディレクトリ作成
mkdir プロジェクトのフォルダ
cd プロジェクトのフォルダ
mkdir build
mkdir -p src/{components,views,assets,directives,filters}
mkdir src/assets/js
# npm で必要なものをあつめてくる
npm init
npm i -g webpack webpack-dev-server mocha typescript tsd tslint
npm i -S vue vue-class-component vue-router
npm i -D babel-loader@^5.3 webpack style-loader css-loader sass-loader ts-loader html-loader typescript tsd tslint-loader mocha mocha-loader chai
# tsd で必要なものを集めてくる
tsd init
tsd install vue --save
tsd install require --save
# tslint用の定義ファイルをテンプレートからコピってくる。しかしこれ厳しすぎてつらいので適宜ゆるく改修する必要あり
cp ./node_modules/tslint-loader/node_modules/tslint/docs/sample.tslint.json ./tslint.json
webpack.config.jsの作成
module.exports = {
entry: {
app: "./src/assets/js/entry.ts"
},
output: {
path: './build/js',
publicPath: '/js/',
filename: "[name].js"
},
resolve: {
alias: {
vue: "vue/dist/vue"
},
modulesDirectories: ['node_modules', 'src/', 'src/assets/js/', 'src/views/', 'src/components/'],
// require()するときに拡張子を省略可能にします
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
},
devServer: {
contentBase: "./build",
},
module: {
preloaders: [
{
test: /\.ts$/,
loader: "tslint"
}
],
loaders: [
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.html$/,
loader: "html"
},
{
test: /\.ts(x?)$/,
loader: 'babel-loader?sourceMaps=true!ts-loader'
}
]
}
};
tsconfig.jsonを作成する
{
"compilerOptions": {
"module": "commonjs",
"removeComments": true,
"noImplicitAny": false,
"target": "es6",
"sourceMap": true,
"experimentalDecorators": true,
"preserveConstEnums": true
},
"exclude": [
"node_modules",
"build"
]
}
src/assets/js/にentry.tsを作成
console.log("hello");
/build/index.htmlを作成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample</title>
</head>
<body>
<div id="app">this is app</div>
<script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>
ここで一旦、webpack-dev-serverを起動してプレビュー
起動コマンド : webpack-dev-server -d --inline
http://localhost:8080
コンソールにhelloと表示されたらここまでOK
横道:IntelliJ使ってる場合の設定
Preferences->Languages & Frameworks->JavaScript
- JavaScript language version を「ECMAScript 6」にする
Preferences->Languages & Frameworks->TypeScript
- Enable TypeScript Compilerをチェックする(重かったらチェック外してもいいかも)
- コマンドラインオプション
--noImplicitAny --target ES6 --experimentalDecorators
- generate sourceMapのチェックをはずす。
Preferences->Languages & Frameworks->TypeScript->Tslint
- プロジェクトのtslint.jsonを設定する
横道から復帰
TypeScriptまわりの準備
typingsの中にあるvue.d.tsの中でexport =
とある部分をexport default
と書き換える
※es6を使うときに怒られちゃうからこれでごまかす。。。
独自定義ファイルディレクトリを作る
mkdir -p custom-typings/vue-class-component
custom-typings/vue-class-component/vue-class-component.d.tsを作る(これでいいのか不明)
declare module "vue-class-component" {
let VueComponent:ClassDecorator;
export default VueComponent;
}
custom-typings/custom.d.tsを作る
/// <reference path="vue-class-component/vue-class-component.d.ts" />
vueの簡単なサンプル作り
src/assets/js/entry.tsを書き換え
/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
require("../sass/main.scss");
new Vue(require("../../views/app"));
src/assets/sass/main.scss作成(てきとー)
body {
margin: 0px;
padding: 0px;
}
.main-header {
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-bottom: 1px solid #CCCCCC;
text-align: center;
}
.main-footer {
position: fixed;
width: 100%;
margin: 0px;
padding: 3px;
background-color: #fafafa;
border-top: 1px solid #CCCCCC;
bottom: 0px;
}
src/views/app/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
import Vue from "vue";
import Header from "../../components/header/index";
const app = new Vue({
el: "#app",
template: require('./template.html'),
components: {
'app-header': Header
}
});
src/views/app/template.htmlを作成
<app-header></app-header>
src/components/header/index.tsを作成
/// <reference path="../../../typings/tsd.d.ts" />
/// <reference path="../../../custom-typings/custom.d.ts" />
import VueComponent from "vue-class-component";
@VueComponent
export default class Header {
public static template:string = require("./template.html");
public ready():void {
console.log("hogehoge");
}
}
src/component/header/template.html
<div class="main-header">
<h3>TypeScript & Vue.js sample</h3>
</div>
サーバを起動して動作確認する。ヘッダーが表示されていればここまでOK
横道2 ChromeのVue Devtoolsについて
能力の無さは積極的にツールでカバーしたい。ということで便利ツールのChromeのプラグイン「Vue Devtools」
webpackの起動オプションに--inlineを設定してあったり、babel-loaderかますときにsourceMapつけてるのはこのツールを使えるようにするためです。
このプラグインのおかげで表示されているコンポーネントの情報をブラウザで実行時に見ることができます。
chrome上でブレイクポイント置いてステップ実行できるようになるものも相当嬉しい(それはVue Devtoolsの機能じゃないけど)