Создание приложения на Vue.js по TDD – обширное руководство для людей, у которых есть время – часть 5
Оригинальная статья: Daniel Kuroski — Working an application in Vue.js with TDD — An extensive guide for people who have time — part 4
Это четвертая часть в серии статей:
- Part 1: Настройка и первый тест
- Part 2: Улучшаем UserView
- Part 3: Тестирование store и остальных компонентов слоя презентации
- Part 4: Тестирование службы запросов API
- Part 5: Добавление и тестирование со сторонними зависимостями
В предыдущей статье мы закончили наше приложение 👏
В этой статье мы рассмотрим, как интегрировать наше приложение со сторонней библиотекой и как обновить наши тесты, чтобы справиться с этим изменением.
Улучшение внешнего вида + сторонние библиотеки
Мы можем стилизовать наши компоненты вручную. Я обычно делаю это из-за своих рабочих требований, но здесь я хочу показать, как мы можем стилизовать наши компоненты, используя стороннюю библиотеку. Я никогда не использовал это, но давайте попробуем. Мы собираемся использовать ElementUI.
Мы можем скачать его через Vue CLI. Давайте загрузим и установим его вручную
npm i -d element-ui
Далее давайте установим его в нашем проекте.
src/main.js
import Vue from 'vue' import Element from 'element-ui' import App from './App.vue' import router from './router' import store from './store' import './registerServiceWorker' import 'element-ui/lib/theme-chalk/index.css' Vue.use(Element) Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
Вставьте следующую разметку в App.vue
<template> <el-container> <el-main> <router-view/> </el-main> </el-container> </template>
Наши тесты все еще проходят, и мы можем перейти к изменениям компонентов.
src/components/VUserSearchForm.vue
<script> export default { name: 'UserSearchForm', data() { return { username: '' } } } </script> <template> <form @submit.prevent="$emit('submitted', username)"> <el-input placeholder="Pesquise o usuário" v-model="username" class="search-form__input" > <el-button class="search-form__button" native-type="submit" slot="append" icon="el-icon-search" ></el-button> </el-input> </form> </template>
Здесь мы только что провели наш первый большой рефакторинг, касающийся внешнего вида. По сути, у нас есть новый макет для формы нашего приложения:
Потрясающе! Наша форма выглядит лучше, но:
Наши тесты не проходят. Но что именно здесь происходит?
Что ж… поскольку мы загрузили ElementUI как стороннюю зависимость и загрузили ее в main.js, когда мы используем элементы внутри тестов нашего компонента VUserSearchForm.vue, наш компонент, используемый в тесте, не знает о ElementUI , поэтому нам нужно вернуться к файлу тестов и сделать именно то, что мы делали на main.js.
tests/unit/VUserSearchForm.spec.js
import { shallowMount, mount, createLocalVue } from '@vue/test-utils' import ElementUI from 'element-ui' import VUserSearchForm from '@/components/VUserSearchForm' const localVue = createLocalVue() localVue.use(ElementUI) describe('VUserSearchForm', () => { const build = () => { const wrapper = shallowMount(VUserSearchForm, { localVue }) return { wrapper, input: () => wrapper.find('input'), button: () => wrapper.find('button'), } } ... ...
Отлично. Мы вставляем сюда зависимость createLocalVue в строке 1, а также импортируем ElementUI в строке 2.
После этого мы создаем локальный экземпляр, подключаем ElementUI и добавляем локальный экземпляр localVue в качестве опции, когда мы визуализируем наш компонент в строке 10. По сути, это то же самое, что мы делали в Vuexcase 😄
Теперь нужно только обновить snapshot, и у нас будет более краткая информация об ошибках:
Здесь нам нужно только обновить ссылки на наши селекторы для поиска классов HTML.
const build = () => { const wrapper = shallowMount(VUserSearchForm, { localVue })return { wrapper, input: () => wrapper.find('.search-form__input'), button: () => wrapper.find('.search-form__button'), } }
Теперь проходит входной тест, а тест кнопки — нет?
Что происходит, так это то, что мы визуализируем el-input, который является настраиваемым элементом ElementUI, поэтому нам нужно вставить в него нашу кнопку, чтобы отобразить правильный интерфейс. Теперь, чтобы протестировать его, мы должны отобразить дерево зависимостей всех компонентов. Поэтому, мы собираемся использовать mount.
tests/unit/VUserSearchForm.spec.js
import { shallowMount, mount, createLocalVue } from '@vue/test-utils' import ElementUI from 'element-ui' import VUserSearchForm from '@/components/VUserSearchForm' const localVue = createLocalVue() localVue.use(ElementUI) describe('VUserSearchForm', () => { const build = () => { const options = { localVue } const wrapper = shallowMount(VUserSearchForm, options) const wrapperMounted = mount(VUserSearchForm, options) return { wrapper, wrapperMounted, input: () => wrapper.find('.search-form__input'), inputMounted: () => wrapperMounted.find('input'), button: () => wrapperMounted.find('button'), } }
Сначала мы импортируем mount. Затем мы создаем wrapperMounting, а затем возвращаем нашу кнопку, используя wrapperMounting. Теперь, когда наш компонент «mounted», мы имеем доступ ко всему дереву нашего компонента. Таким образом, мы можем искать кнопку и даже визуализированный input ElementUI.
В этом случае я также возвращаю wrapperMounting и inputMounting, так как мы собираемся использовать их в следующем тесте.
Далее, мы должны выполнить наш последний тестовый проход, в ходе которого мы проверяем событие submitted.
tests/unit/VUserSearchForm.spec.js
... ... it('calls "submitted" event when submitting form', () => { // arrange const expectedUser = 'kuroski' const { wrapperMounted, button, inputMounted } = build() inputMounted().element.value = expectedUser // act inputMounted().trigger('input') button().trigger('click') button().trigger('submit') // assert expect(wrapperMounted.emitted().submitted[0]).toEqual([expectedUser]) }) ... ...
Для этого, поскольку мы имеем дело с событиями из собственных компонентов, созданных ElementUI, нам нужно импортировать wrapperMounting и inputMounting вместо версий в shallowMount.
Их нужно только заменить на тест. Таким образом, мы возвращаемся к зеленой фазе.
Наконец, давайте изменим только css в VUserProfile.vue, так как мы уже изменили один из компонентов для использования сторонней библиотеки.
src/components/VUserProfile.vue
<style scoped> .user-profile { border-top: solid 1px #ccc; padding-top: 20px; margin-top: 20px; display: flex; flex-direction: column; align-items: center; } .user-profile__avatar { border-radius: 50%; width: 150px; height: 150px; } .user-profile__name { margin-top: 14px; font-size: 24px; font-family: 'Bungee', cursive; text-transform: uppercase; } .user-profile__bio { margin-top: 14px; font-family: 'Open Sans', sans-serif; } </style>
Теперь все готово! Наше приложение проверено и функционирует 😄
Заключение
В пятой части мы сделали:
- Подключили сторонние библиотеки компонентов
- Обновили тесты, чтобы учесть эти изменения
Твиттер автора оригинальной статьи : @DKuroski
Спасибо за перевод!
Отличный материал, чтобы войти в курс дела тестирования Vue приложений.
Единственное, метод find у враппера в июле 2020 deprecated. Используем findComponent