Не может быть установлен Vue Компонент для модульного тестирования - PullRequest
0 голосов
/ 11 февраля 2020

Я новичок в Vue, но у меня есть проект со страницей входа. Я могу запустить его нормально, но я пытаюсь добавить юнит-тестирование ретро (я знаю, я делаю это задом наперед). Я использую Mocha + Chai и vue test utils. когда я пытаюсь сделать shallowMount, я получаю сообщение об ошибке, в котором говорится, что он не может прочитать свойство. Вот полный текст ошибки:

  1) Login
       Has login text:
     TypeError: Cannot read property 'email' of undefined
      at Proxy.render (webpack:///./src/views/user/Login.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options:65:34)
      at VueComponent.Vue._render (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:3640:22)
      at VueComponent.updateComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4168:21)
      at Watcher.get (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4582:25)
      at new Watcher (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4569:45)
      at mountComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4175:3)
      at VueComponent.Vue.$mount (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:8512:10)
      at init (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:3232:13)
      at createComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6053:9)
      at createElm (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6001:9)
      at VueComponent.patch [as __patch__] (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6611:7)
      at VueComponent.Vue._update (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4039:19)
      at VueComponent.updateComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4168:10)
      at Watcher.get (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4582:25)
      at new Watcher (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4569:45)
      at mountComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4175:3)
      at VueComponent.Vue.$mount (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:8512:10)
      at mount (webpack:///./node_modules/@vue/test-utils/dist/vue-test-utils.js?:13265:21)
      at shallowMount (webpack:///./node_modules/@vue/test-utils/dist/vue-test-utils.js?:13278:10)
      at Context.eval (webpack:///./tests/unit/login.spec.js?:17:87)
      at processImmediate (internal/timers.js:439:21)

Вот мой файл пакетов:

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e",
    "test": "mochapack --webpack-config webpack.config.js --require tests/setup.js tests/**/*.spec.js"
  },
  "dependencies": {
    "axios": "^0.19.2",
    "core-js": "^3.6.4",
    "vue": "^2.6.11",
    "vue-axios": "^2.1.5",
    "vue-router": "^3.1.5",
    "vuelidate": "^0.7.5",
    "vuetify": "^2.1.0",
    "vuex": "^3.1.2"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.2.0",
    "@vue/cli-plugin-e2e-cypress": "^4.2.0",
    "@vue/cli-plugin-router": "^4.2.0",
    "@vue/cli-plugin-unit-mocha": "^4.2.0",
    "@vue/cli-plugin-vuex": "^4.2.0",
    "@vue/cli-service": "^4.2.0",
    "@vue/test-utils": "^1.0.0-beta.31",
    "chai": "^4.1.2",
    "jsdom": "^16.1.0",
    "jsdom-global": "^3.0.2",
    "mocha": "^7.0.1",
    "mochapack": "^1.1.13",
    "node-sass": "^4.12.0",
    "sass": "^1.19.0",
    "sass-loader": "^8.0.2",
    "vue-cli-plugin-vuetify": "^2.0.4",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.3.0"
  }
}

Вот мой код компонента:

<template>
  <v-container fluid fill-height>
    <v-layout align-center justify-center>
      <v-flex xs12 sm8 md4>
        <v-card class="elevation-12">
          <v-toolbar color="primary" dark flat>
            <v-toolbar-title>Login form</v-toolbar-title>
          </v-toolbar>
          <v-card-text>
            <v-form @submit.prevent="login">
              <v-text-field
                autofocus
                v-model="email"
                label="Email"
                prepend-icon="mdi-account-circle"
                @blur="$v.email.$touch()"
              />
              <div class="red--text text--lighten-1" v-if="$v.email.$error">
                <div v-if="!$v.email.required">
                  <v-icon color="red">mdi-alert-circle-outline</v-icon>
                  Email is required
                </div>
                <div v-if="!$v.email.email">
                  <v-icon color="red">mdi-alert-circle-outline</v-icon>
                  Invalid email address.
                </div>
              </div>

              <v-text-field
                v-model="password"
                :type="showPassword ? 'text' : 'password'"
                label="Password"
                prepend-icon="mdi-lock"
                :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
                @click:append="showPassword = !showPassword"
                @blur="$v.password.$touch()"
              />

              <div
                class="red--text text--lighten-1"
                v-if="$v.password.$error && !$v.password.required"
              >
                <v-icon color="red">mdi-alert-circle-outline</v-icon>
                Password is required
              </div>

              <v-btn
                type="submit"
                color="success"
                name="button"
                :disabled="$v.$invalid"
              >
                Login now
              </v-btn>

              <v-btn
                text
                small
                color="primary"
                :to="{ name: 'forgotPassword' }"
              >
                Forgot your password?
              </v-btn>

              <div v-if="error" class="red--text text--lighten-1">
                <v-icon color="red">mdi-alert-circle-outline</v-icon>
                {{ getLoginErrorMsg() }}
              </div>
            </v-form>
          </v-card-text>
        </v-card>
      </v-flex>
    </v-layout>
  </v-container>
</template>

<script>
import { required, email } from "vuelidate/lib/validators";

export default {
  name: "Login",

  data() {
    return {
      email: "",
      password: "",
      error: null,
      showPassword: false
    };
  },

  validations: {
    email: {
      required,
      email
    },
    password: {
      required
    }
  },

  methods: {
    login() {
      console.log("Entering component login method");

      this.$store
        .dispatch("user/login", {
          username: this.email,
          password: this.password
        })
        .then(() => {
          console.log(
            'this.$store.getters["user/passwordChangeRequired"]' +
              this.$store.getters["user/passwordChangeRequired"]
          );
          if (this.$store.getters["user/passwordChangeRequired"]) {
            console.log("push to changePassword");
            this.$router.push({ name: "changePassword" });
          } else {
            console.log("pushing to home");
            this.$router.push({ name: "home" });
          }
        })
        .catch(err => {
          this.error = err.response;
        });
    },

    getLoginErrorMsg() {
      if (this.error.status == 401) {
        return "Invalid username or password";
      } else {
        // return `Login failed: {this.error.statusText}`;
        return "failed";
      }
    }
  }
};
</script>

<style></style>

Вот тест file:

import { expect } from "chai";
import { mount, shallowMount } from "@vue/test-utils";
import Login from "../../src/views/user/Login.vue";

describe("Login", () => {

  it("Has login text", () => {
    // const wrapper = mount(Login);
    const wrapper = shallowMount(Login);
    // not getting here.
    expect(2).to.equal(2);
  });
});

Примечание: ни mount, ни shallowMount не работают. Они оба выдают одну и ту же ошибку.

Вот мой файл webpack.config. js file:

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // this will apply to both plain `.js` files
      // AND `<script>` blocks in `.vue` files
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      // this will apply to both plain `.css` files
      // AND `<style>` blocks in `.vue` files
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
  ]
}

Я часами гуглял и не могу ничего найти. Итак, я явно делаю что-то действительно глупое, потому что, похоже, ни у кого больше нет этой проблемы. Скажите, пожалуйста, почему он выдает эту ошибку и не может отменить или смонтировать этот vue компонент.

1 Ответ

0 голосов
/ 11 февраля 2020

Похоже, что в моих тестах / единицах / индексе. js не хватало некоторых вещей ... У меня там не было vuelidate, и я считаю, что это было проблемой. Я изменил его на следующее, и теперь оно работает:

// index.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import VueRouter from 'vue-router';
import Vuelidate from "vuelidate";


Vue.config.productionTip = false;
Vue.use(Vuetify);
Vue.use(VueRouter);
Vue.use(Vuelidate);
...