LoginSignup
1
1

More than 3 years have passed since last update.

VueScrollToはdirectivesで渡す

Posted at

VueScrollTo を使っているコンポーネントのテストを書くときに躓いたので、その時の対応をまとめました。

その時の状況

Vueコンポーネントのテストを書きはじめたところでした。
とりあえず最低限のテストを書きます。
componentをmountして、htmlを出力してみます。

import { mount } from "@vue/test-utils";
import Complete from "@/views/Complete.vue";

const $store = {
  state: {
    answer: {
      type: "hoge",
    },
  },
};

describe("Complete.vue", () => {
  let wrapper;

  beforeEach(() => {
    wrapper = mount(Complete, {
      global: {
        mocks: {
          $store,
        },
      },
    });
  });
  it("ページが表示される", async () => {
    console.log(wrapper.html());
  });
});

このテストを実行したところ、失敗してしまいました。

FAIL  tests/unit/Complete/template.spec.js
  Complete.vue
    ✕ ページが表示される (49 ms)

  ● Complete.vue › ページが表示される

    TypeError: Cannot read property 'created' of undefined

      14 | 
      15 |   beforeEach(() => {
    > 16 |     wrapper = mount(Complete, {
         |               ^
      17 |       global: {
      18 |         mocks: {
      19 |           $store,

      at invokeDirectiveHook (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2922:33)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3814:17)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3793:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3713:21)
      at mountChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3888:13)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3811:17)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3793:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3713:21)
      at mountChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3888:13)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3811:17)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3793:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3713:21)
      at mountChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3888:13)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3811:17)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3793:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3713:21)
      at mountChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3888:13)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3811:17)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3793:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3713:21)
      at componentEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4204:21)
      at reactiveEffect (node_modules/@vue/reactivity/dist/reactivity.cjs.js:46:24)
      at Object.effect (node_modules/@vue/reactivity/dist/reactivity.cjs.js:21:9)
      at setupRenderEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4169:38)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4128:9)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4088:17)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3716:21)
      at componentEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4204:21)
      at reactiveEffect (node_modules/@vue/reactivity/dist/reactivity.cjs.js:46:24)
      at Object.effect (node_modules/@vue/reactivity/dist/reactivity.cjs.js:21:9)
      at setupRenderEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4169:38)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4128:9)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4088:17)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3716:21)
      at render (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4789:13)
      at mount (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3054:25)
      at Object.app.mount (node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.js:1232:23)
      at mount (node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:2335:18)
      at Object.<anonymous> (tests/unit/Complete/template.spec.js:16:15)

  ● Complete.vue › ページが表示される

    TypeError: Cannot read property 'html' of undefined

      23 |   });
      24 |   it("ページが表示される", async () => {
    > 25 |     console.log(wrapper.html());
         |                         ^
      26 |   });
      27 | });
      28 | 

      at Object.<anonymous> (tests/unit/Complete/template.spec.js:25:25)

  console.warn
    [Vue warn]: Failed to resolve directive: scroll-to 
      at <Complete ref="VTU_COMPONENT" > 
      at <VTUROOT>

      60 |             src="/uploads/images/thanks01.jpg"
      61 |           />
    > 62 |           <img
         |                                   ^
      63 |             src="/uploads/images/thanks02.jpg"
      64 |           />
      65 |           <img

      at warn (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:40:17)
      at resolveAsset (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5133:13)
      at Object.resolveDirective (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5104:12)
      at Proxy.render (src/views/Complete.vue:62:38)
      at renderComponentRoot (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:729:44)
      at componentEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4186:53)
      at reactiveEffect (node_modules/@vue/reactivity/dist/reactivity.cjs.js:46:24)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        3.4 s
Ran all test suites matching /\/Users\/okada\/src\/front\/tests\/unit\/Complete\/template.spec.js/i with tests matching "Complete\.vue".

しかし、エラーメッセージが謎です…

TypeError: Cannot read property 'created' of undefined

Complete.vueでは、created使ってないんだけどな :thinking:

やったこと

問題箇所の特定

エラーメッセージからは読み解けないため、Complete.vueの中身を変えて問題の箇所を特定しました。具体的には、Complete.vueの中から怪しそうなところを消して実行→通ったらその場所が問題なので、更に狭い範囲を消して実行、を繰り返し、以下の場所に問題があることがわかりました。

    <div class="present-area-btn">
      <ul>
        <li>
          <a href="#" v-scroll-to="'#present-area'">
            <img
              src="/uploads/images/button.png"
            />
          </a>
        </li>
        <li>
          <a href="#" v-scroll-to="'#other-area'">
            <img src="/uploads/images/other.png" />
          </a>
        </li>
      </ul>
    </div>

v-scroll-toとありますね。

v-scroll-toは、vue-scrolltoというパッケージのもののようです。
以下のページによると、いい感じにスクロールしてくれるパッケージだそうです。

src/main.jsを確認すると、確かに使っていました。

app
  .use(router)
  .use(store)
  .use(VueAxios, axios)
  .use(VueScrollTo, {
    offset: -100,
  })

そして、テスト失敗時のメッセージをもう一度よく見ると、warnも出ていました :sweat_drops:

    [Vue warn]: Failed to resolve directive: scroll-to 

scroll-toというdirectiveが解決できないと言っていました。

対応内容と結果

ということで、mount時にdirectiveを渡してみました。

directives: {
  scrollTo: VueScrollTo,
},

テスト全文

import { mount } from "@vue/test-utils";
import VueScrollTo from "vue-scrollto";
import Complete from "@/views/Complete.vue";

const $store = {
  state: {
    answer: {
      type: "hoge",
    },
  },
};

describe("Complete.vue", () => {
  let wrapper;

  beforeEach(() => {
    wrapper = mount(Complete, {
      global: {
        mocks: {
          $store,
        },
        directives: {
          scrollTo: VueScrollTo,
        },
      },
    });
  });
  it("ページが表示される", async () => {
    console.log(wrapper.html());
  });
});

結果:成功しました 🎉

 PASS  tests/unit/Complete/template.spec.js
  Complete.vue
    ✓ ページが表示される (68 ms)

  console.log
    <div class="host"><div class="comp-top-area"><img src="/uploads/images/thanks_mv.png"> …

      at Object.<anonymous> (tests/unit/Complete/template.spec.js:29:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.814 s
Ran all test suites matching /\/Users\/okada\/src\/front\/tests\/unit\/Complete\/template.spec.js/i with tests matching "Complete\.vue".

補足

github検索すると、Vue.use(VueScrollTo)でやってる人が多そうでした。Vue.useはVue2の書き方なので、それをVue3の書き方にすればよかっただけなのかもしれない…?(試してない)

import VueScrollTo from "vue-scrollto”;
import { createApp } from "vue”;
const app = createApp({});
app.use(VueScrollTo, {
  offset: -100,
});
1
1
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
1
1