Подтвердить что ты не робот

Как написать тест, который издевается над объектом $route в компонентах vue

У меня есть компонент, который содержит инструкцию типа this.$route.fullPath, как мне высмеять значение fullPath объекта $route, если я хочу проверить этот компонент?

4b9b3361

Ответ 1

Лучше не издеваться над vue-router, а скорее использовать его для рендеринга компонента, таким образом вы получите правильный рабочий маршрутизатор. Пример:

import Vue from 'vue'
import VueRouter from 'vue-router'
import totest from 'src/components/totest'

describe('totest.vue', () => {
  it('should totest renders stuff', done => {
    Vue.use(VueRouter)
    const router = new VueRouter({routes: [
        {path: '/totest/:id', name: 'totest', component: totest},
        {path: '/wherever', name: 'another_component', component: {render: h => '-'}},
    ]})
    const vm = new Vue({
      el: document.createElement('div'),
      router: router,
      render: h => h('router-view')
    })
    router.push({name: 'totest', params: {id: 123}})
    Vue.nextTick(() => {
      console.log('html:', vm.$el)
      expect(vm.$el.querySelector('h2').textContent).to.equal('Fred Bloggs')
      done()
    })
  })
})

Примечания:

  • Я использую версию vue только для исполнения, следовательно render: h => h('router-view').
  • Я тестирую только компонент totest, но другие могут потребоваться, если на них ссылаются totest например. another_component в этом примере.
  • Вам нужно nextTick для отображения HTML, прежде чем вы сможете его просмотреть/протестировать.

Одна из проблем заключается в том, что большинство примеров, которые я нашел, относятся к старой версии vue-router, см. документы о переносах, например, в некоторых примерах используется router.go(), который теперь не работает.

Ответ 2

Я не согласен с лучшим ответом - вы можете ошибаться в $route без каких-либо проблем.

С другой стороны, установка vue-router несколько раз на базовый конструктор вызовет проблемы. Он добавляет $route и $router качестве свойств только для чтения. Это делает невозможным перезаписать их в будущих тестах.

Есть два способа добиться этого с помощью vue-test-utils.

Mocking vue-router с опцией mocks

const $route = {
    fullPath: 'full/path'
}
const wrapper = mount(ComponentWithRouter, { 
  mocks: {
    $route
  } 
})

wrapper.vm.$route.fullPath // 'full/path'

Вы также можете безопасно установить Vue Router с помощью createLocalVue:

Установка vue-router безопасно в тестах с помощью createLocalVue

const localVue = createLocalVue()
localVue.use(VueRouter)
const routes = [
 {
   path: '/',
   component: Component
 }
]
const router = new VueRouter({
 routes
})
const wrapper = mount(ComponentWithRouter, { localVue, router })
expect(wrapper.vm.$route).to.be.an('object')

Ответ 3

Все благодарности за @SColvin за его ответ; помогли найти ответ в моем сценарии, в котором у меня был компонент с маршрутизатор-ссылкой, которая бросала

ERROR: '[Vue warn]: Error in render function: (found in <RouterLink>)'

во время unit test, потому что Vue не поставлялся с маршрутизатором. Используя @SColvin ответ, чтобы переписать тест, первоначально поставляемый vue-cli из

