что такое веб элементы
Введение в веб-компоненты. Часть 1
От переводчика: Представляю вашему вниманию перевод многообещающего стандарта Веб-компонентов от Google, который может стать трендом в ближайшие несколько лет. В данный момент, знание этого стандарта не несёт практического применения, поэтому, если вы не фанат всего нового и интересного, вам возможно будет скучно читать данный перевод.
Перевод выложен на github, поэтому, если вы хотите помочь с переводом или исправить ошибку сделайте pull request, ну или пишите в личку.
Статус: Эксперементальный драфт
Введение
Компонентная модель для Web’а (или Web Components) состоит из четырёх модулей, которые, будучи использованными вместе, позволят разработчикам web-приложений создавать виджеты с богатыми визуальными возможностями, легкие в разработке и повторном использовании, что в данный момент невозможно с использованием только CSS и JS-библиотек.
Вместе декораторы и пользовательские элементы называются компонентами
Шаблоны
Содержимое элемента анализируется парсером, но оно неактивно: скрипты не запускаются, изображения не загружаются и т. д. Элемент не выводится.
В скрипте такой элемент имеет специальное свойство content, которое содержит статическую DOM-структуру определённую в шаблоне.
Например, разработчику может понадобиться определить DOM-структуру, которая создается несколько раз в документе, а затем создать его экземпляр, когда это будет необходимо.
Добавление статического DOM-узла в документ делает его «живым», как если бы этот DOM-узел был получен через свойство innerHTML.
Декораторы
Декоратор это нечто, что улучшает или переопределяет представление существующего элемента. Как и все аспекты представлений, поведение декораторов контролируется с помощью CSS. Однако, возможность определять дополнительные аспекты представления, используя разметку — уникальная черта декораторов.
Элемент указывает на место, куда декоратор (точнее, его содержимое) должен быть вставлен.
Декоратор применяется, используя CSS-свойство decorator:
Декоратор и CSS описанные выше заставят данную разметку:
+Но её рендер будет как у этой разметки (стили user agent опущены для краткости):
Если документ изменился так, что CSS-селектор, где был объявлен декоратор, более не действителен — обычно, когда селектор со свойством decorator более не применяется к элементу или правило с декоратором было изменено в атрибуте style, декоратор более не применяется, возвращая рендеринг элемента в первоначальное состояние..
Даже несмотря на то, что CSS-свойство decorator может указывать на любой ресурс в сети, декоратор не будет применяться, пока его определение загружается в текущий документ.
Разметка, которая генерируется представлениями, ограничивается чисто презентационным применением: она никогда не может запустить скрипт (в том числе встроенные обработчики событий), и она не может быть доступна для редактирования.
События в декораторах
Декораторы также могут навешивать обработчики событий для реализации интерактивности. Поскольку декораторы преходящи, не эффективно навешивать обработчики событий на ноды в шаблоне или полагаться на любое состояние шаблона, так как ноды в шаблоне пересобираются каждый раз как декоратор применяется или снимается с элемента.
Вместо этого, декораторы регистрируют обработчики событий у контроллера событий. Чтобы зарегистрировать обработчик событий, шаблон включает в себя элемент Bar
Вызов функции lisnen означает, что когда кнопка будет нажата, сработает обработчик события.
Контроллер событий перенаправит событие, наступившее в на любой ноде, на которой декоратор был применён, в обработчик события.
Рис. Обработка и переназначение событий
Когда слушатель событий вызывается, значением target события является нода, на которую декоратор был применен, а не содержимое его шаблона. Например, если декоратор, указанный выше, такого содержания:
Переопределение свойства target необходимо, тк декоратор определяет отображение; он не влияет на структуру документа. Пока декоратор применён, свойство target переопределяется на ноду, на которую он применён.
Также, если скрипт меняет контент шаблона, изменения игнорируются, точно также, как установка textContent элемента > V
Для этого понадобилось два декоратора. Один представляет detail элемент в закрытом виде, другой в открытом. Каждый декоратор использует обработчик события клика мыши, для изменения состояния открыт/закрыт. Атрибут select элемента будет рассмотрен подробнее ниже.
Пользовательские элементы
Пользовательские элементы — новый тип DOM-элементов, которые могут быть определены автором.
Пользовательские элементы могут определять вид отображения через декораторы. В отличии от декораторов, которые могут быть применены или сняты на нужный элемент, тип пользовательского элемента фиксирован. Но пользовательские элементы могут определять совершенно новое отображение и поведение, которые нельзя определить через декораторы, из-за элементарной природы последних.
Элемент определяет пользовательский элемент.
Атрибут extends определяется элемент, функционал которого мы хотим расширить. Каждый экземпляр пользовательского элемента будет иметь tagName определённый в атрибуте extends.
Атрибут name определяет пользовательский элемент, который будет связан с этой разметкой. Пространство имён у атрибута name такое же, как у имён тэгов стандартных элементов, поэтому для устранения коллизий, используется префикс x-.
Разные браузеры, определяют HTML элементы по-разному, однако все их интерпретации руководствуются семантикой HTML.
Тк не все браузеры поддерживают пользовательские элементы, авторы должны расширять HTML элементы, которые имеют наиболее близкое значение для нового пользовательского элемента. Например, если мы определяем пользовательский элемент, который является интерактивным и реагирует на клики, выполняя некоторые действия, мы должны расширять кнопку ( ).
Представление
Пользовательский элемент может содержать шаблон:
Если пользовательский элемент содержит шаблон, копия этого шаблона будет вставлена в теневой DOM элемента конструктором пользовательских элементов.
Теневой DOM будет описан ниже.
Использование пользовательских элементов в разметке
Т.к. пользовательские элементы использую существующие HTML тэги (div, button, option и тд), нам нужен атрибут для определения когда мы хотим использовать пользовательский элемент. Таким атрибутом является is, а значением его является название пользовательского элемента. Например:
Использование пользовательских элементов в скриптах
Вы можете создать пользовательский элемент из скрипта, используя стандартный метод document.createElement:
Пользовательский элемент может объявлять методы API добавляя их в свой prototype, в элементе …
Для того, чтобы обеспечить простую деградацию, this внутри элемента
Технически, скрипт внутри элемента
Нельзя создать пользовательский элемент указывая is атрибут у существующего DOM-элемента. Выполнение следующего кода ничего не даст:
Обновление элемента
Когда объявление пользовательского элемента будет загружено, каждый элемент с атрибутом is установленном в имя пользовательского элемента будет обновлён до пользовательского элемента. Обновление должно быть идентично удалению элемента и замене его на пользовательский элемент.
Когда каждый элемент заменяется, не всплывающее (non-bubbling), неотменяемое (non-cancellable) событие возникает на удаляющемся элементе. Скрипт, который хочет задержать взаимодействие с остальной часть документа до тех пор, пока пользовательский элемент не загрузиться может подписаться на специальное событие:
Авторы, которые хотят избежать показа нестилизованного контента, могут использовать CSS для изменения отображения не заменённого, обычного элемента, пока пользовательский элемент не загрузиться.
Методы жизненного цикла
Пользовательский элемент может подписаться на четыре метода жизненного цикла:
Обработчики inserted и removed могут быть вызваны несколько раз, каждый раз, когда пользовательский элемент вставляется и удаляется.
Подписаться на эти обработчики можно вызвав метод HTMLElementElement.lifecycle:
Расширение пользовательских элементов
В дополнении к HTML-элементам, можно расширить пользовательский элемент указанием имени пользовательского элемента в атрибуте extends элемента :
Обработка ошибок
Есть несколько возможностей для обработки ошибок при рендеринге пользовательских элементов:
От переводчика: в следующей части мы рассмотрим применение shadow DOM в Веб-компонентах, про внешние пользовательские элементы и декораторы, и про изоляцию, ограничение и инкапсуляцию Веб-компонентов
Веб компоненты. Часть 1: Пользовательские элементы
Вступление
Данная статья — первая часть из небольшой серии статей о создании веб-компонентов нативными средствами HTML и JS
Компонентный подход к разработке веб-приложений опирается на создание независимых модулей кода, которые могут быть использованы повторно, объединяемых по общему признаку, а также обладающие способностью хранить и восстанавливать свои состояния, взаимодействовать с другими компонентами и при этом не зависеть от других компонентов.
Для реализации такого подхода, в настоящее время разрабатываются три спецификации, о первой из которых, пойдет речь в этой статье. Итак, знакомимся — спецификация пользовательских элементов (custom elements), рабочий черновик которой оупбликован 13.10.2016 и последняя версия которого датирована 04.12.2017.
Пользовательский элемент является наиболее важной частью АПИ, входящих в пакет веб компонент, поскольку именно он предоставляет ключевые возможности, а именно:
В общих чертах
За создание пользовательских элементов веб-страницы отвечает интерфейс CustomElementRegistry, который позволяет регистрировать элементы, возвращает сведения о зарегистрированных элементах и т.д. Данный интерфейс доступен нам как объект window.customElement, у которого есть три интересующих нас метода:
Опубликованная версия спецификация предлагает создание пользовательских элементов в одной из двух форм: autonomous custom element (автономный пользовательский элемент) и customized built-in element (кастомизированный встроенный элемент).
О различиях
Автономный пользовательский элемент не имеет особенностей, его использование, согласно спецификации, ожидается во фразовом и потоковом контентах, он может получать любые атрибуты, кроме атрибута is, о котором речь пойдет позднее. DOM интерфейс такого элемента должен определятся автором, т.к. элемент наследует от HTMLElement.
В свою очередь кастомизированный встроенный элемент должен быть определен с указанием свойства extends (расширяет). Создаваемый кастомизированный элемент, таким образом, получает возможность наследовать семантику элемента, указанного значением свойства extends. Необходимость этой особенности авторы спецификации обуславливают тем, что не все существующие поведения HTML элементов могут быть дублированы с использованием только автономных элементов
Различия также заметны в синтаксисе объявления элементов и их использования, но это гораздо проще рассмотреть на примерах (то есть далее по тексту данной статьи).
Об атрибутах
Кастомизированным встроенным элементам присущ атрибут is, который принимает в значение название кастомизированного встроенного элемента (по которому он был объявлен).
Естественно атрибут is, если будет объявлен на автономном элементе (чего, согласно спецификации, делать нельзя ), эффекта не будет.
В остальном атрибуты для обоих видов элемента могут быть любыми, при условии что они XML-совместимы(соответствуют www.w3.org/TR/xml/#NT-Name и не содержат U+003A — двоеточия) и не содержат ASCII заглавных букв (https://html.spec.whatwg.org/multipage/infrastructure.html#uppercase-ascii-letters).
Определение
Определение пользовательского элемента включает:
В соответствии с действующей спецификацией, имена являются валидными, если они соответствуют следующему виду:
, в нотации Extended Backus-Naur Form (EBNF) спецификации XML(https://www.w3.org/TR/xml/#sec-notation).
Если проще — начинаются с маленькой буквы ASCII, не содержат заглавных букв, и разделены минимум одним дефисом.
Имена не могут иметь следующих значений: annotation-xml, color-profile, font-face, font-face-src, font-face-uri, font-face-format, font-face-name, missing-glyph.
Для автономного пользовательского элемента это имя из определения (defined name), а для кастомизированного встроенного элемента — значение, переданное в его опцию extends(в то время как имя из определения используется как значение is атрибута)
Конструктор вызывается когда инстанс создается или апгрейдится, подходит для инициализации состояния, установки наблюдателей или создания shadow dom. Однако есть некоторые ограничения. Так, первым вызовом в теле конструктора должен быть вызов super() без параметров; ключевое слово return не должно фигурировать в теле конструктора, если только это не обычный ранний return (return или return this); не должен вызывать document.write() или document.open(), потомки и атрибуты не должны создаваться на этом этапе, также обращение к ним не должно происходить; тут должна производится только та работа, которая действительно потребуется только единожды, а вся прочая по возможности должна быть вынесена в connectedCallback (см. далее).
Прототип, объект JS
Список тех атрибутов, изменение которых приведет к вызову метода attributeChangedCallback (см.далее). Определяется статичным геттером, который должен вернуть массив строковых значений.
Коллекция методов жизненного цикла
Представлены 4 метода, соответствующие жизненному циклу компонента:
вызывается каждый раз когда элемент внедряется в DOM. Тут уместно запрашивать ресурсы и производить рендеринг. Большинство работы лучше откладывать на этот метод;
вызывается каждый раз при удалении элемента из DOM и используется для освобождения памяти (отмена запросов, отмена интервалов, таймеров и обработчиков и пр.);
вызывается когда элемент был перемещен в новый документ, например вызовом document.adoptNode();
вызывается каждый раз при добавлении, изменении или замене атрибутов, входящих в список observedAttributes — этот метод будет вызван с тремя аргументами: именем атрибута претерпевшего изменения, его старым значением и его новым значением.
Они могут быть не присвоены, т.к. спецификация предусматривает их значением либо функцию, либо null. Все изложенные колбэки вызывается синхронно.
Стек конструирования (construction stack)
изначально пустой список, изменяемый алгоритмом upgrade an element и конструкторами HTML элементов, чье каждое вхождение далее окажется либо элементом, либо уже созданным маркером.
Подробнее: Автономные пользовательские элементы
Минимальный синтаксис создания прост:
Создается класс, который расширяет класс HTMLElement. Разметка будущего компонента задается в this.innerHTML внутри connectedCallback.
После объявления класса, элемент нужно определить, вызовом:
Пример с добавлением простейшего поведения:
Использование автономных пользовательских элементов возможно как путем указания их в виде тега:
Понаблюдав за работой таймера в инструментах разработчика можно заметить что страница не перегружается, изменения в DOM вносятся точечно. Очень напоминает реакт
В ознакомительных целях, я планировала сквозь весь цикл статей провести создание пользовательского элемента таб. На данном этапе техническое задание выглядит достаточно просто. Табы должны состоять из произвольного количества таб (при условии что количество навигационных элементов будет соответствовать количеству таб).
* Забегая вперед, инкапсуляцию стилей, и предоставаления большей свободы в задании содержимого как таб так и ярлыков будет рассмотрено в следующей статье.
Итак, я планирую создать три пользовательских элемента: элемент навигации, элемент содержимого, и элемент-обертка. Элемент навигации будет принимать атрибут target, его содержимое будет связывать элемент с соответствующим ему элементом навигации и, одновременно, будет выводится как текст навигационного элемента. Реализация:
Класс для создания элемента табы, должен иметь атрибут target, чье значение должно связать элемент с элементом навигации а также атрибут куда в данном случае будет передаваться содержимое табы (пока содержимое передается в атрибут — пользователь сильно ограничен в возможностях использования таб, но реализацию более гибкого подхода мы осуществим в следующей статье).
Непосредственно элемент обертка будет содержать функциональную логику — он получит все навигационные элементы и навесит обработчиков на событие клик, который свойство _target определит и покажет нам нужную табу.
* апдейт, исправлено снятие обработчика
Последним, но самым значимым этапом идет объявление элементов:
Пример работающих таб можно посмотреть тут
Подробнее: Кастомизированные встроенные элементы
Такой элемент унаследует семантику HTMLButtonElement и будет иметь возможность расширить ее.
При использовании элемента будет указан тег встроенного HTML элемента, в нашем примере — button с атрибутом is, которому будет передано имя из определения пользовательского элемента, таким образом:
а его создание методами js будет выглядеть так:
На сегодняшний день ни один браузер не реализовал customized built-in elements, потому рассматривать примеры пока приходится теоретически.
Вместо заключения или два слова про апгрейд
Прошу не судить строго. С уважением Tania_N
Что такое веб элементы
Что пишут в блогах
Продолжу хвастаться статусом книги.
I’m sticking with “bug” rather than adopt another word such as “fault,” which is the current fad in publications because:
Онлайн-тренинги
Что пишут в блогах (EN)
Разделы портала
Про инструменты
Автор: Энди Найт (Andy Knight)
Оригинал статьи
Перевод: Ольга Алифанова
Если вы занимаетесь тест-автоматизацией через веб-интерфейс (например, при помощи Selenium WebDriver), то, возможно, тратите много рабочего времени на поиск элементов на странице – к примеру, кнопок, полей ввода и блоков. Поиск нужных элементов может быть сложным делом, особенно в тех случаях, когда у них нет уникальных идентификаторов или имен классов. Это руководство поможет вам профессионально находить любые веб-элементы.
Что такое веб-элементы?
Веб-элемент – это индивидуальная сущность, генерирующаяся на веб-странице. Элементы – это все то, что пользователь видит (а иногда и не видит) на странице – заголовки, кнопки «ОК», поля ввода, текстовые блоки… Элементы в HTML определяются через имя тэга, атрибуты и содержание. У них также могут быть дочерние элементы – например, таблицы. CSS может применяться к элементам и менять их цвета, размеры и расположение. Языки программирования обычно получают доступ к веб-элементам как к нодам в объектной модели документа (DOM).
Что такое локаторы веб-элементов?
Веб-элементы и локаторы – это разные вещи. Локатор веб-элемента – это объект, который находит и возвращает веб-элементы на странице по заданному запросу. Короче говоря, локаторы находят элементы.
Зачем нужны локаторы? Как пользователи, мы взаимодействуем с веб-страницами визуально. Мы смотрим, скроллим, кликаем и печатаем посредством браузера. Тест-автоматизация, однако, взаимодействует со страницами программно: ей нужен закодированный способ поиска и манипулирования теми же самыми элементами. Традиционная автоматизация не будет «смотреть» на страницу, как человек – вместо этого она будет искать через DOM.
(Более современные технологии автоматизации позволяют визуальное тестирование – об этом будет сказано чуть позже).
Selenium WebDriver разделяет вопросы поиска элементов и взаимодействия с ними. Вызовы WebDriver для этих двух целей часто идут подряд.
WebDriver предоставляет следующие типы запросов для локаторов через «By»:
provides the following locator query types using “By”:
Какой из них лучше? Обсудим далее.
Локаторы могут возвращать несколько элементов, или вообще их не вернуть! Вот пример:
Большие тест-фреймворки часто используют шаблоны дизайна для структурирования локаторов и взаимодействий. Модель Page Object организует локаторы и методы действий в классы – по странице или по компоненту. Однако я крайне рекомендую шаблон Screenplay, а не Page Object, потому что части Screenplay лучше подаются повторному использованию и масштабированию. Вне зависимости от модели локаторы необходимы.
Как найти элементы?
Элементы могут с трудом поддаваться поиску, когда вы пишете локаторы для тест-автоматизации. Для упрощения работы я использую инструменты разработчика Chrome вместе с моей IDE. Почему Chrome?
Чтобы исследовать любую страницу в Chrome, просто кликните правой кнопкой на любом месте страницы:
Вуаля! Инструменты разработчика откроются. Для поиска веб-элементов мы воспользуемся вкладкой Elements.
В Chrome легко выделить элемент визуально. Выберите инструмент «Select» в верхнем левом углу панели инструментов разработчика (она выглядит как квадрат с курсором). Иконка должна поменять цвет на синий.
Затем переместите курсор к нужному элементу на странице. Вы увидите, как каждый элемент подсвечивается, когда вы наводите на него мышь. Соответствующий исходный HTML-код на вкладке Elements также будет подсвечен. Чудненько! Кликните на нужном элементе, чтобы подсветка сохранилась после смещения курсора.
Теперь вы можете изучить тег элемента, классы, атрибуты, содержание, родительские и дочерние элементы.
Как писать хорошие локаторы?
Поиск элемента – это полдела. Создание уникального запроса для локатора – вот вторая половина. Если локатор чересчур широк, он будет возвращать ложноположительные значения. При слишком узком подходе он начнет ломаться при любом изменении DOM, и его будет сложно читать другим людям. Лучший подход здесь такой – пишите наиболее простой запрос, который уникально идентифицирует целевой элемент или элементы.
Мой список предпочтения типов запросов в порядке убывания:
Уникальные ID, имена и имена классов крайне упрощают создание локаторов: запросы будут краткими и не требуют дополнительных якорей. Всегда ратуйте, чтобы ваши разработчики использовали уникальные идентификаторы (например, имена классов) для всех элементов. Однако у многих элементов таких идентификаторов нет, и локаторам приходится полагаться на более сложные CSS-селекторы и (содрогнувшись) XPath. Если это случилось с вами, вот мои рекомендации:
Всегда тестируйте локаторы, в них часто встречаются ошибки синтаксиса и ложноположительные значения. Chrome DevTools упрощает их тестирование – нажмите Ctrl+F на вкладке элементов и вставьте запрос локатора в поле поиска. DevTools подсветит все соответствующие элементы по порядку. Шик-блеск-красота!
Если я не могу разобраться, почему локатор в тесте не срабатывает, я делаю следующее:
Что делать, если тесты нестабильны?
Тестирование через Web UI часто критикуют за нестабильность, потому что тесты часто падают из-за непредвиденных причин. Однако большая часть ненадежности, с которой сталкиваются тестировщики Web UI (и, зачастую, пользователи Selenium WebDriver как такового) связана с тем, что все Web-взаимодействия изначально создают гоночные условия. Автоматизация и браузер работают независимо друг от друга, и взаимодействие должно синхронизироваться с состоянием страницы. В противном случае WebDriver будет выдавать исключения из-за таймаутов, устаревших и не найденных элементов. В ряде случаев эти проблемы возникают не каждый раз, поэтому их тяжело отследить и исправить.
Лучший способ избежать гоночных условий таков – всегда ожидайте существования элемента, прежде чем взаимодействовать с ним. Это кажется элементарным, но про это легко забыть. Пакеты Selenium WebDriver всегда предлагают какую-то разновидность объекта WebDriverWait, заставляющего драйвер ожидать истинности определенного условия перед дальнейшими действиями. Простейший способ проверить, существует ли элемент – это проверить список элементов, возвращаемый вызовом FindElements (для списка элементов) и убедиться, что он непустой. Добавление дополнительного вызова для каждого взаимодействия может показаться затратным, однако дизайн-шаблоны хорошо спроектированных фреймворков (например, Screenplay) могут автоматически осуществлять подобные проверки.
Еще одна хорошая практика – всегда получать «свежие» элементы. Иногда автоматизация вначале получит ряд элементов, а затем через второй запрос получит следующую часть. Или же, в случае с Page Object Factory (никогда ей не пользуйтесь – если в трех словах, она отвратительна), элементы получаются один раз при конструировании Page Object, а затем на них ссылаются. Вне зависимости от способа – чем дольше существует объект на веб-странице, тем более он подвержен тому, чтобы устареть и вызвать исключения. Я видел элементы, необъяснимо устаревающие, даже если они еще присутствовали на странице. Всегда запрашивайте элемент тогда, когда он нужен – в этом случае он не успеет устареть!
Как искусственный интеллект может помочь в тестировании Web UI?
Ряд новых основанных на ИИ проектов и продуктов направлен на улучшение автоматизированного тестирования Web UI по сравнению с традиционными методами:
Множество инструментов тестирования, основанных на ИИ, очень полезны, но держите в уме, что под капотом они все-таки пользуются локаторами.