После довольно удачной пробы пера с Ember Octane я решил (точнее мы с гуглотранслейтом решили) замахнутся на святое перевод туториала из официального руководства Ember.js


Как вы увидите из текста, данный туториал рассчитан на самых маленьких начинающих программистов. Что не мешает ему служить опытным бойцам прекрасной отправной точкой для знакомства фреймворком. Для полного прохождения этой игры туториала вам понадобится 1-2 часа времени. После этого вы сможете оценить Ember.js в его последней редакции Octane без необходимости читать обзоры позапрошлогодней свежести


Список тем, которые покрывает туториал внушает:


  • Использование Ember CLI
  • Навигация по структуре файлов и папок приложения Ember
  • Создание и связь между страницами
  • Шаблоны (templates) и компоненты
  • Автоматизированное тестирование
  • Работа с данными сервера
  • Динамические сегменты в маршрутах
  • Сервисы в Ember
  • Библиотека Ember Data
  • Адаптеры и сериализаторы
  • Паттерн компонента-провайдера

Если вы согласны, что это вкуснота стоит траты 1-2 часов, добро пожаловать под кат!


От переводчика:
Так как Хабр не может корректно отобразить hbs я вставлял картинки. Воспользуйтесь текстом оригинала, чтобы копировать кодовые вставки. Сорри за неудобства.

Также оригинальный туториал состоит из двух частей, но из-за объема я разбил первую часть на две: часть 1.1 и часть 1.2. Надеюсь, что вторая часть будет переводиться целиком и тогда я дам ей нумерацию часть 2. Также надеюсь, что это не приведет к путанице)

На русском про Ember можно спрашивать в телеграмм канале ember_js

Вступление


Добро пожаловать в мир Ember!


В этом туториале мы будем использовать Ember для создания приложения Super Rentals. Это будет веб-сайт для просмотра интересных мест, где можно остановиться во время вашего следующего отпуска. Проверьте готовое приложение, чтобы получить представление о масштабах проекта.


image


Попутно вы узнаете все, что вам нужно знать для создания базового приложения Ember. Если вы застряли в какой-то момент во время урока, не стесняйтесь скачать исходники для полного рабочего примера.


Этот урок состоит из двух частей. Первая часть охватывает следующие основные понятия:


  • Использование Ember CLI
  • Навигация по структуре файлов и папок приложения Ember
  • Создание и связь между страницами
  • Шаблоны и компоненты
  • Автоматизированное тестирование
  • Работа с данными сервера

Во вторая части урока мы перейдем на следующий уровень, используя уже изученные концепции.


Генерация нового проекта


В этой части вы будете устанавливать Ember CLI, использовать его для создания нового проекта Ember и добавлять базовые шаблоны и стили в свое новое приложение. К концу части у вас должна появиться целевая страница с изображением милого профессора Томстера:
image


Создавая эту страницу, вы научитесь:


  • Устанавливать Ember CLI
  • Создавать новое приложение Ember с Ember CLI
  • Запускать и останавливать сервер разработки
  • Редактировать файлы и видеть сразу видеть результат (live reload)
  • Работать с HTML, CSS и ресурсами в приложении Ember

Установка Ember CLI


Вы можете установить последнюю версию Ember CLI, выполнив следующую команду:


$ npm install -g ember-cli 

Чтобы убедиться, что ваша установка прошла успешно, запустите:


$ ember --version
ember-cli: 3.15.0
node: 12.8.1
os: linux x64

Если отображается номер версии, вы готовы к работе.


Создание нового приложения Ember с помощью Ember CLI


Мы можем создать новый проект, используя команду Ember CLI new. Используйте паттерн ember new <project-name>. В нашем случае название проекта будет super-rentals:


$ ember new super-rentals
installing app
Ember CLI v3.15.0

Creating a new Ember app in /home/runner/work/super-rentals-tutorial/super-rentals-tutorial/dist/code/super-rentals:
  create .editorconfig
  create .ember-cli
  create .eslintignore
  create .eslintrc.js
  create .template-lintrc.js
  create .travis.yml
  create .watchmanconfig
  create README.md
  create app/app.js
  create app/components/.gitkeep
  create app/controllers/.gitkeep
  create app/helpers/.gitkeep
  create app/index.html
  create app/models/.gitkeep
  create app/router.js
  create app/routes/.gitkeep
  create app/styles/app.css
  create app/templates/application.hbs
  create config/environment.js
  create config/optional-features.json
  create config/targets.js
  create ember-cli-build.js
  create .gitignore
  create package.json
  create public/robots.txt
  create testem.js
  create tests/helpers/.gitkeep
  create tests/index.html
  create tests/integration/.gitkeep
  create tests/test-helper.js
  create tests/unit/.gitkeep
  create vendor/.gitkeep

