Недавно я изучал Jest с помощью @ vue / test-utils и наткнулся на интересный тестовый пример. Мне нужно было утверждать, что мой компонент вызывает метод в ответ на порожденное событие дочернего компонента. Это привело меня к открытию нескольких новых (новых для меня) способов доступа к параметрам родительского и дочернего компонентов.

Передать все реквизиты / данные сразу

Иногда нам может потребоваться просто передать все свойства родительского компонента дочернему компоненту. Это легко сделать так: <child-component :example-data="$props" /> и данные тоже <child-component :example-data="$data" />. Быстро и безболезненно.

Бонус: вы также можете передать реквизит на <router-view />. В этом примере данные компонента all-props.vue: элементы, ошибка и загрузка будут доступны для всех дочерних маршрутов в this.$attrs['example-data']

<template>
  <div class='all-props'>
    <child-component :example-data="$props" />
    <router-view :example-data="$data" />
  </div>
</template>
<script>
import { ChildComponent } from "./components"
export default {
  name: "all-props",
  components: {
    ChildComponent
  },
  props: {
    status: {
      type: String,
      required: true,
      validator: val => ['loading','error','complete'].indexOf(val) > -1
    }
  },
  data:() => ({
    items:[],
    error: false,
    loading: false
  })
};
</script>

Параметры родитель / потомок

Вы также можете легко получить доступ к параметрам родительского / дочернего компонента. Скажем, мы хотим напрямую вызвать метод в родительском компоненте с именем coolFunction(), для этого мы можем написать this.$parent.coolFunction(). Это работает в обоих направлениях, поэтому компонент может делать то же самое с дочерним компонентом. В приведенном ниже примере Home.vue (родительский) и HelloWorld.vue (дочерний) из каркаса проекта по умолчанию vue-cli. Мы можем напрямую вызвать дочерний метод triggerAlert(), используя $ refs или $ children.

Home.vue

<template>
  <div class="home">
    <HelloWorld ref="foo" msg="Hello World" />
    <button
      @click.exact="triggerChildMethod"
      @keydown.enter="triggerChildMethod"
    >
      Trigger Child Method
    </button>
  </div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
  name: "Home",
  components: {
    HelloWorld
  },
  props: {
    items: {
      type: Array,
      default: () => []
    }
  },
  data: () => ({
    lorem: "ipsum"
  }),
  methods: {
    triggerChildMethod() {
      this.$refs.foo.triggerAlert();
    }
  },
  /**
   * @note $refs and $children not available in created hook
   */
  mounted() {
    console.log("this.$refs.foo.$data :", this.$refs.foo.$data);
    console.log("this.$children[0].$data :", this.$children[0].$data);
  }
};
</script>

HelloWorld .vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data: () => ({
    message: null,
    items: false,
    thing: true
  }),
  methods: {
    triggerAlert() {
      alert("ayyyy");
    }
  }
};
</script>

Консольные журналы данных компонентов:

И вот мы сработали наше оповещение:

Модульный тест

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

import { mount } from '@vue/test-utils'
import Home from '@/views/home.vue'
import HelloWorld from '@/components/HelloWorld.vue'
describe('Home.vue', () => {
it('child can access and invoke a parent method', () => {
const triggerChildMethod = jest.fn()
const wrapper = mount(Home, {
      methods: {
        triggerChildMethod
      }
    })
wrapper.find(HelloWorld).vm.triggerParentMethod()
expect(triggerChildMethod).toHaveBeenCalledTimes(1)
})
})

Спасибо

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