Vue Router не может перемещаться изнутри модульных тестов, используя шутку - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть маршрутизатор, компоненты 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('/');
  });

});
...