LoginSignup
3
8

More than 5 years have passed since last update.

vueの単一ページコンポーネントのテストをkarmaなしで行う

Last updated at Posted at 2017-06-10

現状

vueの単一ページコンポーネントのテスト行う場合、
公式ドキュメントの単体テストの項に従って行った場合は、karmaが必要になります。

問題

ただKarmaを利用した場合、そのための設定が必要になってちょっと面倒です。
その上、手間をかけて設定したとしてもViewのレンダリングを含めてのテストは後回しになるケースが多く(自分の場合)、レンダリングのテストは無駄になる場合も多いため、そこにコストをかけたくありません。またKarmaの起動するコストも気になります。

解決策

.vue ファイルをimportすることでモジュールのテストができれば良いのですが、そのままjavaファイルをimportした場合はparseできずにエラーになります。これをできるようにするのが今回のGoalです。

結論

package.jsonに以下を追加した上で

package.json
{
  "devDependencies": {
    "babel-core": "^6.24.0",
    "vue-template-compiler": "2.2.6",
  },
}

vue用のloaderを自作して、

test/loader.js
import fs from "fs";
import path from "path";

import { parseComponent } from "vue-template-compiler";
import { transform } from "babel-core";

require.extensions[".vue"] = (module, filename) => {
  const parsed = parseComponent(fs.readFileSync(filename, "UTF-8"));
  const content = transform(parsed.script.content, { extends: path.resolve(".babelrc") });
  module._compile(content.code, filename);
};

mocha.optsに埋め込みました。

--compilers js:babel-register,vue:babel-register
--require test/loader

こうすることで、importした場合に、vueの単一ファイルコンポーネントの<script> タグの部分のみを解釈したcomponentが生成されます。importされたファイルは<template>を持たないVueファイルになるので、avoriazを用いて、通常通りmountすることも可能です。

簡単な説明

require.extensions[".vue"] = (module, filename) => {

.vueの拡張子を持つファイルを読み込んだ場合の実行されるローダーを定義します。

const parsed = parseComponent(fs.readFileSync(filename, "UTF-8"));

vue-template-compilerparseComponentを使って、対象のvueファイルをparseします。

const content = transform(parsed.script.content, { extends: path.resolve(".babelrc") });

babel-coretransformを使って、es6のコードをバベります。その際に、.babelrcを設定することで、適時変換を行います。依存関係の解決もここで行われます。

module._compile(content.code, filename);

変換されたファイルをコンパイルして実際のコンポーネントに変換します。

実際のテスト

そのまま、mochaでテストできます

component.test.js
import Vue from "vue";
import ExampleView from "components/ExampleView.vue";
import { mount } from "avoriaz";

describe("components/ExampleView", () => {
  describe("computed", () => {
    describe("hello", () => {
      it("workが返される", () => {
        const wrapper = mount(ExampleView, {
          propsData: {
             // 必要があれば設定する
          },
        });
        const actual = "world";
        assert(actual === wrapper.vm.hello);
      });
    });
});

私は、今のところはこれで必要十分でした。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8