Installing packages... This might take a couple of minutes.
npm: Installing dependencies ...
npm: Installed dependencies

Initializing git repository.
Git: successfully initialized.

Successfully created project super-rentals.
Get started by typing:

  $ cd super-rentals
  $ npm start

Happy coding!

Это должно было создать для нас новую папку под названием super-rentals. Мы можем перейти к нему с помощью команды cd.


$ cd super-rentals

В оставшейся части туториала все команды должны выполняться в папке super-rentals. Эта папка имеет следующую структуру:


super-rentals
+-- app
¦   +-- components
¦   ¦   L-- .gitkeep
¦   +-- controllers
¦   ¦   L-- .gitkeep
¦   +-- helpers
¦   ¦   L-- .gitkeep
¦   +-- models
¦   ¦   L-- .gitkeep
¦   +-- routes
¦   ¦   L-- .gitkeep
¦   +-- styles
¦   ¦   L-- app.css
¦   +-- templates
¦   ¦   L-- application.hbs
¦   +-- app.js
¦   +-- index.html
¦   L-- router.js
+-- config
¦   +-- environment.js
¦   +-- optional-features.json
¦   L-- targets.js
+-- public
¦   L-- robots.txt
+-- tests
¦   +-- helpers
¦   ¦   L-- .gitkeep
¦   +-- integration
¦   ¦   L-- .gitkeep
¦   +-- unit
¦   ¦   L-- .gitkeep
¦   +-- index.html
¦   L-- test-helper.js
+-- vendor
¦   L-- .gitkeep
+-- .editorconfig
+-- .ember-cli
+-- .eslintignore
+-- .eslintrc.js
+-- .gitignore
+-- .template-lintrc.js
+-- .travis.yml
+-- .watchmanconfig
+-- README.md
+-- ember-cli-build.js
+-- package.json
+-- package-lock.json
L-- testem.js

15 directories, 32 files

По мере продвижения по уроку мы узнаем о целях этих файлов и папок. А пока, просто знайте, что большую часть времени мы будем работать в папке app.


Запуск и остановка сервера разработки


Ember CLI поставляется с множеством различных команд для различных задач разработки, таких как команда ember new которую мы видели ранее. Он также поставляется с сервером разработки, который мы можем запустить с помощью команды ember server :


$ ember server
building...

Build successful (9761ms) – Serving on http://localhost:4200/

Сервер разработки отвечает за компиляцию нашего приложения. Также в него встроен веб-сервер, поставляющий файлы браузеру. Загрузка может занять некоторое время. Как только он заработает, откройте ваш любимый браузер и перейдите по адресу http://localhost:4200. Вы должны увидеть следующую страницу приветствия:
welcome page


Зои поясняет:



Адрес localhost в URL означает, что вы можете получить доступ к серверу разработки только с вашего локального компьютера. Если вы хотите поделиться своей работой со всем миром, вам придется развернуть свое приложение в общедоступном Интернете. Мы расскажем, как это сделать, во второй части урока.

Вы можете выйти из сервера разработки в любое время, набрав Ctrl + C (для MacOS Cmd + C) в окне терминала, где работает ember server. То есть, нажимая клавишу «C» на клавиатуре, одновременно удерживая клавишу «Ctrl». Как только он остановился, вы можете запустить его снова с помощью той же команды ember server. Мы рекомендуем открыть два окна терминала: одно для запуска сервера в фоновом режиме, другое для ввода других команд консоли Ember.


Редактирование файлов и живая перезагрузка (live reload)


Сервер разработки имеет функцию под названием live reload, которая отслеживает изменения файлов в вашем приложении, автоматически перекомпилирует все и обновляет все открытые страницы браузера. Это очень удобно при разработке, поэтому давайте попробуем!


