Пользовательский интерфейс Keboola Connection (keboola/kbc-ui) восходит к 2015 году, а некоторые компоненты React написаны на Coffeescript. Мы решили переписать эти компоненты на JSX.

Поскольку не существует конвертера, способного выполнять эту работу автоматически (или с удовлетворительным результатом), мы согласились делать это вручную, небольшими шагами. Когда нам нужно что-то изменить (или исправить) в .coffee файле, мы переписываем его в .jsx, если это возможно.

Давайте назовем компонент React черным ящиком. Этот черный ящик отвечает за одну работу — визуализацию дерева React (в основном HTML). Этот так называемый HTML-вывод может отличаться в зависимости от переданных реквизитов, поэтому мы хотим стабилизировать это поведение и быть уверенными, что оно не изменится со временем (особенно при переписывании на JSX).

Итак, как мы это делаем? С написанием тестов.

Мы используем библиотеку Jest для запуска тестов. В этом случае одна специальная функция поможет нам протестировать упомянутое выше поведение черного ящика — Тестирование моментальных снимков. работает как прежде.

Решил переписать CurrentUser компонент. Он отвечает за отображение информации о пользователе (аватар, имя и адрес электронной почты) и простое «выпадающее меню» (сейчас это не так важно).

Поэтому я написал для него тест.

import React from 'react';
import CurrentUser from './CurrentUser';
import { fromJS } from 'immutable';

// few variables defined here, used later to pass as props

describe('<CurrentUser />', function() {
  it('should render 40x40 icon, with email, no admin links, no maintainers, dropup false (no mode passed)', function() {
    shallowSnapshot(
      <CurrentUser
        user={user}
        maintainers={fromJS([])}
        urlTemplates={urlTemplates}
        canManageApps={false}
        dropup={true}
      />
    );
  });
  // more tests here, not mentioned for simplicity
});

Функция shallowSnapshot отвечает за рендеринг снимка и сравнение его с существующим. Первый запуск теста создаст снимок (файл .snap), который будет сохранен в каталоге __snapshots__.

Вот предварительный просмотр снимка:

exports[`<CurrentUser /> should render 40x40 icon, with email, no admin links, no maintainers, dropup false (no mode passed) 1`] = `
<div
  className="kbc-user"
  onClick={[Function]}>
  <img
    className="kbc-user-avatar"
    height={40}
    src="/user.png"
    width={40} />
  <div>
    <strong>
      dev user
    </strong>
    <DropdownButton
    ...
</div>
`;

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

Мы запускаем этот режим, запуская команду yarn tdd (наш псевдоним для jest с параметром --watch).

А дальше начинается скучная часть, с этого момента мы можем начать переписывать на JSX.

После нескольких итераций, когда мы увидели, что тесты не пройдены, мы должны получить новый файл JSX и увидеть, что тесты снова пройдены.

TL;DR

  1. Напишите тесты и убедитесь, что вы охватили достаточное количество случаев, особенно случаев без передачи необязательных реквизитов.
  2. Запустите Jest в режиме просмотра (при первом запуске создаются снимки)
  3. Переписывайте, пока не увидите, что тесты снова проходят
  4. Выгода! :)