Я новичок в 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 компонент.