Как указывалось в тексте на странице приветствия, исходный код страницы находится в app/templates/application.hbs. Давайте попробуем отредактировать этот файл и заменить его собственным контентом:
hbs hello world
Вскоре после сохранения файла ваш браузер должен автоматически обновиться и передать наши поздравления всему миру. Супер!
browser hello world
Когда вы закончите экспериментировать, удалите файл app/templates/application.hbs. Нам это не понадобится какое-то время, поэтому давайте начнем заново. Мы можем добавить его позже, когда это понадобится.


Опять же, если у вас по-прежнему открыта вкладка браузера, ваша вкладка автоматически повторно отобразит пустую страницу, как только вы удалите файл. Это отражает тот факт, что у нас больше нет шаблона приложения в нашем приложении.


Работа с HTML, CSS и активами в приложении Ember


Создайте файл app/templates/index.hbs и вставьте следующую разметку.
hbs index
Если вы думаете: «Эй, это похоже на HTML!», То вы абсолютно правы! В своей простейшей форме шаблоны Ember — это просто HTML. Если вы уже знакомы с HTML, вы должны чувствовать себя здесь как дома.


Конечно, в отличие от HTML, шаблоны Ember могут сделать гораздо больше, чем просто отображать статический контент. Мы скоро увидим это в действии.


После сохранения файла ваша вкладка браузера должна автоматически обновиться, показывая нам приветственное сообщение, над которым мы только что работали.


html unstyled


Прежде чем делать что-то еще, давайте добавим немного стиля в наше приложение. Мы тратим достаточно времени, глядя на экран компьютера, поэтому мы должны защитить свое зрение от голой HTML разметки!


К счастью, наш дизайнер прислал нам немного CSS для использования, поэтому мы можем загрузить файл таблицы стилей и скопировать его в app/styles/app.css. В этом файле есть все стили, которые нам нужны для создания остальной части приложения.


