Vue how to test component with slot and slot-props


Vue how to test component with slot and slot-props

07.06.2019 01:14:22 Просмотров 90 Источник

Я хочу проверить это FooComponent:

<div>
  <slot :fn="internalFn" />
</div>

Он используется именно так (например, в ParentComponent):

<FooComponent>
  <template slot-scope="slotProps">
    <BarComponent @some-event="slotProps.fn" />
  </template>
</FooComponent>

Поэтому я хочу проверить, как мой компонент реагирует на вызов этого "fn" из реквизита слота. Самый простой способ, который я вижу, - это взять сам метод и вызвать его, вот так:

cosnt wrapper = shallowMount(FooComponent, /* ... */)
wrapper.vm.methods.internalFn(/* test payload */)
expect(wrapper.emitted()).toBe(/* some expectation */)

Но это хорошо известно как анти-паттерн о тестировании внутренней реализации. Поэтому вместо этого я хотел бы протестировать его через prop fn, переданный в слот, потому что это также своего рода компонентный интерфейс, например, собственный реквизит компонента.

Но как проверить реквизит, пройденный в слот? Я могу себе представить, что это работает только в том случае, если я проверю, что ParentComponent что-то вроде этого:

const wrapper = shallowMount(ParentComponent, /* ... */)
const foo = wrapper.find(FooComponent)
wrapper.find(BarComponent).vm.$emit('some-event', /*...*/)
/* write expectations against foo */

Но это похоже на тесты для FooComponent внутри тестов для ParentComponent

Может быть, есть лучший способ сделать это?

У вопроса есть решение - Посмотреть?

Ответы - Vue how to test component with slot and slot-props / Vue how to test component with slot and slot-props

Является ответом!
Alendorff

13.06.2019 12:24:41

Поскольку ответов нет, я просто делюсь тем, что у меня получилось.

Я решил проверить внутренний метод. Это не круто, но, по крайней мере, поскольку я использую typescript, у меня есть типобезопасный тест, который потерпит неудачу с явной ошибкой типа, если я переименую или изменю метод, который я тестирую. Выглядеть так:

import Foo from '@/components/foo/Foo.ts'
import FooComponent from '@/components/foo/Foo.vue'

/*...*/

cosnt wrapper = <Foo>shallowMount(FooComponent, /* ... */)

// notice that because I passed `Foo` which is a class-component, 
// I have autocomplete and type checks for vm.*
wrapper.vm.internalFn(/* test payload */)

expect(wrapper.emitted()).toBe(/* some expectation */)
danjah

10.12.2019 04:26:24

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

Вот что я придумал:

import { shallowMount } from '@vue/test-utils';
import Component from 'xyz/Component';

let wrapperSlotted;

describe('xyz/Component.vue', () => {
  beforeAll(() => {
    wrapperSlotted = shallowMount(Component, {
      data() {
        return { myProp: 'small' }
      },
      scopedSlots: {
        default: function (props) {
          return this.$createElement('div', [props.myProp]);
        }
      },
    });
  });

  it('slot prop passed to a scoped slot', () => {
    let text = wrapperSlotted.find('div').text();
    expect(text).toBe('small'); // the value of `myProp`, which has been set as the text node in the slotted <div />
  });
});

Поэтому главным было то, что я использовал функцию рендеринга для scopedSlots.

Надеюсь, это кому-то поможет :)

Помочь в развитии проекта:
Закрыть X