Vue.js-Vuetify-很难测试菜单组件

时间:2018-08-28 12:38:38

标签: unit-testing vue.js vuetify.js

鉴于以下工具栏组件,我试图测试在单击菜单项时更改的语言环境...,但是在菜单选择器上发生鼠标悬停事件后,包装内容没有更改...

Toolbar.vue

    <template>
      <v-toolbar height="80px" fixed>
        <v-toolbar-title>
          <img src="@/assets/images/app_logo.png" alt="">
          <v-menu bottom offset-y open-on-hover class="btn btn--flat" style="margin-bottom: 12px;">
            <v-btn id="current-flag" flat slot="activator">
              <img :src="flagImage(currentLocaleIndex)" width="24px">
            </v-btn>
            <v-list>
              <v-list-tile v-for="(locale, index) in locales" :key="index" @click="switchLocale(index)">
                <div class="list__tile__avatar avatar--tile" @click="switchLocale(index)">
                  <img :src="flagImage(index)" width="24px">
                </div>
                <div class="list__tile__title" v-html="flagTitle(index)"></div>
              </v-list-tile>
            </v-list>
          </v-menu>
        </v-toolbar-title>
        <v-spacer></v-spacer>
        <v-toolbar-items>
          <!-- MENU HOME-->
          <v-btn flat @click="$router.push(menuItems.home.link)">
            <v-icon left>{{ menuItems.home.icon }}</v-icon>
          <span>{{ menuItems.home.title | translate }}</span>
          </v-btn>
          <!-- ABOUT HOME-->
          <v-btn flat @click="$router.push(menuItems.about.link)">
            <v-icon left>{{ menuItems.about.icon }}</v-icon>
          <span>{{ menuItems.about.title | translate }}</span>
          </v-btn>
        </v-toolbar-items>
      </v-toolbar>
    </template>

    <script>
    // import i18n from '@/locales'
    export default {
      name: "Toolbar",
      props: ["appName"],
      data() {
        return {
          menuItems: {
            home: { icon: "home", title: "Home", link: "/" },
            about: { icon: "info", title: "About", link: "/about" }
          },
          locales: [
            { id: "en", title: "English", flag: "@/assets/images/flag_en_24.png" },
            { id: "fr", title: "Français", flag: "@/assets/images/flag_fr_24.png" },
            { id: "br", title: "Português", flag: "@/assets/images/flag_br_24.png" }
          ]
        };
      },
      computed: {
        currentLocaleIndex: function() {
          let index = this.locales.findIndex(o => o.id === this.$i18n.locale);
          return index;
        },
        currentLocaleTitle: function() {
          let obj = this.locales.find(o => o.id === this.$i18n.locale);
          return obj.title;
        },
        currentLocaleFlag: function() {
          let obj = this.locales.find(o => o.id === this.$i18n.locale);
          return obj.flag;
        }
      },
      methods: {
        flagImage: function(index) {
          return require("@/assets/images/flag_" +
            this.locales[index].id +
            "_24.png");
        },
        flagTitle: function(index) {
          return this.locales[index].title;
        },
        switchLocale: function(index) {
          this.$i18n.locale = this.locales[index].id;
        }
      },
      mounted() {}
    };
    </script>

Toobar.spec.je

    import Vue from "vue";
    import router from "@/router";
    import Vuetify from "vuetify";
    import i18n from "@/locales";
    import { mount, shallowMount } from "@vue/test-utils";
    import Toolbar from "@/components/shared/Toolbar.vue";

    describe("App.vue", () => {
      let wrapper;
      beforeEach(() => {
        Vue.use(Vuetify);
        Vue.filter("translate", function(value) {
          if (!value) return "";
          value = "lang.views.global." + value.toString();
          return i18n.t(value);
        });
        const el = document.createElement('div');
        el.setAttribute('data-app', true);
        document.body.appendChild(el);
      });

      it("should change locale", () => {
        // given
        wrapper = mount(Toolbar, { router, i18n });
        console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
        // console.log(wrapper.html());
        const currentFlagBtn = wrapper.find("#current-flag");
        console.log(currentFlagBtn.html())
        currentFlagBtn.trigger('mouseover');
        wrapper.vm.$nextTick( () => {
          console.log(wrapper.html());
          // const localesBtn = wrapper.findAll("btn");
        });
        // when
        // localesBtn.at(1).trigger("click"); // French locale
        // then
        // expect(wrapper.wrapper.vm.currentLocaleIndex).toBe(1);
      });

    });

console.log

console.log tests / unit / Toolbar.spec.js:32       当前本地索引:0

console.log tests/unit/Toolbar.spec.js:35
  <button type="button" class="v-btn v-btn--flat" id="current-flag"><div class="v-btn__content"><img src="[object Object]" width="24px"></div></button>

console.log tests/unit/Toolbar.spec.js:38
  <nav class="v-toolbar v-toolbar--fixed" style="margin-top: 0px; padding-right: 0px; padding-left: 0px; transform: translateY(0px);">

      <div class="v-toolbar__content" style="height: 80px;">

        <div class="v-toolbar__title">
           <img src="@/assets/images/app_logo.png" alt=""> 
          <div class="v-menu btn btn--flat v-menu--inline" style="margin-bottom: 12px;">
            <div class="v-menu__activator">
               <button type="button" class="v-btn v-btn--flat" id="current-flag">
                <div class="v-btn__content">
                    <img src="[object Object]" width="24px">
                </div>
              </button>
            </div>
          </div>
       </div> 

      <div class="spacer"></div> 

      <div class="v-toolbar__items">
          <button type="button" class="v-btn v-btn--flat">
            <div class="v-btn__content">
                <i aria-hidden="true"class="v-icon v-icon--left material-icons">home</i>
                <span>Home</span>
            </div>
          </button> 
          <button type="button" class="v-btn v-btn--flat">
            <div class="v-btn__content">
               <i aria-hidden="true" class="v-icon v-icon--left material-icons">info</i> 
                <span>About</span>
             </div>
          </button>
      </div>

    </div>
  </nav>

1 个答案:

答案 0 :(得分:1)

我找到了解决方案,但也许有人可以解释原因:

btnFlags.at(1).vm.$emit('click');  // OK

btnFlags.at(1).trigger('click');  // NOT OK

这是运行良好的规范:

import Vue from "vue";
import router from "@/router";
import Vuetify from "vuetify";
import i18n from "@/locales";
import { mount, shallowMount } from "@vue/test-utils";
import Toolbar from "@/components/shared/Toolbar.vue";

describe("Toolbar.vue", () => {
  let wrapper;
  beforeEach(() => {
    Vue.use(Vuetify);
    Vue.filter("translate", function(value) {
      if (!value) return "";
      value = "lang.views.global." + value.toString();
      return i18n.t(value);
    });
    const el = document.createElement('div');
    el.setAttribute('data-app', true);
    document.body.appendChild(el);
  });

  it("should change locale", async () => {
    // given
    wrapper = shallowMount(Toolbar, { router, i18n });
    console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
    const btnFlags = wrapper.findAll("v-list-tile-stub");
    // when
    btnFlags.at(1).vm.$emit('click');
    await wrapper.vm.$nextTick();
    // then
    console.log('NEW LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
    expect(wrapper.vm.currentLocaleIndex).toBe(1);
  });

});