@import url(https://fonts.googleapis.com/css?family=Lato:300,300italic,400,700,700italic);

/**
 * Base Elements
 */

* {
  margin: 0;
  padding: 0;
}

body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
div,
span,
a,
button {
  font-family: 'Lato', 'Open Sans', 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif;
  line-height: 1.5;
}

body {
  background: #f3f3f3;
}

/* ...snip... */

Если вы знакомы с CSS, не стесняйтесь настраивать эти стили по своему вкусу! Просто имейте в виду, что вы можете увидеть некоторые визуальные различия в будущем, если вы решите это сделать.


Когда вы будете готовы, сохраните файл CSS; наш надежный сервер разработки должен сразу же его заберет и обновить нашу страницу. Нет больше голого HTML контента!


orientation styled


Чтобы соответствовать макету от нашего дизайнера, нам также нужно скачать изображение teaching-tomster.png, на которое ссылается наш CSS-файл:


.tomster {
  background: url(../assets/images/teaching-tomster.png);
  /* ...snip... */
}

Как мы узнали ранее, конвенция Ember заключается в размещении вашего исходного кода в папке app. Для других ресурсов, таких как изображения и шрифты, существует папка public. Мы будем следовать этому соглашению, загрузив файл изображения и сохранив его в public/assets/images/teaching-tomster.png .


И Ember CLI, и сервер разработки понимают эти соглашения о папках и автоматически делают эти файлы доступными для браузера.


Вы можете подтвердить это, перейдя по http://localhost:4200/assets/images/teaching-tomster.png. Изображение также должно отображаться на странице приветствия, над которой мы работаем. Если при обновлении изображение все-таки не появилось, попробуйте выполнить обновление вручную, чтобы браузер подобрал новый файл.
styled-with-tomster


Создание страниц приложения


В этой части вы создадите первые несколько страниц вашего приложения Ember и установите ссылки между ними. К концу этой главы у вас должно появиться две новые страницы — страница о странице и страница контактов. Эти страницы будут связаны с вашей стартовой страницей:
index-with-link
about-with-link
contact-with-link


Создавая эти страницы, вы узнаете об:


  • Определении маршрутов (route)
  • Использовании шаблонов маршрутов
  • Настройке URL
  • Связывании страниц с компонентом <LinkTo>
  • Передаче аргументов и атрибутов компонентам

Определение маршрутов


После создания нашей первой страницы, давайте добавим еще одну!


На этот раз мы хотели бы, чтобы страница размещалась по URL-адресу /about. Для этого нам нужно сообщить Ember о нашем плане добавить страницу в этом месте. В противном случае Ember будет считать, что мы посетили неверный URL!


Местом для управления доступными страницами является маршрутизатор. Откройте app/router.js и внесите следующие изменения:


router about


Это добавляет маршрут с именем «about», который по умолчанию обслуживается в URL-адресе /about.


Использование шаблонов маршрутов (route templates)


Теперь мы можем создать новый файл app/templates/about.hbs со следующим содержимым:


about hbs


Чтобы увидеть это в действии, перейдите по http://localhost:4200/about.


building-pages about


Вот и готова наша вторая страница!


Определение маршрутов с помощью пользовательских путей


Продолжаем! Давайте добавим нашу третью страницу. На этот раз все немного по-другому. Все в компании называют это «контактной» страницей. Тем не менее, старый веб-сайт, который мы заменяем, уже имеет аналогичную страницу, которая обслуживается по устаревшему URL-адресу /getting-in-touch.


Мы хотим сохранить существующие URL-адреса для нового веб-сайта, но нам не нужно вводить getting-in-touch всему новому коду! К счастью, мы можем поступить лучше:



Здесь мы добавили маршрут contact, но явно указали путь для маршрута. Это позволяет нам сохранить устаревший URL, но использовать новое, более короткое имя для маршрута, а также имя файла шаблона.


Говоря о шаблоне, давайте создадим и его. Мы добавим файл app/templates/contact.hbs с содержимым:



Ember придерживается жестких соглашений и разумных настроек по умолчанию — если бы мы начинали с нуля, мы бы не возражали против дефолтного URL /contact. Однако, если настройки по умолчанию не работают для нас, это не проблема. Мы можем настроить Ember для наших нужд!


После того как вы добавили маршрут и шаблон выше, у нас должна появиться новая страница по адресу http://localhost:4200/getting-in-touch.


contact


Создаем перекрестную навигацию на страницах используя компонент <LinkTo>


Мы приложили столько усилий, чтобы сделать эти страницы, но нам нужно, чтобы люди могли их найти! В Интернете для этого используют гиперссылки или для краткости просто ссылки.


Ember предлагает отличную поддержку для URL-адресов «из коробки». Мы можем просто связать наши страницы вместе, используя тег <a> с соответствующим href. Однако щелчок по этим ссылкам потребует от браузера полного обновления страницы, а это значит, что ему придется вернуться на сервер, чтобы получить страницу, а затем снова загрузить все с нуля.


С Ember мы можем добиться большего! Вместо простого старого тега <a> Ember предлагает альтернативу <LinkTo>. Например, вот как вы могли бы использовать его на страницах, которые мы только что создали:




Давайте разберем подробнее, что мы сейчас добавили.


<LinkTo> является примером компонента в Ember — вы можете отличить его от обычных тегов HTML, поскольку они начинаются с заглавной буквы. Наряду с обычными тегами HTML, компоненты являются теми кирпичиками, которые мы можем использовать для создания пользовательского интерфейса приложения.


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


Часть @route=... — это то, как мы передаем аргументы в компонент. Здесь мы используем этот аргумент, чтобы указать, какой маршрут мы хотим связать. (Обратите внимание, что это должно быть имя маршрута, а не путь, поэтому мы указали "about" вместо "/about" и "contact" вместо "/getting-in-touch" .)


В дополнение к аргументам компоненты также могут принимать обычные атрибуты HTML. В нашем примере мы добавили класс "button" для стилизации, но мы могли бы также указать другие атрибуты, которые мы посчитаем нужными, такие как атрибут role ARIA. Они передаются без символа @ ( class=... в отличие от @class=...), поэтому Ember будет знать, что они являются обычными HTML-атрибутами.


Под капотом компонент <LinkTo> генерирует для нас обычный тег <a> с соответствующей href для конкретного маршрута. Этот тег <a> прекрасно работает с программами чтения с экрана, а также позволяет нашим пользователям добавить ссылку в закладки или открыть ее в новой вкладке.


Однако при нажатии на одну из этих специальных ссылок Ember будет перехватывать клик мышки, отображать содержимое для новой страницы и обновлять URL-адрес — все это выполняется локально, без ожидания сервера. Это позволяет избежать полного обновления страницы.


Мы узнаем больше о том, как все это работает в ближайшее время. А пока идем дальше и нажимаем на ссылку в браузере. Вы заметили, как это быстро происходят переходы?


Поздравляем, вы уже на полпути к тому, чтобы стать мастером по созданию страниц!


Автоматизированное тестирование


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



В процессе вы узнаете о:


  • Цели автоматизированного тестирования
  • Написании приемочных тестов (acceptance tests)
  • Использовании генераторов в Ember CLI
  • Тестировании с помощью тестовой библиотеке QUnit
  • Работе с тестовыми помощниками (test helpers) Ember
  • Практике рабочего процесса тестирования

Цель автоматизированного тестирования


Мы уже достигли многого! Подведем итоги — мы начали с чистого листа, добавили несколько страниц контента, стилизовали все, чтобы выглядело красиво, добавили изображение Томстера, добавили ссылки между нашими страницами и, что удивительно, все заработало!


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


В конце концов, большинство из нас имеют опыт (или услышали ужасные истории), когда маленькое изменение в одной области приложения непреднамеренно ломала что-то в другой части. Даже если мы ничего там не меняли (и соответственно, не проверяли потом).


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


Хм, роботы. Это идея! Что если мы сможем написать этот контрольный список и просто заставить компьютер проверить все за нас? Я думаю, что мы только что изобрели идею автоматизированного тестирования! Ладно, может быть, мы не были первыми, кто придумал эту концепцию, но мы независимо ее обнаружили, поэтому мы все еще заслуживаем небольшой похвалы)


