У меня есть маршрутизатор, компоненты Home, Login и модульные тесты для компонента Login.
Логика такова: когда пользователь не прошел проверку подлинности, отправьте его на страницу входа, как только он будет аутентифицирован, отправьте его на домашнюю страницу.
Логика отлично работает в браузере, однако, когда я запускаю модульные тесты, я получаю исключение: throw: undefined , как только компонент входа в систему пытается перейти с помощью this.$router.push('/');
В консоли я вижу сообщение:
trying to route /login /
, а затем выдается исключение при запуске next();
Я пропустил некоторые настройкиправильно ли работает маршрутизатор в тестовой среде?
В качестве альтернативы: есть ли способ высмеять функцию next (), переданную в навигационную охрану?
Вот маршрутизатор:
import VueRouter from 'vue-router';
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';
import { state } from '@/store';
export const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/login',
name: 'login',
component: Login,
meta: {
noAuthRequired: true,
},
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to: any, from: any, next: any) => {
console.log('trying to route', from.fullPath, to.fullPath);
const isAuthed = !!state.user.token;
if (!to.meta.noAuth && !isAuthed) {
next({ name: 'login' });
} else {
next();
}
});
export default router;
Компонент (соответствующая часть):
import Vue from 'vue';
import Component from 'vue-class-component';
import { axios } from '../plugins/axios';
@Component
export default class App extends Vue {
private credentials = {
email: '',
password: '',
};
private error = '';
private async login() {
try {
const data = await axios.post('http://localhost:5000/api/v1/user/auth', this.credentials);
const token = data.data.payload;
this.$store.dispatch('setUser', { token });
this.error = '';
this.$router.push('/');
} catch (error) {
console.warn(error);
this.error = error;
}
}
}
И модульный тест:
import Vue from 'vue';
import Vuetify from 'vuetify';
import AxiosMockAdapter from 'axios-mock-adapter';
import { Wrapper, shallowMount, createLocalVue } from '@vue/test-utils';
import flushPromises from 'flush-promises';
import Vuex, { Store } from 'vuex';
import { axios } from '@/plugins/axios';
import VTest from '@/plugins/directive-test';
import LoginPage from '@/views/Login.vue';
import { mainStore, state, IState } from '@/store';
import VueRouter from 'vue-router';
import router from '@/router';
describe('Login page tests', () => {
let page: Wrapper<Vue>;
let localStore: Store<IState>;
const localVue = createLocalVue();
const maxios = new AxiosMockAdapter(axios);
const vuetify = new Vuetify();
const errorMessage = 'Input payload validation failed';
const emailError = 'Invalid Email format';
const validData = {
email: 'valid@email.com',
password: 'test pass',
};
// in order for "click" action to submit the form,
// the v-btn component must be stubbed out with an HTML button
const VBtn = {
template: '<button type="submit"/>',
};
localVue.use(Vuetify);
localVue.directive('test', VTest);
localVue.use(Vuex);
localVue.use(VueRouter);
beforeAll(() => {
maxios.onPost().reply((body: any) => {
const jsonData = JSON.parse(body.data);
if (jsonData.email !== validData.email) {
return [400, {
message: errorMessage,
errors: { email: emailError },
}];
}
return [200, { payload: 'valid-token' }];
});
});
beforeEach(() => {
try {
localStore = new Vuex.Store({
...mainStore,
state: JSON.parse(JSON.stringify(state)),
});
page = shallowMount(LoginPage, {
store: localStore,
router,
localVue,
vuetify,
stubs: {
VBtn,
},
attachToDocument: true,
sync: false,
});
} catch (error) {
console.warn(error);
}
});
afterEach(() => {
maxios.resetHistory();
page.destroy();
});
const submitLoginForm = async (data: any) => {
page.find('[test-id="LoginEmailField"]').vm.$emit('input', data.email);
page.find('[test-id="LoginPasswordField"]').vm.$emit('input', data.password);
page.find('[test-id="LoginBtn"]').trigger('click');
await flushPromises();
};
it('Redirects user to home page after successful auth', async () => {
await submitLoginForm(validData);
expect(page.vm.$route.path).toEqual('/');
});
});