describe('Hello.vue', () =>
{
  it('should render correct contents', () =>
  {
    const Constructor = Vue.extend(Hello);
    const vm = new Constructor().$mount();
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome to Your Vue.js App');
  });

к

describe('Hello.vue', () =>
{
  it('should render correct contents', () =>
  {
    Vue.use(VueRouter);
    const router = new VueRouter({
      routes: [
        { path: '/', name: 'Hello', component: Hello },
      ],
    });
    const vm = new Vue({
      el: document.createElement('div'),
      /* eslint-disable object-shorthand */
      router: router,
      render: h => h('router-view'),
    });
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome to Your Vue.js App');
  });
});

Не нужно передавать параметры в представление, я мог бы упростить компонент как рендеринг по умолчанию, не нужно нажимать и не нужно ждать nextTick. HTH кто-то еще!

Ответ 4

Добавляя к большому ответу от @SColvin, вот пример этого, используя Avoriaz:

import { mount } from 'avoriaz'
import Vue from 'vue'
import VueRouter from 'vue-router'
import router from '@/router'
import HappyComponent from '@/components/HappyComponent'

Vue.use(VueRouter)

describe('HappyComponent.vue', () => {
  it('renders router links', () => {
    wrapper = mount(HappyComponent, {router})
    // Write your test
  })
})

Я считаю, что это должно работать с vue-test-utils.

Ответ 5

Взгляните на этот пример, используя vue-test-utils, где я издеваюсь над маршрутизатором и хранилищем.

import ArticleDetails from '@/components/ArticleDetails'
import { mount } from 'vue-test-utils'
import router from '@/router'

describe('ArticleDetails.vue', () => {
  it('should display post details', () => {
    const POST_MESSAGE = 'Header of our content!'

    const EXAMPLE_POST = {
      title: 'Title',
      date: '6 May 2016',
      content: `# ${POST_MESSAGE}`
    }

    const wrapper = mount(ArticleDetails, {
      router,

      mocks: {
        $store: {
          getters: {
            getPostById () {
              return EXAMPLE_POST
            }
          }
        }
      }
    })

    expect(wrapper.vm.$el.querySelector('h1.post-title').textContent.trim()).to.equal(EXAMPLE_POST.title)
    expect(wrapper.vm.$el.querySelector('time').textContent.trim()).to.equal(EXAMPLE_POST.date)
    expect(wrapper.vm.$el.querySelector('.post-content').innerHTML.trim()).to.equal(
      `<h1>${POST_MESSAGE}</h1>`
    )
  })
})

Ответ 6

Это то, что я делал по в этой статье:

it('renders $router.name', () => {
    const scopedVue = Vue.extend();

    const mockRoute = {
        name: 'abc'
    };

    scopedVue.prototype.$route = mockRoute;

    const Constructor = scopedVue.extend(Component);
    const vm = new Constructor().$mount();
    expect(vm.$el.textContent).to.equal('abc');
});

Ответ 7

Вы можете издеваться над vm. $ Router, установив vm._routerRoot._router

Например

var Constructor      = Vue.extend(Your_Component)
var vm               = new Constructor().$mount()
var your_mock_router = {hello:'there'}

vm.$router             = your_mock_router //An error 'setting a property that has only a getter'
vm._routerRoot._router = your_mock_router //Wow, it works!

Вы можете проверить свой исходный код здесь: https://github.com/vuejs/vue-router/blob/dev/dist/vue-router.js#L558

Ответ 8

Самый простой способ, который я нашел, - высмеять $ route.

it('renders $router.name', () => {
  const $route = {
    name: 'test name - avoriaz'
  }


 const wrapper = shallow(Component, {
    mocks: {
      $route
    }
  })
  expect(wrapper.text()).to.equal($route.name)
})

Ответ 9

Самый простой метод, который я нашел, - использовать localVue

import { createLocalVue, mount } from '@vue/test-utils'
import ComponentName from 'componentPath'
import Vuex from 'vuex'
import store from '@/store/store' //Add store file if any getters is accessed
import VueRouter from 'vue-router'

describe('File name', () => { 
const localVue = createLocalVue()
localVue.use(VueRouter)
const routes = [  //Can also be rreplaced with route(router.js) file
    {
        path: '/path',
        component: ComponentName,
        name: 'Route name'
    }
]
const router = new VueRouter({
    routes
})
router.push({ 
              name: 'Route name',
              params: {} 
            }) //if needed
const wrapper = mount(ComponentName, {localVue, router, store })
beforeEach(function() {      
});

    it('Method()', () => {
        wrapper.vm.methodName()
        expect(wrapper.vm.$route.path).toBe(routes[0].path)
    });
});

Надеюсь, поможет!!!

Ответ 10

Никакой ответ не помог мне, поэтому я копаюсь в документации vue-test-utils и нашел себе рабочий ответ, поэтому вам нужно импортировать.

import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
const localVue = createLocalVue();

Мы создали пример экземпляра vue. Во время тестирования вам нужно использовать shallowMount чтобы вы могли предоставить экземпляр и маршрутизатор vue.

describe('Components', () => {
  it('renders a comment form', () => {
    const COMMENTFORM = shallowMount(CommentForm,{
      localVue,
      router
    });
  })
})

Вы можете легко пройти маршрутизатор и неглубокое крепление, и это не дает вам ошибки. Если вы хотите передать магазин, вы используете:

import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
import store from '@/store.ts';
const localVue = createLocalVue();

И затем пройдите магазин:

describe('Components', () => {
  it('renders a comment form', () => {
    const COMMENTFORM = shallowMount(CommentForm,{
      localVue,
      router,
      store
    });
  })
})

Это решение разрешило следующие ошибки:

  • Невозможно прочитать свойства "параметры" неопределенного при использовании this.$route.params.id
  • Неизвестный пользовательский элемент router-link