{"id":226,"date":"2021-02-02T20:02:11","date_gmt":"2021-02-02T20:02:11","guid":{"rendered":"https:\/\/fde.cat\/?p=226"},"modified":"2021-02-02T20:02:12","modified_gmt":"2021-02-02T20:02:12","slug":"automation-made-easy-for-web-components-shadow-roots","status":"publish","type":"post","link":"https:\/\/fde.cat\/index.php\/2021\/02\/02\/automation-made-easy-for-web-components-shadow-roots\/","title":{"rendered":"Automation made easy for Web Components #shadow-roots"},"content":{"rendered":"<h3>Automate Shadow DOM with WebDriver &amp; Playwright<\/h3>\n<h4>Locate elements in Shadow DOM of Web Components directly through CSS query&nbsp;engine.<\/h4>\n<figure><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/800\/1*5VHuFmJwDN9T0MToqh5itA.png?w=750&#038;ssl=1\" alt=\"\" data-recalc-dims=\"1\"><\/figure>\n<p>This document shows how to use the simpler CSS\/xPaths that calls through document.querySelector to locate elements within #shadow-root of your <strong>Web Components<\/strong> or <strong>Salesforce LWC <\/strong>Applications. This solution can be extended to LitElements, Lighting Fast Templates etc.<\/p>\n<p>The wish is to locate your #shadow-root elements directly through CSS query engine (whic you cannot do it with current WebDriver implementation) e.g,<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/688072c871ac827da34895057bf6731f\/href\">https:\/\/medium.com\/media\/688072c871ac827da34895057bf6731f\/href<\/a><\/p>\n<p>\ud83d\udd0e If you\u2019re building your app with the Web Components or <a href=\"https:\/\/lwc.dev\/\">Salesforce\u2019s LWC<\/a>, and if you try to use document.querySelector (in the console), it will not find anything in the document though you see the element in the Browser DOM. The reason is that the elements of Web Component are not in the <em>Main DOM<\/em> but rather in the <a href=\"https:\/\/www.webcomponents.org\/introduction#shadow-dom\">Shadow&nbsp;DOM<\/a>.<\/p>\n<blockquote><p>\u201cThe Shadow DOM shield becomes the pain for developers in writing integration\/component\/E2E automated tests for Web Components.\u201d<\/p>\n<\/blockquote>\n<h3>\u26a0\ufe0f THE&nbsp;PROBLEM<\/h3>\n<blockquote><p>Shadow DOM <strong>prevents<\/strong> your components from easily being e2e tested because normal Selenium commands fail, due to the element actually not being in the main document. Rather, they are encapsulated under Shadow&nbsp;DOM.<\/p>\n<\/blockquote>\n<p>Selenium uses querySelector to find an element; Shadow DOMs prevent&nbsp;this.<\/p>\n<p>The selector engines like css\/xpath do not work on the shadow DOM by&nbsp;default.<\/p>\n<h4>Example<\/h4>\n<p>Let\u2019s take a look at chrome:\/\/download page. It implements the Shadow DOM. As you see, the #searchInput is a scoped element under #shadow-root (open), and so the document.querySelector <strong>command fails<\/strong> to locate the #searchInput element,<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1*HKv5HvRWV-XetXuPmArQkg.gif?w=750&#038;ssl=1\" alt=\"\" data-recalc-dims=\"1\"><\/figure>\n<p>The below query fails to return the element because #searchInput is encapsulated under Shadow&nbsp;Dom,<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/1ff87622bc29dfc8144da9648c48c0bb\/href\">https:\/\/medium.com\/media\/1ff87622bc29dfc8144da9648c48c0bb\/href<\/a><\/p>\n<p>and as a result the below <em>Selenium WebDriver Command<\/em> <strong>will also fail <\/strong>to find an element&nbsp;\u274e<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/af4785ce5cb48633e734444fbcfac807\/href\">https:\/\/medium.com\/media\/af4785ce5cb48633e734444fbcfac807\/href<\/a><\/p>\n<p>So what is needed is a <strong>very complex nested CSS<\/strong> <strong>[not recommended] <\/strong>\u2193<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/96b5abde6d915960e9f8180b727f50f6\/href\">https:\/\/medium.com\/media\/96b5abde6d915960e9f8180b727f50f6\/href<\/a><\/p>\n<p>\ud83e\udd14 now imagine, you add one more element in the nested route. Then, you are unknowingly breaking the automation tests. You will need to track and update all the existing nested CSS\u200a\u2014\u200awhich is a&nbsp;pain!!<\/p>\n<h4>Can I get the support from WebDriver?<\/h4>\n<p>Yes. <a href=\"https:\/\/github.com\/salesforce\/codeceptjs-bdd\/tree\/develop\/examples\/webcomponents-playwright-webdriver-example\">Codeceptjs-BDD<\/a> Framework provides out-of-the-box support to locate Shadow DOM elements at ease. Though, there is an existing feature request to have the support in <a href=\"https:\/\/github.com\/w3c\/webdriver\/issues\/350\">W3C\/Webdriver<\/a>, but thru Codeceptjs-BDD Framework, you can locate elements like, document.query,<\/p>\n<pre>I.click('.any-shadow-elements-in-dom'); \/\/ no dom hierarchy<\/pre>\n<blockquote><p>[..] most end-to-end testing frameworks rely on [..] calls to querySelector through CSS\/xPaths. Elements in Shadow DOM are selectable by neither. But, we have a Solution at framework level.<\/p>\n<\/blockquote>\n<h3>\ud83d\ude80 THE&nbsp;SOLUTION<\/h3>\n<p>The solution is <strong>Codeceptjs-BDD Webdriver implementations <\/strong>\ud83c\udf89 \ud83c\udf89 \ud83c\udf89<strong>, <\/strong>which provides automatic support for the Shadow DOM&nbsp;, and Playwright already has in-built&nbsp;support.<\/p>\n<p>Let\u2019s talk about the real scenarios built with framework <strong>CodeceptJS<\/strong>!<\/p>\n<p><a href=\"https:\/\/github.com\/salesforce\/codeceptjs-bdd\">salesforce\/codeceptjs-bdd<\/a><\/p>\n<p><em><strong>Example: <\/strong>As you see in line #6 in below gif, the CSS is pretty simplified in&nbsp;test.<\/em><\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1*D87eC9yXe4Zm42qqx78mBQ.gif?w=750&#038;ssl=1\" alt=\"\" data-recalc-dims=\"1\"><\/figure>\n<p>\u2705 As you see in a below example, you would just define a very simple CSS #searchInput&nbsp;. The Playwright driver will find an element(s) for you. No need to mention about any of the hierachy of #shadow-roots!<\/p>\n<p>\ud83d\ude4c<strong> No Nested\/Complex CSS required!<\/strong><\/p>\n<p><a href=\"https:\/\/medium.com\/media\/3f3eeeb821abf23a84d6614f87725159\/href\">https:\/\/medium.com\/media\/3f3eeeb821abf23a84d6614f87725159\/href<\/a><\/p>\n<p>Simply inspect the element in DOM, and grab the unique attribute. It is as simple as that with Playwright because Playwright does rest of the plumbing work for&nbsp;us.<\/p>\n<p>\u2763\ufe0f<strong> WebDriver Exclusive Support for Shadow Dom&nbsp;<\/strong>\u2b07<\/p>\n<p><a href=\"https:\/\/github.com\/salesforce\/codeceptjs-bdd\/tree\/develop\/examples\/webcomponents-playwright-webdriver-example\">salesforce\/codeceptjs-bdd<\/a><\/p>\n<h4>\u2705 The Framework Documentations:<a href=\"https:\/\/gkushang.github.io\/\"> https:\/\/gkushang.github.io\/<\/a><\/h4>\n<h3>Demo Time<\/h3>\n<h4>Let\u2019s take a look some real examples with scenarios<\/h4>\n<p>The examples in this doc are built with <a href=\"https:\/\/github.com\/salesforce\/codeceptjs-bdd\">Codeceptjs-BDD<\/a> framework with Playwright!<\/p>\n<p><strong>A Complete Example&nbsp;Test<\/strong><\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/823\/1*iV7LPLv6yaBifFshcbYbJg.png?w=750&#038;ssl=1\" alt=\"\" data-recalc-dims=\"1\"><\/figure>\n<p>As you see in above example, the #searchInput is a scoped element (#shadow-root) but it does not require you to have nested CSS of #shadowRootsto locate the element but it still finds an&nbsp;element!<\/p>\n<h4>Salesforce\u2019s LWC Page Object, the <strong>Another&nbsp;Example<\/strong><\/h4>\n<p>The Salesforce Lighting Web Components (LWC) is another great example of Shadow DOM elements. <a href=\"https:\/\/recipes.lwc.dev\/\">LWC Recipes<\/a> is build with LWC. Below is the Page Object on how to query Shadow DOM elements with simple&nbsp;CSS.<\/p>\n<p>A complete E2E automation Example of <a href=\"https:\/\/recipes.lwc.dev\/\">Salesforce\u2019s Lighting Web Components Application<\/a> is available here:<\/p>\n<img decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/753\/1*3OpIYq0-kPYesEiQl_StSA.png?w=750&#038;ssl=1\" alt=\"\" data-recalc-dims=\"1\">\n<p><a href=\"https:\/\/github.com\/salesforce\/codeceptjs-bdd\/tree\/develop\/packages\/salesforce-lwc-codecept-example\/salesforce-lwc-e2e-playwright\">salesforce\/codeceptjs-bdd<\/a><\/p>\n<p>\ud83c\udf89 The <a href=\"https:\/\/gkushang.github.io\/\">Codeceptjs-BDD<\/a> makes it easy to Automate Web Components in any of the below mentioned automation test&nbsp;layers:<\/p>\n<ul>\n<li><strong>Component Tests<\/strong><\/li>\n<li><strong>Integration Tests<\/strong><\/li>\n<li><strong>Functional Tests<\/strong><\/li>\n<li><strong>E2E Tests<\/strong><\/li>\n<\/ul>\n<p>\u2b50\ufe0f Don\u2019t forget to checkout more docs on <a href=\"https:\/\/gkushang.github.io\/\">Codeceptjs-BDD framework WebSite<\/a> and the CodeceptJS <a href=\"https:\/\/codecept.io\/\">library<\/a> for great additional features\ud83c\udf08!<\/p>\n<p>Thanks for reading, I hope you discovered something new and useful. Stay curious, and happy&nbsp;coding!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/medium.com\/_\/stat?event=post.clientViewed&#038;referrerSource=full_rss&#038;postId=b23016779ce8\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<hr>\n<p><a href=\"https:\/\/engineering.salesforce.com\/automation-made-easy-for-web-components-shadow-roots-b23016779ce8\">Automation made easy for Web Components #shadow-roots<\/a> was originally published in <a href=\"https:\/\/engineering.salesforce.com\/\">Salesforce Engineering<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Automate Shadow DOM with WebDriver &amp; Playwright Locate elements in Shadow DOM of Web Components directly through CSS query&nbsp;engine. This document shows how to use the simpler CSS\/xPaths that calls through document.querySelector to locate elements within #shadow-root of your Web Components or Salesforce LWC Applications. This solution can be extended to LitElements, Lighting Fast Templates&hellip; <a class=\"more-link\" href=\"https:\/\/fde.cat\/index.php\/2021\/02\/02\/automation-made-easy-for-web-components-shadow-roots\/\">Continue reading <span class=\"screen-reader-text\">Automation made easy for Web Components #shadow-roots<\/span><\/a><\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","footnotes":""},"categories":[7],"tags":[],"class_list":["post-226","post","type-post","status-publish","format-standard","hentry","category-technology","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":632,"url":"https:\/\/fde.cat\/index.php\/2022\/09\/12\/memlab-an-open-source-framework-for-finding-javascript-memory-leaks\/","url_meta":{"origin":226,"position":0},"title":"MemLab: An open source framework for finding JavaScript memory leaks","date":"September 12, 2022","format":false,"excerpt":"We\u2019ve open-sourced MemLab, a JavaScript memory testing framework that automates memory leak detection. Finding and addressing the root cause of memory leaks is important for delivering a quality user experience on web applications. MemLab has helped engineers and developers at Meta improve user experience and make significant improvements in memory\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":839,"url":"https:\/\/fde.cat\/index.php\/2024\/03\/18\/logarithm-a-logging-engine-for-ai-training-workflows-and-services\/","url_meta":{"origin":226,"position":1},"title":"Logarithm: A logging engine for AI training workflows and services","date":"March 18, 2024","format":false,"excerpt":"Systems and application logs play a key role in operations, observability, and debugging workflows at Meta. Logarithm is a hosted, serverless, multitenant service, used only internally at Meta, that consumes and indexes these logs and provides an interactive query interface to retrieve and view logs. In this post, we present\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":869,"url":"https:\/\/fde.cat\/index.php\/2024\/05\/22\/composable-data-management-at-meta\/","url_meta":{"origin":226,"position":2},"title":"Composable data management at Meta","date":"May 22, 2024","format":false,"excerpt":"In recent years, Meta\u2019s data management systems have evolved into a composable architecture that creates interoperability, promotes reusability, and improves engineering efficiency.\u00a0 We\u2019re sharing how we\u2019ve achieved this, in part, by leveraging Velox, Meta\u2019s open source execution engine, as well as work ahead as we continue to rethink our data\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":499,"url":"https:\/\/fde.cat\/index.php\/2021\/11\/01\/the-journey-of-building-a-scalable-api\/","url_meta":{"origin":226,"position":3},"title":"The Journey of Building a Scalable API","date":"November 1, 2021","format":false,"excerpt":"APIs are an essential tool to allow partners, developers, and applications to consume, communicate\u00a0,or build on top of the various capabilities your microservices provide. Building a high quality API that can scale and perform with the business ecosystem is not easy and requires putting thought and planning into everything, from\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":658,"url":"https:\/\/fde.cat\/index.php\/2022\/11\/30\/enabling-static-analysis-of-sql-queries-at-meta\/","url_meta":{"origin":226,"position":4},"title":"Enabling static analysis of SQL queries at Meta","date":"November 30, 2022","format":false,"excerpt":"UPM is our internal standalone library to perform static analysis of SQL code and enhance SQL authoring.\u00a0 UPM takes SQL code as input and represents it as a data structure called a semantic tree. Infrastructure teams at Meta leverage UPM to build SQL linters, catch user mistakes in SQL code,\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":636,"url":"https:\/\/fde.cat\/index.php\/2022\/09\/27\/a-peek-at-datoramas-aws-s3-sql-query-tool\/","url_meta":{"origin":226,"position":5},"title":"A Peek at Datorama\u2019s AWS S3 SQL Query Tool","date":"September 27, 2022","format":false,"excerpt":"Datorama Reports for Marketing Cloud enables you to generate, view, and share a detailed analysis of your Email, Push, and Journey campaign-level data. For that, Datorama extracts large volumes of data to its Data Lake solution for the Marketing Cloud marketing analytics, which is stored in a structured table compatible\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/226","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/comments?post=226"}],"version-history":[{"count":2,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/226\/revisions"}],"predecessor-version":[{"id":235,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/226\/revisions\/235"}],"wp:attachment":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/media?parent=226"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/categories?post=226"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/tags?post=226"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}