Использование генераторов для создания приемочных тестов (acceptance tests)


Как только мы закончим поглаживать себя по голове или доедим пирожок с полки, выполним следующую команду в терминале:


$ ember generate acceptance-test super-rentals
installing acceptance-test
  create tests/acceptance/super-rentals-test.js

В Ember CLI это называется командой генератора. Генераторы автоматически создают файлы для нас на основе соглашений Ember и заполняют их соответствующим стандартным содержимым, подобно тому, как ember new изначально создала для нас скелетное приложение. Обычно он следует шаблону ember generate <type> <name>, где <type> — это то, что мы генерируем, а <name> — то, что мы хотим назвать.


В этом случае мы сгенерировали приемочный тест, расположенный по адресу tests/acceptance/super-rentals-test.js.


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


Зои поясняет ...



Хотите сэкономить еще больше при печатании? ember generate ... может быть сокращено до ember g ... Это на 7 символов меньше! Другие команды следуют похожей логике

Пишем приемочные тесты


Приемочные тесты, являются одним из видов автоматизированного тестирования, который находится в нашем распоряжении в Ember. Позже мы узнаем о других типах, но что делает приемочные тесты уникальными, так это то, что они тестируют наше приложение как бы с точки зрения пользователя — это автоматизированная версия тестирования «нажми и посмотри, работает ли», которое мы делали ранее самостоятельно.


Давайте откроем сгенерированный тестовый файл и заменим шаблонный тест нашим собственным:



Сначала мы проинструктировали тестового робота перейти к корневому URL / нашего приложения с помощью тестового помощника (test helper) visit предоставленного Ember. Это сродни нам, набрав http://localhost:4200/ в адресной строке браузера и нажав клавишу enter.


Поскольку загрузка страницы займет некоторое время, это называется асинхронным шагом, поэтому нам нужно будет сказать тестовому роботу ждать, используя ключевое слово JavaScript await. Таким образом, он будет ждать, пока страница полностью не загрузится, прежде чем перейти к следующему шагу.


Это почти всегда то поведение, которое мы хотим, поэтому мы почти всегда будем использовать await и visit как пару. Это относится и к другим видам симулированного взаимодействия, например, к нажатию на кнопку или ссылку, поскольку все они требуют времени для завершения. Хотя иногда эти действия могут показаться нам незаметно быстрыми, мы должны помнить, что у нашего тестового робота действительно, очень быстрые руки, в чем мы убедимся через мгновение.


После перехода к URL / и ожидания решения проблемы мы проверяем, соответствует ли текущий URL ожидаемому URL ( / ). Мы можем использовать currentURL тест-помощник currentURL, а также equal утверждение. Вот как мы кодируем наш «контрольный список» в код. Указав или заявив, как все должно себя вести, мы будем предупреждены, если наше приложение не будет вести себя так, как мы ожидаем.


Затем мы подтвердили, что на странице есть тег <h2>, содержащий текст «Добро пожаловать в Super Rentals!». Проверка этого, означает, что мы можем быть совершенно уверены, что шаблон был отображен без ошибок.


