前提
- Vue.js 2.1.1
- karma + mocha + chai
経緯
- Vm のデータを更新後、画面上の表示文字列が変わることを確認する Unittest を書いた
- 当初 browser に PhantomJS を指定していたが、Chrom に変更した
- assert がうまく出ない!!
原因
- Vue.nextTick() が ブラウザの Promise サポート有無によってい使い方が変わる
- ブラウザが Promiseをサポートしない nextTick() のコールバックを指定する (PhantomJS)
   it('画面が更新される', function(done) {
      cmp.upate_value = 'test';
      Vue.nextTick(function() {
          expect(cmp.$el.textContent).to.equal('test');
          done();
      });
   });
- プラウザが Promiseをサポート する nextTick() は コールバックをサポートせず、Promise を返す (Chrome など)
   it('画面が更新される', function(done) {
      cmp.upate_value = 'test';
      Vue.nextTick()
      .then(function() {
          expect(cmp.$el.textContent).to.equal('test');
      })
      .then(done)
      .catch(done);
   });
解決案
- Waitしてくれる関数を定義する
/**
 * 更新待ち
 * @param {function} callback
 * @param {function} done
 */
function waitForUpdate(callback, done) {
    /** Promise がサポートされている場合、Promise が返される **/
    if(typeof Promise !== 'undefined' && isNative(Promise)) {
        Vue.nextTick().then(callback).then(done).catch(done);
    }
    /** Promise がサポートされていない場合、Callbackを指定する **/
    else {
        Vue.nextTick(function () {
            callback();
            done();
        });
    }
}
function  isNative(Ctor) {
    return /native code/.test(Ctor.toString());
}
テストはこんな感じ
   it('画面が更新される', function(done) {
      cmp.upate_value = 'test';
      waitForUpdate(function() {
          expect(cmp.$el.textContent).to.equal('test');
      },done);
   });