useLayoutEffect
Вариация useEffect, которая дает шанс вмешаться в рендеринг компонента.
useLayoutEffect запускается СИНХРОННО после всех изменений DOM, ДО ТОГО, как браузер осуществит их отрисовку. Это практически полный аналог классовых методов componentDidMount/componentDidUpdate.
Этот хук дает возможность что-то изменить в отрисованном представлении так, чтобы пользователь не увидел предыдущего состояния.
#документация #хуки
Вариация useEffect, которая дает шанс вмешаться в рендеринг компонента.
useLayoutEffect запускается СИНХРОННО после всех изменений DOM, ДО ТОГО, как браузер осуществит их отрисовку. Это практически полный аналог классовых методов componentDidMount/componentDidUpdate.
Этот хук дает возможность что-то изменить в отрисованном представлении так, чтобы пользователь не увидел предыдущего состояния.
#документация #хуки
useDebugValue
Позволяет отобразить метку для пользовательских хуков в React Dev Tools, что может быть полезно для дебаггинга.
#документация #хуки #отладка
Позволяет отобразить метку для пользовательских хуков в React Dev Tools, что может быть полезно для дебаггинга.
#документация #хуки #отладка
Объяснение хуков
Статья от создателя React Дэна Абрамова (англ.): https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889
В принципе все, что он говорит, мы уже рассмотрели и в целом уяснили, но все-таки пропускать статью от основателя было бы неправильно.
Основные моменты:
- До появления хуков React позволял удобно разделять UI, но не логику. Хуки решают эту проблему без добавления дополнительных оберток.
- Добавление хуков не раздувает библиотеку. Напротив, их использование позволяет уменьшить размер бандла, так как хуки минифицируются лучше, чем классы.
- Хуки больше соответствуют философии React, чем классы, но от поддержки классов никто не отказывается, ничего переписывать не нужно.
- Никакой магии в хуках нет, они не сложнее, чем Array.push/Array.pop.
- Правила хуков хоть и выглядят несколько странно, но никак не помешают в работе.
#ссылки #хуки
Статья от создателя React Дэна Абрамова (англ.): https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889
В принципе все, что он говорит, мы уже рассмотрели и в целом уяснили, но все-таки пропускать статью от основателя было бы неправильно.
Основные моменты:
- До появления хуков React позволял удобно разделять UI, но не логику. Хуки решают эту проблему без добавления дополнительных оберток.
- Добавление хуков не раздувает библиотеку. Напротив, их использование позволяет уменьшить размер бандла, так как хуки минифицируются лучше, чем классы.
- Хуки больше соответствуют философии React, чем классы, но от поддержки классов никто не отказывается, ничего переписывать не нужно.
- Никакой магии в хуках нет, они не сложнее, чем Array.push/Array.pop.
- Правила хуков хоть и выглядят несколько странно, но никак не помешают в работе.
#ссылки #хуки
Medium
Making Sense of React Hooks
This week, Sophie Alpert and I presented the “Hooks” proposal at React Conf, followed by a deep dive from Ryan Florence:
React-хуки - это не магия, а обычные массивы
Статья Rudi Yardley (англ.): https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e
Руди рассказывает о том, как примерно реализованы хуки в React, и почему мы должны соблюдать правила хуков. Вкратце мы уже это разбирали, но статью все равно стоит посмотреть, в ней есть наглядная визуализация всего механизма.
#ссылки #хуки
Статья Rudi Yardley (англ.): https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e
Руди рассказывает о том, как примерно реализованы хуки в React, и почему мы должны соблюдать правила хуков. Вкратце мы уже это разбирали, но статью все равно стоит посмотреть, в ней есть наглядная визуализация всего механизма.
#ссылки #хуки
Medium
React hooks: not magic, just arrays
Untangling the rules around the proposal using diagrams
Пример запроса данных с помощью хуков
Демо-пример: https://codesandbox.io/s/jvvkoo8pq3?file=/src/index.js
Тут все очень просто:
- Создается состояние data для массива результатов, изначально - пустой массив (хук useState)
- Создается состояние query для текста поискового запроса (хук useState)
- При изменении запроса (setQuery) происходит перерендер компонента - После рендера вызывается эффект, заданный с помощью хука useEffect (у него в зависимостях указана переменная query, значение которой изменилось, поэтому он вызывается)
- Функция-эффект запрашивает данные по апи, а когда приходит ответ, записывает его в состояние data (setData)
- Снова происходит перерендер, но в этот раз эффект не вызывается, так как его единственная зависимость query не изменилась
Пошаговый туториал: https://www.robinwieruch.de/react-hooks-fetch-data
Здесь все подробно разобрано:
- Почему в useEffect нельзя передавать асинхронную функцию
- Зачем нужен массив зависимостей и как он работает
- Зачем используется переменная ignore внутри эффекта (спойлер: чтобы не выводить данные предыдущего запроса, если после него уже отправлен новый)
- Добавление индикатора загрузки
- Обработка ошибок загрузки
- Добавление формы (form) и обработка события onSubmit
Кроме того описан пользовательский хук для извлечения данных useDataApi. Он принимает полный урл запроса, поэтому может работать с любым API. Этот хук инкапсулирует логику запроса данных, индикатора загрузки и обработки ошибок запроса.
Хук useDataApi на гитхабе: https://github.com/the-road-to-learn-react/use-data-api
Наконец в конце рассматривается кейс с заменой отдельных простых состояний (isError, isLoading, data) на единое сложное состояние с использованием хука useReducer. При этом в нужные моменты вызываются нужные события (FETCH_INIT, FETCH_SUCCESS, FETCH_FAILURE) с помощью метода dispatch, а редьюсер обрабатывает их и обновляет состояние.
#ссылки #хуки #примерыкода
Демо-пример: https://codesandbox.io/s/jvvkoo8pq3?file=/src/index.js
Тут все очень просто:
- Создается состояние data для массива результатов, изначально - пустой массив (хук useState)
- Создается состояние query для текста поискового запроса (хук useState)
- При изменении запроса (setQuery) происходит перерендер компонента - После рендера вызывается эффект, заданный с помощью хука useEffect (у него в зависимостях указана переменная query, значение которой изменилось, поэтому он вызывается)
- Функция-эффект запрашивает данные по апи, а когда приходит ответ, записывает его в состояние data (setData)
- Снова происходит перерендер, но в этот раз эффект не вызывается, так как его единственная зависимость query не изменилась
Пошаговый туториал: https://www.robinwieruch.de/react-hooks-fetch-data
Здесь все подробно разобрано:
- Почему в useEffect нельзя передавать асинхронную функцию
- Зачем нужен массив зависимостей и как он работает
- Зачем используется переменная ignore внутри эффекта (спойлер: чтобы не выводить данные предыдущего запроса, если после него уже отправлен новый)
- Добавление индикатора загрузки
- Обработка ошибок загрузки
- Добавление формы (form) и обработка события onSubmit
Кроме того описан пользовательский хук для извлечения данных useDataApi. Он принимает полный урл запроса, поэтому может работать с любым API. Этот хук инкапсулирует логику запроса данных, индикатора загрузки и обработки ошибок запроса.
Хук useDataApi на гитхабе: https://github.com/the-road-to-learn-react/use-data-api
Наконец в конце рассматривается кейс с заменой отдельных простых состояний (isError, isLoading, data) на единое сложное состояние с использованием хука useReducer. При этом в нужные моменты вызываются нужные события (FETCH_INIT, FETCH_SUCCESS, FETCH_FAILURE) с помощью метода dispatch, а редьюсер обрабатывает их и обновляет состояние.
#ссылки #хуки #примерыкода
CodeSandbox
zxn70rnkx - CodeSandbox
zxn70rnkx by gaearon using react, react-dom, react-scripts
Коллбэк-рефы в функциональных компонентах
Мы уже говорили о коллбэк-рефах здесь https://yangx.top/react_junior/42.
В двух словах: если в атрибут ref элемента передать функцию (вместо объекта, созданного методом React.createRef), она будет вызвана при монтировании этого элемента, а в качестве аргумента получит ссылку на него.
В функциональных компонентах так тоже можно делать, с одним условием - функция (коллбэк-реф) должна быть создана с помощью хука useCallback. В ином случае она будет меняться при каждом рендере.
#рефы #примерыкода #документация #хуки
Мы уже говорили о коллбэк-рефах здесь https://yangx.top/react_junior/42.
В двух словах: если в атрибут ref элемента передать функцию (вместо объекта, созданного методом React.createRef), она будет вызвана при монтировании этого элемента, а в качестве аргумента получит ссылку на него.
В функциональных компонентах так тоже можно делать, с одним условием - функция (коллбэк-реф) должна быть создана с помощью хука useCallback. В ином случае она будет меняться при каждом рендере.
#рефы #примерыкода #документация #хуки
Функции в списке зависимостей
Если мы указываем для хука список зависимостей (useEffect, useLayoutEffect, useMemo, useCallback, useImperativeHandle), в него должны войти все использованные значения, которые задействованы в потоке данных React, включая пропсы, состояние и их производные.
А что если одно из этих значений функция - внешняя по отношению к вызову хука? Нужно ли ее указывать в зависимостях к хуку useEffect. (см. прикрепленный скриншот)
С одной стороны - да, ведь она использует состояние count. Если count изменится, эффект должен быть вызван заново. Можно, конечно, указать в списке зависимостей сам count, но ведь функция foo может использовать еще какие-нибудь данные, можно что-то упустить.
С другой стороны, функция foo (ее идентичность) будет меняться при каждом рендере. Это создаст замкнутый круг:
- изменился count при клике на кнопку
- произошел перерендер
- функция foo создалась заново
- поэтому вызван эффект
- вызов foo изменяет состояние fooCount
- происходит перерендер
- функция foo создалась заново
- поэтому вызван эффект... 🤦♂️ (хотя не должен быть вызван, ведь count-то не изменился)
Варианты решения
👉 объявить foo снаружи компонента (при этом она не сможет ссылаться на пропсы и состояние)
👉 переместить foo внутрь эффекта (тогда она не будет пересоздаваться, и в зависимостях ее указывать не нужно)
👉 убедиться, что foo не использует никаких данных компонента, которые могут измениться при перерендере (и тогда не указывать ее в зависимостях)
👉 создать foo с использованием хука useCallback и указанием зависимостей (тогда ее идентичность не будет меняться между рендерами)
https://codepen.io/furrycat/pen/MWmKKwZ?editors=0011
#ошибки #примерыкода #хуки
Если мы указываем для хука список зависимостей (useEffect, useLayoutEffect, useMemo, useCallback, useImperativeHandle), в него должны войти все использованные значения, которые задействованы в потоке данных React, включая пропсы, состояние и их производные.
А что если одно из этих значений функция - внешняя по отношению к вызову хука? Нужно ли ее указывать в зависимостях к хуку useEffect. (см. прикрепленный скриншот)
С одной стороны - да, ведь она использует состояние count. Если count изменится, эффект должен быть вызван заново. Можно, конечно, указать в списке зависимостей сам count, но ведь функция foo может использовать еще какие-нибудь данные, можно что-то упустить.
С другой стороны, функция foo (ее идентичность) будет меняться при каждом рендере. Это создаст замкнутый круг:
- изменился count при клике на кнопку
- произошел перерендер
- функция foo создалась заново
- поэтому вызван эффект
- вызов foo изменяет состояние fooCount
- происходит перерендер
- функция foo создалась заново
- поэтому вызван эффект... 🤦♂️ (хотя не должен быть вызван, ведь count-то не изменился)
Варианты решения
👉 объявить foo снаружи компонента (при этом она не сможет ссылаться на пропсы и состояние)
👉 переместить foo внутрь эффекта (тогда она не будет пересоздаваться, и в зависимостях ее указывать не нужно)
👉 убедиться, что foo не использует никаких данных компонента, которые могут измениться при перерендере (и тогда не указывать ее в зависимостях)
👉 создать foo с использованием хука useCallback и указанием зависимостей (тогда ее идентичность не будет меняться между рендерами)
https://codepen.io/furrycat/pen/MWmKKwZ?editors=0011
#ошибки #примерыкода #хуки
Инициализация состояния
Хук useState может принимать функцию вместо дефолтного значения. Гарантируется, что эта функция будет вызвана всего один раз при первом рендере. Таким образом можно инициализировать сложные состояния - затратные операции будут выполнены лишь один раз.
#хуки #документация #важно
Хук useState может принимать функцию вместо дефолтного значения. Гарантируется, что эта функция будет вызвана всего один раз при первом рендере. Таким образом можно инициализировать сложные состояния - затратные операции будут выполнены лишь один раз.
#хуки #документация #важно
👍1
Передача коллбэков дочерним компонентам
Если вам не хочется передавать вниз по дереву компонентов кучу коллбэков для изменения разных полей состояния, созданных хуком useState, можно рассмотреть возможность использования useReducer. При этом у вас появляется лишь один коллбэк - dispatch, который к тому же гарантировано не изменяется между рендерами.
dispatch даже можно передать вниз с помощью контекста, чтобы избежать пробрасывания пропсов на несколько уровней.
#важно #документация #хуки
Если вам не хочется передавать вниз по дереву компонентов кучу коллбэков для изменения разных полей состояния, созданных хуком useState, можно рассмотреть возможность использования useReducer. При этом у вас появляется лишь один коллбэк - dispatch, который к тому же гарантировано не изменяется между рендерами.
dispatch даже можно передать вниз с помощью контекста, чтобы избежать пробрасывания пропсов на несколько уровней.
#важно #документация #хуки
Тестирование в React
Открываем новый большой раздел - тестирование React-приложений.
Компонентный подход, который используется в React, позволяет легко разделить приложение на отдельные модули - юниты. Следовательно, юнит-тестирование совершенно логично встраивается в процесс разработки. Мы можем тестировать каждый компонент изолированно от всего остального кода.
Так как речь идет о фронтенде и интерфейсах, тестировать придется не только логику, но и верстку. И экосистема React уже имеет готовые решения для этого.
Мы будем разбираться, как тестировать React-приложения с использованием библиотек Jest (исполнитель тестов) и React Testing Library (набор вспомогательных функций).
#документация #тестирование
Открываем новый большой раздел - тестирование React-приложений.
Компонентный подход, который используется в React, позволяет легко разделить приложение на отдельные модули - юниты. Следовательно, юнит-тестирование совершенно логично встраивается в процесс разработки. Мы можем тестировать каждый компонент изолированно от всего остального кода.
Так как речь идет о фронтенде и интерфейсах, тестировать придется не только логику, но и верстку. И экосистема React уже имеет готовые решения для этого.
Мы будем разбираться, как тестировать React-приложения с использованием библиотек Jest (исполнитель тестов) и React Testing Library (набор вспомогательных функций).
#документация #тестирование
Jest
Jest - это тестовый фреймворк для JavaScript-кода. Create React App использует Jest из коробки.
Возможности Jest
👉 подмена области рендеринга с помощью jsdom
тесты будут выполняться вне настоящего браузера, следовательно его поведение нужно имитировать.
👉 подмена функций
особенно удобно при получении данных через апи, позволяет избежать отправки реального запроса, а лишь сымитировать его, получив предсказуемые данные
👉 фиктивные модули
позволяет заменить сторонние модули, от которых зависит тестируемый компонент, если они неправильно работают в среде тестирования или вообще не нужны для тестирования
👉 фиктивные таймеры
позволяют контролировать (например, ускорять) функции, связанные со временем
#документация #тестирование
Jest - это тестовый фреймворк для JavaScript-кода. Create React App использует Jest из коробки.
Возможности Jest
👉 подмена области рендеринга с помощью jsdom
тесты будут выполняться вне настоящего браузера, следовательно его поведение нужно имитировать.
👉 подмена функций
особенно удобно при получении данных через апи, позволяет избежать отправки реального запроса, а лишь сымитировать его, получив предсказуемые данные
👉 фиктивные модули
позволяет заменить сторонние модули, от которых зависит тестируемый компонент, если они неправильно работают в среде тестирования или вообще не нужны для тестирования
👉 фиктивные таймеры
позволяют контролировать (например, ускорять) функции, связанные со временем
#документация #тестирование
jestjs.io
Тестирование в React: подготовка и завершение
Чтобы протестировать компонент, его нужно "отрендерить" в среде исполнения - создать элемент-контейнер для монтирования компонента, а после завершения теста удалить его. Для этих действий используются функции фреймворка Jest:
- beforeEach (создание контейнера)
- afterEach (очистка и удаление контейнера)
Для очистки контейнера можно использовать метод ReactDOM.unmountComponentAtNode.
#документация #тестирование
Чтобы протестировать компонент, его нужно "отрендерить" в среде исполнения - создать элемент-контейнер для монтирования компонента, а после завершения теста удалить его. Для этих действий используются функции фреймворка Jest:
- beforeEach (создание контейнера)
- afterEach (очистка и удаление контейнера)
Для очистки контейнера можно использовать метод ReactDOM.unmountComponentAtNode.
#документация #тестирование
Утилиты для тестирования
Пакет react-dom предоставляет набор утилитарных функция для тестирования компонентов - react-dom/test-utils.
Раздел в документации (рус.): https://ru.reactjs.org/docs/test-utils.html
- act - имитация рендера компонента
- isElement(element) - проверка на React-элемент
- isElementOfType(element, componentClass) - проверка на тип элемента
- isDOMComponent(instance) - проверка на DOM-элемент
- isCompositeComponent(instance) - проверка на пользовательский компонент (классовый или функциональный, не важно)
- isCompositeComponentWithType(instance, componentClass) - проверка на тип пользовательского компонента
- findAllInRenderedTree(tree, testCallback) - поиск компонентов в дереве с помощью коллбэка (должен вернуть true или false)
- scryRenderedDOMComponentsWithClass(tree, className) - поиск DOM-элементов с указанным классом в дереве
- findRenderedDOMComponentWithClass(tree, className) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- scryRenderedComponentsWithType(tree, componentClass) - поиск компонентов с указанным классом
- findRenderedComponentWithType(tree, componentClass) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- renderIntoDocument(element)
- Simulate.{eventName}(element,[eventData]) - симулировать отправку события
#документация #тестирование
Пакет react-dom предоставляет набор утилитарных функция для тестирования компонентов - react-dom/test-utils.
Раздел в документации (рус.): https://ru.reactjs.org/docs/test-utils.html
- act - имитация рендера компонента
- isElement(element) - проверка на React-элемент
- isElementOfType(element, componentClass) - проверка на тип элемента
- isDOMComponent(instance) - проверка на DOM-элемент
- isCompositeComponent(instance) - проверка на пользовательский компонент (классовый или функциональный, не важно)
- isCompositeComponentWithType(instance, componentClass) - проверка на тип пользовательского компонента
- findAllInRenderedTree(tree, testCallback) - поиск компонентов в дереве с помощью коллбэка (должен вернуть true или false)
- scryRenderedDOMComponentsWithClass(tree, className) - поиск DOM-элементов с указанным классом в дереве
- findRenderedDOMComponentWithClass(tree, className) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- scryRenderedComponentsWithType(tree, componentClass) - поиск компонентов с указанным классом
- findRenderedComponentWithType(tree, componentClass) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- renderIntoDocument(element)
- Simulate.{eventName}(element,[eventData]) - симулировать отправку события
#документация #тестирование
ru.legacy.reactjs.org
Утилиты для тестирования – React
JavaScript-библиотека для создания пользовательских интерфейсов
Тестирование простого компонента
Самый примитивный пример тестирования компонента:
https://codesandbox.io/s/testing-react-junior-i6ldm?file=/src/Hello.test.js
- beforeEach (метод Jest) - создание контейнера для рендера
- ReactDOM.unmountComponentAtNode - размонтирование React-компонента из контейнера после выполнения теста
- afterEach (метод Jest) - удаление контейнера после выполнения теста
- it (метод Jest) - объявление блока тестов
- act (вспомогательная функция из пакета react-dom/test-utils) - обеспечивает завершенность процесса рендеринга компонента перед выполнением тестов
- ReactDOM.render - рендерит компонент
- expect (метод Jest) - осуществляет проверку некоторого утверждения.
Jest предоставляет множество различных проверок (полный список здесь https://jestjs.io/docs/expect), мы воспользовались для примера самой простой - toBe, которая проверяет равенство примитивных значений или ссылок на объекты.
Результаты выполнения тестов можно увидеть во вкладке Tests.
#документация #примерыкода #тестирование
Самый примитивный пример тестирования компонента:
https://codesandbox.io/s/testing-react-junior-i6ldm?file=/src/Hello.test.js
- beforeEach (метод Jest) - создание контейнера для рендера
- ReactDOM.unmountComponentAtNode - размонтирование React-компонента из контейнера после выполнения теста
- afterEach (метод Jest) - удаление контейнера после выполнения теста
- it (метод Jest) - объявление блока тестов
- act (вспомогательная функция из пакета react-dom/test-utils) - обеспечивает завершенность процесса рендеринга компонента перед выполнением тестов
- ReactDOM.render - рендерит компонент
- expect (метод Jest) - осуществляет проверку некоторого утверждения.
Jest предоставляет множество различных проверок (полный список здесь https://jestjs.io/docs/expect), мы воспользовались для примера самой простой - toBe, которая проверяет равенство примитивных значений или ссылок на объекты.
Результаты выполнения тестов можно увидеть во вкладке Tests.
#документация #примерыкода #тестирование
Mock-функции в Jest
Mock-функция - это фиктивная реализация некоторого интерфейса, предназначенная для упрощения тестирования.
Создать такую функцию можно с помощью метода jest.fn(). В качестве необязательного аргумента можно передать реализацию мок-функции (которая будет вызываться при обращении к мок-функции). Реализацию можно также установить после создания, с помощью метода mockFn.mockImplementation(fn).
Подробнее о моках в документации Jest: https://jestjs.io/docs/mock-function-api
У мок-функций есть ряд полезных методов, позволяющих, например, посмотреть все вызовы.
Кроме того, передав мок-функцию в метод expect, мы получаем еще ряд полезных утверждений вроде toHaveBeenCalled().
Помимо простых моков есть еще шпионы (spies). Они имеют интерфейс мок-функции и отслеживают вызовы некоторого существующего метода. Создать шпиона можно с помощью метода jest.spyOn(object, methodName) - он будет отслеживать вызовы object[methodName]. Для них также можно переопределить существующую функциональность с помощью mockFn.mockImplementation().
Например, можно установить шпиона для метода fetch:
Mock-функция - это фиктивная реализация некоторого интерфейса, предназначенная для упрощения тестирования.
Создать такую функцию можно с помощью метода jest.fn(). В качестве необязательного аргумента можно передать реализацию мок-функции (которая будет вызываться при обращении к мок-функции). Реализацию можно также установить после создания, с помощью метода mockFn.mockImplementation(fn).
Подробнее о моках в документации Jest: https://jestjs.io/docs/mock-function-api
У мок-функций есть ряд полезных методов, позволяющих, например, посмотреть все вызовы.
Кроме того, передав мок-функцию в метод expect, мы получаем еще ряд полезных утверждений вроде toHaveBeenCalled().
Помимо простых моков есть еще шпионы (spies). Они имеют интерфейс мок-функции и отслеживают вызовы некоторого существующего метода. Создать шпиона можно с помощью метода jest.spyOn(object, methodName) - он будет отслеживать вызовы object[methodName]. Для них также можно переопределить существующую функциональность с помощью mockFn.mockImplementation().
Например, можно установить шпиона для метода fetch:
jest.spyOn(global, "fetch").mockImplementation(setupFetchStub)#тестирование #jest
jestjs.io
The Jest Object · Jest
The jest object is automatically in scope within every test file. The methods in the jest object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via import from '@jest/globals'.
Замена методов
Некоторые функции (вроде запросов данных) могут вызывать проблемы при тестировании: они долго выполняются, могут прерываться неожиданными ошибками, которые не имеют отношения к тестам, а также возвращают неопределенные данные.
Такие функции можно заменить шпионами Jest (jest.spyOn) и установить для них фиктивную реализацию.
https://codesandbox.io/s/mock-methods-react-junior-0oxgq?file=/src/Pokemon.test.js
Примечание: в примере запрос данных осуществляется с помощью метода Utils.fetch и шпион устанавливается именно для него:
Это сделано для демонстрации, так как в codesandbox не получилось установить шпиона для global.fetch. В нормальной среде выполнения должно быть:
#документация #тестирование #примерыкода
Некоторые функции (вроде запросов данных) могут вызывать проблемы при тестировании: они долго выполняются, могут прерываться неожиданными ошибками, которые не имеют отношения к тестам, а также возвращают неопределенные данные.
Такие функции можно заменить шпионами Jest (jest.spyOn) и установить для них фиктивную реализацию.
https://codesandbox.io/s/mock-methods-react-junior-0oxgq?file=/src/Pokemon.test.js
Примечание: в примере запрос данных осуществляется с помощью метода Utils.fetch и шпион устанавливается именно для него:
jest.spyOn(Utils, 'fetch')
Это сделано для демонстрации, так как в codesandbox не получилось установить шпиона для global.fetch. В нормальной среде выполнения должно быть:
jest.spyOn(global, 'fetch')
#документация #тестирование #примерыкода
CodeSandbox
Mock methods. React Junior - CodeSandbox
Mock methods. React Junior by furrycat.web using react, react-dom, react-scripts
Фиктивные модули
Создать фиктивную реализацию можно не только для функции, но и для целого модуля.
Для этого предназначен метод jest.mock(moduleName, factory, options).
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#mocking-modules
#документация #тестирование #jest
Создать фиктивную реализацию можно не только для функции, но и для целого модуля.
Для этого предназначен метод jest.mock(moduleName, factory, options).
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#mocking-modules
#документация #тестирование #jest
jestjs.io
The Jest Object · Jest
The jest object is automatically in scope within every test file. The methods in the jest object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via import from '@jest/globals'.
События при тестировании
Создать событие на элементе можно стандартным методом dispatchEvent, передав ему объект события.
Важно: Объекту события нужно передать опцию
#документация #тестирование
Создать событие на элементе можно стандартным методом dispatchEvent, передав ему объект события.
Важно: Объекту события нужно передать опцию
bubbles: true
, чтобы обработчик событий React его увидел и автоматически передал в корень документа.#документация #тестирование
Фиктивные таймеры
Jest предоставляет моки и для таймеров (setTimeout, setInterval): https://jestjs.io/ru/docs/timer-mocks.
👉 jest.useFakeTimers() и jest.useRealTimers() позволяют переключить режим работы таймеров.
👉 jest.advanceTimersByTime(ms) сдвигает время на указанное количество милисекунд.
Есть еще пара методов, которые могут пригодиться: runAllTimers и runOnlyPendingTimers.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#timers
#документация #тестирование #jest
Jest предоставляет моки и для таймеров (setTimeout, setInterval): https://jestjs.io/ru/docs/timer-mocks.
👉 jest.useFakeTimers() и jest.useRealTimers() позволяют переключить режим работы таймеров.
👉 jest.advanceTimersByTime(ms) сдвигает время на указанное количество милисекунд.
Есть еще пара методов, которые могут пригодиться: runAllTimers и runOnlyPendingTimers.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#timers
#документация #тестирование #jest
Снапшоты
Jest позволяет делать снапшоты - сохранять "снимки" данных. Иначе говоря, сохраняется результат рендера компонента. При внесении изменений этот "снимок" изменится.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#snapshot-testing
#документация #тестирование #jest
Jest позволяет делать снапшоты - сохранять "снимки" данных. Иначе говоря, сохраняется результат рендера компонента. При внесении изменений этот "снимок" изменится.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#snapshot-testing
#документация #тестирование #jest
ru.legacy.reactjs.org
Рецепты тестирования – React
JavaScript-библиотека для создания пользовательских интерфейсов