Я заметил, что в сети не так много руководств по тестированию компонентов OpenLayers React. Для большого проекта, над которым я работал, мне пришлось включить OpenLayers в React, и когда наступил этап тестирования, я столкнулся с несколькими препятствиями, которые нужно было немного поэкспериментировать, чтобы их преодолеть. В этом посте я хочу поделиться с вами тем, как я настроил минимальную среду тестирования для компонента OpenLayers, визуализируемого с помощью React.

Это руководство основано на тестовой настройке, которую я сделал для создания приложения React на основе Mocha, Chai, Enzyme, и предполагает, что у вас уже есть тестовая настройка. Вот как вы можете сделать свою собственную. Если вы хотите использовать другой механизм тестирования (например, Jest), вы можете почерпнуть здесь вдохновение, но есть части, в которых два средства запуска тестов существенно различаются, и вы можете поискать ресурсы для своей конфигурации в другом месте. Я также сделал «репозиторий GitHub с готовым примером.

  1. Установить/настроить jsdom и холст

jsdom — это утилита для тестирования, которая создаст экземпляр виртуального браузера, реализующего стандарт HTML в глобальном виртуальном документе, в котором мы можем визуализировать/монтировать наши компоненты для тестирования. Jsdom требуется, потому что OpenLayers при его создании ищет HTML-элементы, такие как <canvas>, и нам нужен браузер, в данном случае виртуальный, для тестирования библиотеки. Для установки jsdom сделаем:

npm install jsdom --save-dev or yarn add jsdom -dev

jsdom поддерживает <canvas> как внешнюю зависимость, и ее необходимо установить отдельно и включить в наш HTML-документ. Пакет можно найти здесь, а установить его можно так:

npm install canvas --save-dev or yarn add canvas -dev

После того, как мы установили jsdom, нам нужно создать файл, в котором мы создадим экземпляр нашего HTML document в глобальной области видимости. Это должно произойти до того, как мы начнем наши тесты, поскольку OpenLayers требует присоединения HTML, если мы хотим его протестировать. Следующий файлsetup.js подойдет для работы, это то же самое, что вы найдете на странице документации Enzyme для Jsdom (за исключением требования к холсту).

Мы поместим файл в корневую папку нашего приложения React.

|--test-openlayers
      |--src
         |--test
            App.test.js
          App.css
          App.js
          index.js
          index.css
          logo.js
          logo.svg
          ...
   babel.config.js
   setup.js
   ...

После того, как мы создали этот файл, он потребуется нам при запуске теста с флагом Mocha require. Точно так же, как мы делали это для Babel в нашем предыдущем уроке, мы добавим--require setup.jsк нашему тестовому сценарию в package.json.

2. Установите и включите OpenLayers в наше приложение

OpenLayers — хорошо известная и используемая картографическая библиотека в среде веб-ГИС. Это было вокруг и я использовал в течение долгого времени. Для тех, кто хочет узнать об этом больше, здесь находится официальная страница. Давайте установим его в наше приложение React:

npm install ol --save or yarn add ol

После его установки мы создадим простую карту как компонент React, став дочерним компонентом нашего основного компонента App. Затем мы добавим новый файл Map.js и создадим там новый экземпляр объекта карты OpenLayers следующим образом:

Затем мы импортируем и используем наши MapComponentв наших App

Нам также нужно будет импортировать таблицу стилей Openlayers. Мы можем импортировать его в глобальной области видимости, добавив ссылку на нашу главную страницу в public/index.html.

<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">

Поскольку мы собираемся добавить больше компонентов на страницу нашего приложения, мы уменьшим размер карты и разместим ее в центре экрана, используя свойства css flexbox. Измените файл App.css, в частности .app class, следующим образом (см. поддержку старых браузеров для display: flex онлайн):

.App {
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
}

Мы также уменьшим размер карты до половины ее текущей ширины и высоты, Map.js непосредственно перед тем, как метод render() изменит объявление встроенного стиля:

render() {
    const styles = { height: '50%', width: '50%'}
    return(
        <div style={styles} ref={this.setMapRef}></div>
    )
}

3. Добавьте на карту некоторые функции

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

У нас будет начальное состояние, напрямую связанное с центром карты, которые (x, y) соответствуют первому предварительно выбранному городу в раскрывающемся списке. Состояние и функция, которая отвечает на выпадающие onChange события, будут храниться в нашем App компоненте, родительском. MapComponent является потомком App, он получит координаты выбранного города в качестве реквизита, переданного от родителя. LocationsSelect — это дочерний компонент другого приложения, функция события onChange в родительском компоненте передается ему в качестве реквизита. Когда пользователь выбирает новый город, координаты отправляются из LocationsSelect в App, что обновляет его состояние и свойство представления карты center в методе componentWillUpdate, заставляя карту перемещаться в выбранное место.

