|
| 1 | +## Добавляем входные параметры через propsData |
| 2 | + |
| 3 | +`propsData` может использоваться как с `mount`, так и с `shallowMount`. Данный метод часто используют при тестировании входных параметров, которые получает компонент от своего родителя. |
| 4 | + |
| 5 | +`propsData` передаётся вторым аргуметов в `shallowMount` или `mount` в следующем виде: |
| 6 | + |
| 7 | +```js |
| 8 | +const wrapper = shallowMount(Foo, { |
| 9 | + propsData: { |
| 10 | + foo: 'bar' |
| 11 | + } |
| 12 | +}) |
| 13 | +``` |
| 14 | + |
| 15 | +## Создаём компонент |
| 16 | + |
| 17 | +Добавим новый простенький компонент `<SubmitButton>`, который принимает на вход параметры `msg` и `isAdmin`. В зависимости от `isAdmin` компонент будет содержать `<span>` в одном из двух состояний: |
| 18 | + |
| 19 | +* `Не авторизован`, если `isAdmin` в значении false (или не передан) |
| 20 | +* `Привилегии администратора`, если `isAdmin` в значении true |
| 21 | + |
| 22 | +```vue |
| 23 | +<template> |
| 24 | + <div> |
| 25 | + <span v-if="isAdmin">Привилегии администратора</span> |
| 26 | + <span v-else>Не авторизован</span> |
| 27 | + <button> |
| 28 | + {{ msg }} |
| 29 | + </button> |
| 30 | + </div> |
| 31 | +</template> |
| 32 | +
|
| 33 | +<script> |
| 34 | +export default { |
| 35 | + name: "SubmitButton", |
| 36 | +
|
| 37 | + props: { |
| 38 | + msg: { |
| 39 | + type: String, |
| 40 | + required: true |
| 41 | + }, |
| 42 | + isAdmin: { |
| 43 | + type: Boolean, |
| 44 | + default: false |
| 45 | + } |
| 46 | + } |
| 47 | +} |
| 48 | +</script> |
| 49 | +``` |
| 50 | + |
| 51 | +## Первый тест |
| 52 | + |
| 53 | +Добавим проверку сообщения в случае, когда у пользователя нет привилегий администратора. |
| 54 | + |
| 55 | +```js |
| 56 | +import { shallowMount } from '@vue/test-utils' |
| 57 | +import SubmitButton from '@/components/SubmitButton.vue' |
| 58 | + |
| 59 | +describe('SubmitButton.vue', () => { |
| 60 | + it("Отображает сообщение для неавторизованного пользователя", () => { |
| 61 | + const msg = "Войти" |
| 62 | + const wrapper = shallowMount(SubmitButton,{ |
| 63 | + propsData: { |
| 64 | + msg: msg |
| 65 | + } |
| 66 | + }) |
| 67 | + |
| 68 | + console.log(wrapper.html()) |
| 69 | + |
| 70 | + expect(wrapper.find("span").text()).toBe("Не авторизован") |
| 71 | + expect(wrapper.find("button").text()).toBe("Войти") |
| 72 | + }) |
| 73 | +}) |
| 74 | +``` |
| 75 | + |
| 76 | +Запустим тесты через `yarn test:unit`. Результат будет следующий: |
| 77 | + |
| 78 | +```bash |
| 79 | +PASS tests/unit/SubmitButton.spec.js |
| 80 | + SubmitButton.vue |
| 81 | + ✓ Отображает сообщение для неавторизованного пользователя (15ms) |
| 82 | +``` |
| 83 | + |
| 84 | +Также выведется результат `console.log(wrapper.html())` |
| 85 | + |
| 86 | +```html |
| 87 | +<div> |
| 88 | + <span>Не авторизован</span> |
| 89 | + <button> |
| 90 | + Войти |
| 91 | + </button> |
| 92 | +</div> |
| 93 | +``` |
| 94 | + |
| 95 | +Как мы видим, `msg` обработался и результирующая разметка отрисовалась правильно. |
| 96 | + |
| 97 | +## Второй тест |
| 98 | + |
| 99 | +Давайте также добавим проверку еще одного возможного случая, когда `isAdmin` в значении `true` |
| 100 | + |
| 101 | +```js |
| 102 | +import { shallowMount } from '@vue/test-utils' |
| 103 | +import SubmitButton from '@/components/SubmitButton.vue' |
| 104 | + |
| 105 | +describe('SubmitButton.vue', () => { |
| 106 | + it('Отображает сообщение для администратора', () => { |
| 107 | + const msg = "Войти" |
| 108 | + const isAdmin = true |
| 109 | + const wrapper = shallowMount(SubmitButton,{ |
| 110 | + propsData: { |
| 111 | + msg, |
| 112 | + isAdmin |
| 113 | + } |
| 114 | + }) |
| 115 | + |
| 116 | + expect(wrapper.find("span").text()).toBe("Привилегии администратора") |
| 117 | + expect(wrapper.find("button").text()).toBe("Войти") |
| 118 | + }) |
| 119 | +}) |
| 120 | +``` |
| 121 | + |
| 122 | +Запустим тесты через `yarn test:unit` и посмотрим на результаты: |
| 123 | + |
| 124 | +```bash |
| 125 | +PASS tests/unit/SubmitButton.spec.js |
| 126 | + SubmitButton.vue |
| 127 | + ✓ Отображает сообщение для администратора (4ms) |
| 128 | +``` |
| 129 | +Мы также вывели разметку через `console.log(wrapper.html())`: |
| 130 | + |
| 131 | +```html |
| 132 | +<div> |
| 133 | + <span>Привилегии администратора</span> |
| 134 | + <button> |
| 135 | + Войти |
| 136 | + </button> |
| 137 | +</div> |
| 138 | +``` |
| 139 | + |
| 140 | +Как мы видим `isAdmin` был использован, чтобы отрисовать правильный `<span>` |
| 141 | + |
| 142 | +## Рефакторинг тестов |
| 143 | + |
| 144 | +Давайте перепишем наши тесты, придерживаясь принципа "Don't Repeat Yourself" (не повторяйся). Так как все тесты проходят проверку, мы можем их уверенно изменять. После рефакторинга нам также нужно убедиться, что ничего не сломалось. |
| 145 | + |
| 146 | +## Рефактор через фабрику (factory function) |
| 147 | + |
| 148 | +В обоих тестах мы вызываем `shallowMount`, затем передаём похожий объект `propsData`. Мы можем это изменить, используя фабрику. Под фабрикой понимают функцию, которая возвращает объект, отсюда и её название. |
| 149 | + |
| 150 | +```js |
| 151 | +const msg = "Войти" |
| 152 | +const factory = (propsData) => { |
| 153 | + return shallowMount(SubmitButton, { |
| 154 | + propsData: { |
| 155 | + msg, |
| 156 | + ...propsData |
| 157 | + } |
| 158 | + }) |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +Выше приведена функция, которая отрисовывает компонент `SubmitButton` через `shallowMount`. Мы можем передавать любые данные первым аргументом в функцию `factory`. Давайте перепишем тесты, придерживаясь принципа DRY. |
| 163 | + |
| 164 | +```js |
| 165 | +describe("SubmitButton.vue", () => { |
| 166 | + describe("Нет привилегий администратора", ()=> { |
| 167 | + it("Выводит верное сообщение", () => { |
| 168 | + const wrapper = factory() |
| 169 | + |
| 170 | + expect(wrapper.find("span").text()).toBe("Не авторизован") |
| 171 | + expect(wrapper.find("button").text()).toBe("Войти") |
| 172 | + }) |
| 173 | + }) |
| 174 | + |
| 175 | + describe("Есть привилегии администратора", ()=> { |
| 176 | + it("Выводит верное сообщение", () => { |
| 177 | + const wrapper = factory({ isAdmin: true }) |
| 178 | + |
| 179 | + expect(wrapper.find("span").text()).toBe("Привилегии администратора") |
| 180 | + expect(wrapper.find("button").text()).toBe("Войти") |
| 181 | + }) |
| 182 | + }) |
| 183 | +}) |
| 184 | +``` |
| 185 | + |
| 186 | +Давайте запустим тесты еще раз. Они всё еще работают. |
| 187 | + |
| 188 | +```bash |
| 189 | +PASS tests/unit/SubmitButton.spec.js |
| 190 | + SubmitButton |
| 191 | + Нет привилегий администратора |
| 192 | + ✓ Выводит верное сообщение (26ms) |
| 193 | + Есть привилегии администратора |
| 194 | + ✓ Выводит верное сообщение (3ms) |
| 195 | +``` |
| 196 | + |
| 197 | +Поскольку у нас есть хороший набор тестов, мы можем легко и уверенно проводить рефакторинг. |
| 198 | + |
| 199 | +## Заключение |
| 200 | + |
| 201 | +- Передавая `propsData` во время отрисовки компонента, вы можете устанавливать входные параметры, которые будут применены в тесте |
| 202 | +- Функции-фабрики могут быть использованы, чтобы достичь принципа DRY в тестах |
| 203 | +- Вместо `propsData`, вы также можете использовать [`setProps`](https://vue-test-utils.vuejs.org/api/wrapper-array/#setprops-props) для того чтобы передавать входные параметры в тесты. |
0 commit comments