Затем мы искали ссылку с текстом «About Us», расположенную с помощью селектора CSS .jumbo a.button. Это тот же синтаксис, который мы использовали в нашей таблице стилей, что означает «заглянуть внутрь тега с классом jumbo для тега <a> с классом button». Это соответствует структуре HTML в нашем шаблоне.


Как только существование этого элемента на странице подтвердилось, мы попросили тестового робота нажать на эту ссылку. Как упоминалось выше, это взаимодействие с пользователем, поэтому его нужно await.


Наконец, мы утверждаем, что нажатие на ссылку должно привести нас к URL-адресу /about.


Зои поясняет ...



Здесь мы пишем тесты в среде, называемой QUnit, откуда берутся функции module, test и assert. У нас также есть дополнительные помощники, такие как click, visit и currentURL предоставляемые пакетом @ember/test-helpers. Вы можете судить, из какого пакета берется та или иная функция исходя из пути import в верхней части файла. Знание этого будет полезно, когда вам нужно искать документацию в Интернете или обратиться за помощью.

Мы можем запустить наш автоматический тест, запустив тестовый сервер с помощью команды ember test --server или ember t -s для краткости. Этот сервер ведет себя во многом как сервер разработки, но он запущен для наших тестов. Он может автоматически открыть окно браузера и перейти к тестовому интерфейсу. Или вы можете открыть http://localhost:7357/ самостоятельно.


Если вы посмотрите очень внимательно, вы увидите, как наш тестовый робот бродит по нашему приложению и нажимает на ссылки (это происходит очень быстро):



Здесь важно то, что тест, который мы написали, прошел, а это означает, что все работает именно так, как мы ожидаем, и в пользовательском интерфейсе теста все зеленое и счастливое. Если вы хотите, вы можете перейти к index.hbs, удалить компонент <LinkTo> и посмотреть, как все будет выглядеть, когда у нас будет неудачный (failing) тест:



Не забудьте вернуть эту строку обратно!


Практикуя рабочий процесс тестирования


Давайте попрактикуемся в том, что мы узнали, добавив тесты для оставшихся страниц:



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



В оставшейся части руководства мы продолжим добавлять дополнительные автоматизированные тесты по мере разработки новых функций. Тестирование не является обязательным, но настоятельно рекомендуется (от переводчика: особенно, когда вы дописываете или переписываете ваше приложение) Тесты не влияют на функциональность вашего приложения, они просто защищают его от регрессий, что просто является способом заметить «случайные поломки».


Если вы спешите, вы можете пропустить разделы тестирования в этом учебном пособии и при этом продолжать следить за всем остальным. Но разве вы не находите супер удовлетворяющим — странно удовлетворяющим — наблюдать, как робот шустро бегает по страницам и выдает в конце зеленую полосочку?


Основы компонентов


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



При этом вы узнаете об:


  • Извлечении разметки в компоненты
  • Вызове компонентов
  • Передаче контента в компоненты
  • Выводе контента с ключевым словом {{yield}}
  • Рефакторинге существующего кода
  • Написании компонентных тестов
  • Использовании шаблона приложения и {{outlet}}

Извлечение разметки в компоненты


В предыдущей части мы получили небольшое представление о компонентах при использовании <LinkTo> для соединения наших страниц. Напомним, что мы говорили, что компоненты — это способ создания пользовательских тегов Ember в дополнение к встроенным тегам HTML из браузера. Теперь мы собираемся создать наши собственные компоненты!


В ходе разработки приложения довольно часто используется один и тот же элемент пользовательского интерфейса в разных частях приложения. Например, мы использовали один и тот же заголовок "jumbo" на всех трех страницах. На каждой странице мы работали, следуя одной и той же базовой структуре:



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


Компоненты являются идеальным решением для этого. В своей основной форме компонент — это просто часть шаблона, на которую можно ссылаться по имени. Давайте начнем с создания нового файла в app/components/jumbo.hbs с разметкой для заголовка «jumbo»:



Вот и все, мы создали наш первый компонент! Теперь мы можем вызвать этот компонент в любом месте нашего приложения, используя <Jumbo> качестве имени тега.


Зои поясняет ...



Помните, что при вызове компонентов нам нужно использовать заглавные буквы их имен, чтобы Ember мог отличить их от обычных элементов HTML. Шаблон jumbo.hbs соответствует тегу <Jumbo>, так же, как super-awesome.hbs соответствует <SuperAwesome>.