Мы добавим еще два компонента LocationsSelect и MapComponent; первый останется в нашем файле App.js, а для второго мы создадим отдельный файл Map.js, так как позже мы добавим еще одно поведение. Структура папки нашего пакета будет такой:

|--test-openlayers
      |--src
         |--test
            App.test.js
         App.css
         App.js
         index.js
         index.css
         logo.js
         logo.svg
         Map.js
         ...
      babel.config.js
      setup.js
      ...

И наши файлы App.js и Map.js станут такими:

Наше приложение React Openlayers теперь будет выглядеть и действовать следующим образом:

4. Транспиляция и полифилл библиотеки ol

Пакет javascript Openlayers под названием ol в версии 5.3.0, используемой для этого руководства, написан на ES6/ES2015. Поскольку наши тестируемые компоненты импортируют этот пакет, а Mocha не поддерживает ES6/ES2015, нам придется транспилировать node_modules/ol перед запуском любого теста в нашем приложении. Для этого мы будем использовать @babel/register, как и в предыдущем примере, но на этот раз мы будем использовать флаг ignore в нашей конфигурации. Это заставит Babel транспилировать только модуль ol и подмодули перед запуском любого теста. Модули ol используют некоторые функции ES6, как описано здесь, нам нужно будет установить @babel/polyfill и потребовать их перед запуском тестов.

Сначала мы установим @babel/polyfill :

npm install @babel/polyfill --save-dev or yarn add @babel/polyfill -dev

Мы переместим нашу тестовую конфигурацию в новый файл с именем babel-register.js. Здесь нам потребуются наши @babel/polyfill и @babel/register со свойством ignore. Это свойство представляет собой массив, содержащий регулярное выражение /node_modules\/(?!(ol)\/)/, которое указывает Babel транспилировать только файлы только в подпапке ol папки node_modules , имеющей указанное extensions , файл будет выглядеть следующим образом:

и он будет размещен в корневом каталоге нашего приложения:

|--test-openlayers
      |--src
         |--test
            App.test.js
         ...
         index.js
         Map.js
         ...
      babel.config.js
      babel-register.js
      setup.js
      ...

Прежде чем перейти к следующей части, нам нужно будет изменить нашу запись «test» в сценариях в package.json, чтобы отразить новую тестовую конфигурацию, которую мы только что создали.

Если вы находитесь в Linux, это будет

"test": "NODE_ENV=test mocha --require babel-register.js --require ignore-styles --require setup.js  src/test/*.test.js"

В винде будет

"test": "set NODE_ENV=test&& mocha --require babel-register.js --require ignore-styles --require setup.js  src/test/*.test.js",

5. Проверка объекта карты (часть I)

Тестовый верстак теперь построен, у нас есть все необходимое для начала тестирования наших компонентов реакции OpenLayers, мы начнем с первого поведения, мы проверим, меняет ли карта свои координаты, когда пользователь меняет выбор в раскрывающемся компоненте LocationsSelection. В этом наборе тестов мы будем использовать функцию mount Enzyme, которая будет отображать виртуальную карту в нашем виртуальном браузере, а Chai будет использоваться в качестве нашей библиотеки утверждений.

В первой тестовой спецификации мы просто печатаем строковое HTML-представление компонента раскрывающегося списка в браузере jsdom, сравнивая его с ожидаемым представлением.

Во второй тестовой спецификации мы протестируем OpenLayers в нашем MapComponent, мы сначала проверяем, был ли компонент отрендерен, затем мы имитируем событие изменения с помощью метода simulate Enzyme на компоненте LocationsSelection. Обратите внимание, как мы вызываем этот метод: первый аргумент — это строка, определяющая тип события, второй — фиктивный объект события, содержащий только те биты, которые нам нужны для передачи функции panToLocation. Для тестирования поведения карты нам нужны не все свойства, а только индекс выбранного элемента target -> selectedOptions -> index. Метод panToLocation компонента App вычислит новые координаты. Наконец, мы проверяем, действительно ли карта переместилась в нужное место. Мы создаем экземпляр MapComponent для доступа к объекту карты olMap OpenLayers, получаем координаты центра текущего вида и сравниваем их с координатами выбранного элемента (преобразованными в EPSG:3857). Теперь давайте откроем наш терминал и сделаем npm test или yarn run test, это то, что вы должны увидеть.

В приведенном выше примере мы тестировали непосредственно объект карты ol, передавая свойство, которое изменяет его представление. Есть много других тестов, которые вы можете выполнить на объекте карты (например, правильно ли карта отображается, правильно ли центрируется/масштабируется карта при запуске и т. д.). Если вы поняли, как работает логика тестирования, и вы чувствуете себя достаточно уверенно, чтобы начать самостоятельное тестирование, то то, что мы сделали до сих пор, является хорошим местом для начала. Если вы хотите последовать другому примеру и расширить свои знания, нажмите здесь или на изображение ниже, в следующей части мы собираемся протестировать объект ol/interaction.