Передача содержимого в компоненты с помощью{{yield}}


При вызове компонента Ember заменяет тег компонента содержимым, найденным в шаблоне компонента. Как и в случае с обычными HTML-теги, распространено передавать контент компонентам, например, <Jumbo>some content</Jumbo>. Мы можем обработать это с помощью ключевого слова {{yield}}, которое будет заменено содержимым, которое было передано компоненту.


Давайте попробуем это, отредактировав шаблон индекса:



Рефакторинг существующего кода


После сохранения изменений ваша страница должна автоматически перезагрузиться, и, вуаля… ничего не изменилось! Ну, это именно то, что мы хотели! Мы успешно реорганизовали наш индексный шаблон для использования компонента <Jumbo>, и все по-прежнему работает, как и ожидалось.



И тесты проходят!



Давайте сделаем то же самое для двух других наших страниц.




После сохранения все должно выглядеть точно так же, как и раньше, и все тесты должны пройти.


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


Написание тестов компонентов


Прежде чем мы перейдем к следующему аспекту, давайте напишем автоматический тест для нашего компонента <Jumbo>. Запустите эту команду в своем терминале:


$ ember generate component-test jumbo
installing component-test
  create tests/integration/components/jumbo-test.js

Здесь мы использовали генератор для генерации теста компонента (component test), также известного как тест рендеринга (rendering test). Они используются для визуализации и тестирования одного компонента за раз. Это в отличие от приемочных тестов, которые мы написали ранее, которые должны отображать целые страницы контента.


Давайте заменим шаблон кода, который был сгенерирован для нас, нашим собственным тестом:



Вместо перехода по URL-адресу мы начинаем тестирование с отображения нашего компонента <Jumbo> на тестовой странице. Это полезно, потому что в противном случае может потребоваться много настройки и взаимодействия, чтобы просто попасть на страницу, где используется ваш компонент. Тестирование компонентов позволяет нам пропустить все это и сосредоточиться исключительно на тестировании компонента в отдельности.


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



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


Создадим компонент <NavBar> в app/components/nav-bar.hbs:



Далее добавим наш компонент вверху каждой страницы:




Вуаля, мы сделали еще один компонент!



Зои поясняет ...



<NavBar /> является сокращением для <NavBar></NavBar>. Теги компонентов всегда должны быть закрыты должным образом, даже если вы не передаете им какой-либо контент, как в этом случае. Поскольку это довольно распространенное явление, Ember предлагает альтернативную самозакрывающуюся нотацию!

В браузере все выглядит отлично, но, как мы знаем, мы никогда не можем быть слишком уверены. Итак, давайте напишем несколько тестов!


Но каких? Мы могли бы написать тест компонента для <NavBar> сам по себе, как мы только что сделали для компонента <Jumbo>. Однако, поскольку задача <NavBar> состоит в том, чтобы ориентировать нас по приложению, нет особого смысла тестировать этот конкретный компонент изолированно. Вернемся же к написанию приемочных тестов!




Мы обновили существующие тесты, чтобы утверждать, что на каждой странице существует элемент <nav>. Это важно для доступности (accessibility), так как программы чтения с экрана будут использовать этот элемент для обеспечения навигации. Также мы добавили новый тест, который проверяет поведение ссылок <NavBar> .


Все тесты должны пройти в этот момент!



Использование глобального шаблона приложения и {{outlet}}


Прежде чем мы перейдем к следующей функции, есть еще одна вещь, которую мы могли бы улучшить. Поскольку <NavBar> используется для навигации по всему сайту, его действительно необходимо отображать на каждой странице приложения. До сих пор мы добавляли компонент на каждую страницу вручную. Это подвержено ошибкам, так как мы можем легко забыть сделать это при следующем добавлении новой страницы.


Мы можем решить эту проблему, переместив панель навигации в специальный шаблон под названием application.hbs. Возможно, вы помните, что оно было сгенерировано для нас, когда мы впервые создали приложение, но мы удалили его. Теперь пришло время вернуть его!


Этот шаблон отличается тем, что у него нет собственного URL-адреса, и на него нельзя перейти самостоятельно. Скорее, он используется для указания общего макета, который используется всеми страницами вашего приложения. Это отличное место для размещения элементов пользовательского интерфейса, таких как навигационная панель и нижний колонтитул (footer) сайта.


Пока мы это делаем, мы также добавим элемент контейнера, который будет охватывать всю страницу, как того требует наш дизайнер для стилизации.






Ключевое слово {{outlet}} обозначает место, где должны отображаться страницы нашего сайта, аналогично ключевому слову {{yield}}, которое мы использовали ранее.


Так намного приятнее! Мы можем запустить наш набор тестов, который подтверждает, что все работает после нашего рефакторинга. И мы готовы перейти к следующей фиче!



На этом часть 1.1 заканчивается. Как посадить самолет Продолжение мы с гуглотранслейтом расскажем в следующей серии.

Комментарии (4)


  1. MK1301
    30.12.2019 20:45

    Есть стилистические неточности (отправлю в личку). Серер не стартует, быстрое решение проблемы закоментировать строчки в файле super-rentals\node_modules\ember-cli\lib\commands\serve.js со 115 по 118 но измениться порт на котором создался сервер смотрим в портянке запуска (if (commandOptions.port !== foundPort && commandOptions.port !== 0) {
    let message = `Port ${commandOptions.port} is already in use.`;
    return Promise.reject(new SilentError(message));
    }).
    Если работаете с Apache.
    Если используеться не корневая папка веб сервера а например APP1 в файле config\environment.js ищем параметр rootURL и меняем rootURL: '/', на rootURL: '/APP1/',
    в корне данной папки сервера apache в файле .htaccess надо добавить строку FallbackResource index.html


    1. chilicoder Автор
      30.12.2019 20:49

      выглядит, что у вас уже что-то живет на локалхосте.


      А с какой ошибкой сервер не стартует? приходите в дискорд или телеграмм, разберемся


      ember-cli в качестве http-сервера использует express. если ванговать, выглядит, что express у вас конфликтует с чем-то еще


      1. MK1301
        31.12.2019 05:04

        Сервер не стартует с ошибкой о том что порт 4200 занят, хотя на самом деле он свободен. Проблема связана с библиотекой portfinder она по настроению выдаёт то порт 4204 то 4212.


        1. chilicoder Автор
          31.12.2019 12:19

          порт можно менять опцией --port например ember server --port 8080


          Список опций для server можно получить командой ember help server


          $ ember help server
          Requested ember-cli commands:
          
          ember serve <options...>
            Builds and serves your app, rebuilding on file changes.
            aliases: server, s
            --port (Number) (Default: 4200) To use a port different than 4200. Pass 0 to automatically pick an available port.
              aliases: -p <value>
            --host (String) Listens on all interfaces by default
              aliases: -H <value>
            --proxy (String)
              aliases: -pr <value>, -pxy <value>
            --proxy-in-timeout (Number) (Default: 120000) When using --proxy: timeout (in ms) for incoming requests
              aliases: -pit <value>
            --proxy-out-timeout (Number) (Default: 0) When using --proxy: timeout (in ms) for outgoing requests
              aliases: -pot <value>
            --secure-proxy (Boolean) (Default: true) Set to false to proxy self-signed SSL certificates
              aliases: -spr
            --transparent-proxy (Boolean) (Default: true) Set to false to omit x-forwarded-* headers when proxying
              aliases: --transp
            --watcher (String) (Default: events)
              aliases: -w <value>
            --live-reload (Boolean) (Default: true)
              aliases: -lr
            --live-reload-host (String) Defaults to host
              aliases: -lrh <value>
            --live-reload-base-url (String) Defaults to baseURL
              aliases: -lrbu <value>
            --live-reload-port (Number) Defaults to same port as ember app
              aliases: -lrp <value>
            --live-reload-prefix (String) (Default: _lr) Default to _lr
              aliases: --lrprefix <value>
            --environment (String) (Default: development) Possible values are "development", "production", and "test".
              aliases: -e <value>, -dev (--environment=development), -prod (--environment=production)
            --output-path (Path) (Default: dist/)
              aliases: -op <value>, -out <value>
            --ssl (Boolean) (Default: false) Set to true to configure Ember CLI to serve using SSL.
            --ssl-key (String) (Default: ssl/server.key) Specify the private key to use for SSL.
            --ssl-cert (String) (Default: ssl/server.crt) Specify the certificate to use for SSL.
            --path (Path) Reuse an existing build at given path.