{"id":48883,"date":"2023-03-30T08:59:26","date_gmt":"2023-03-30T15:59:26","guid":{"rendered":"https:\/\/app14743.cloudwayssites.com\/?p=48883"},"modified":"2024-04-22T09:31:23","modified_gmt":"2024-04-22T16:31:23","slug":"using-web-selectors-in-webdriverio","status":"publish","type":"post","link":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/","title":{"rendered":"Let the Engineers Speak: Selectors in WebdriverIO"},"content":{"rendered":"\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p>Earlier this month, Applitools hosted a webinar, <a href=\"https:\/\/app14743.cloudwayssites.com\/event\/selectors-locators-cypress-webdriverio-webinar\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Let the Engineers Speak: Selectors<\/span><\/strong><\/a>, where testing experts discussed one of the most common pain points that pretty much anyone who&#8217;s ever done web UI testing has felt. In this two-part blog series, I will recap what our experts had to say about locating their web elements using their respective testing frameworks: WebDriverIO and Cypress.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-introducing-our-experts\">Introducing our experts<\/h2>\n\n\n\n<p>I\u2019m Pandy Knight, the <a href=\"https:\/\/automationpanda.com\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Automation Panda<\/span><\/strong><\/a>. I moderated our two testing experts in our discussion of selectors:<\/p>\n\n\n\n<ul>\n<li><a href=\"https:\/\/bromann.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Christian Bromann<\/span><\/strong><\/a>, <em>WebdriverIO<\/em><\/li>\n\n\n\n<li><a href=\"https:\/\/filiphric.com\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Filip Hric<\/span><\/strong><\/a>, <em>Cypress<\/em><\/li>\n<\/ul>\n\n\n\n<p>In each article, we&#8217;re going to compare and contrast the approaches between these two frameworks. This comparison is meant to be collaborative, not competitive. This series is meant to showcase and highlight the awesomeness that we have with modern frameworks and tools available.<\/p>\n\n\n\n<p>This first article in our two-part series will define our terms and challenges, as well as recap Christian\u2019s WebDriverIO selectors tutorial and WebdriverIO Q&amp;A. The upcoming second article will recap Filip\u2019s Cypress selectors tutorial and Cypress Q&amp;A.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-defining-our-terms\">Defining our terms<\/h2>\n\n\n\n<p>Let\u2019s define the words that will be used in this series to frame the discussion and so that we have the same understanding as we discuss selectors, locators, and elements:<\/p>\n\n\n\n<ul>\n<li><strong>Selectors<\/strong>: A selector is a text-based query used for locating elements. Selectors could be things like CSS selectors, XPaths, or even things like an ID or a class name. In modern frameworks, you can even use things like text selectors to query by the text inside of a button.<\/li>\n\n\n\n<li><strong>Locators<\/strong>: A locator is an object in the tool or framework you use that uses the selector for finding the element on the active page.<\/li>\n\n\n\n<li><strong>Elements<\/strong>: The element itself is the entity on the page that exists. An element could be a button, it could be a label, an input field, or a text area. Pretty much anything in HTML that you put on a page is an element.<\/li>\n<\/ul>\n\n\n\n<p>In one sentence, <strong>locators<\/strong> use <strong>selectors<\/strong> to find <strong>elements<\/strong>. We may sometimes use the terms \u201cselector\u201d and \u201clocator\u201d interchangeably, especially in more modern frameworks.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-challenges-of-locating-web-elements\">Challenges of locating web elements<\/h2>\n\n\n\n<p>We&#8217;re going to talk about selectors, locators, and the pain of trying to get elements the right way. In the simple cases, there may be a button on a page with an ID, and you can just use the ID to get it. But what happens if that element is stuck in a shadow DOM? What if it&#8217;s in an iframe? We have to do special things to be able to find these elements.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-locating-web-elements-with-webdriverio\">Locating web elements with WebdriverIO<\/h2>\n\n\n\n<p>Christian Bromann demonstrated effective web element locator strategies with WebDriverIO. In this series, we used Trello as the example web app to compare the frameworks. For the purposes of the demo, the app is wrapped over a component test, allowing Christian to work with web on the console to easier show you how to find certain elements on the page.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong><em>Note<\/em><\/strong><em>: All the following text in this section is based on Christian\u2019s part of the webinar.<\/em> <em>Christian&#8217;s repository is available on <a href=\"https:\/\/github.com\/christian-bromann\/trelloapp-vue-vite-ts\/tree\/main\/test\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">GitHub<\/span><\/strong><\/a>.<\/em><\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-creating-a-board\">Creating a board<\/h3>\n\n\n\n<p>First, we want to start creating a new board. We want to write a test to inspect the input element that the end user sees. From the dev tools, the input element can be found.<\/p>\n\n\n\n<p>There are various ways to query for that input element:<\/p>\n\n\n\n<ul>\n<li>We could fetch the element with WebdriverIO using $ or $$ commands, depending if you want to fetch one element, the first element on the page, or all elements. <em>Using an input as a selector is not advised, as there could be more inputs and then the wrong input could be fetched.<\/em><\/li>\n\n\n\n<li>We could also use a CSS class called <a href=\"https:\/\/tailwind.build\/classes\/paddings\/px-2\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">px-2<\/span><\/strong><\/a>. <em>Using CSS classes is also not advised, as oftentimes these classes are meant to style an element, not necessarily locate it.<\/em><\/li>\n\n\n\n<li>We could use a property, such as the name of the input using the data attribute. <em>This is the suggested way to locate a web element in WebdriverIO \u2013 using the accessibility properties of an element.<\/em><\/li>\n<\/ul>\n\n\n\n<p>WebdriverIO has a more simplified way to use <a href=\"https:\/\/webdriver.io\/docs\/selectors\/#accessibility-name-selector\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">accessibility properties<\/span><\/strong><\/a>. This approach is a much better selector, because it&#8217;s actually what the user is seeing and interacting with. To make things easier, Chrome helps with finding the accessibility selector for every element under the accessibility tab.<br><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em><strong>Note<\/strong>: WebdriverIO doesn\u2019t use the accessibility API of the browser and instead uses a complex XPath to compute the accessibility name.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>After you\u2019ve located the input element, press enter using the <a href=\"https:\/\/webdriver.io\/docs\/api\/browser\/keys\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">keys API<\/span><\/strong><\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">  it('can create an initial board', async () =&gt; {\n    await $('aria\/Name of your first board').setValue('Let the Engineers Speak')\n    await browser.keys(Key.Enter)\n    await expect(browser).toHaveUrlContaining('\/board\/1')\n    \n    await browser.eyesCheck('Empty board')\n  })<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-creating-a-list\">Creating a list<\/h3>\n\n\n\n<p>Now that our board is created, we want to start a list. First, we inspect the \u201cAdd list\u201d web element for the accessibility name, and then use that to click the element.<\/p>\n\n\n\n<p>Set the title of the list, and then press enter using the <a href=\"https:\/\/webdriver.io\/docs\/api\/browser\/keys\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">keys API<\/span><\/strong><\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">  it('can add a list on the board', async () =&gt; {\n    await $('aria\/Enter list title...').setValue('Talking Points')\n    await $('aria\/Add list').click()\n\n    \/**\n     * Select element by JS function as it is much more perfomant this way\n     * (1 roundtrip vs nth roundtrips)\n     *\/\n    await expect($(() =&gt; (\n      [...document.querySelectorAll('input')]\n        .find((input) =&gt; input.value === 'Talking Points')\n    ))).toBePresent()\n  })<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-adding-list-items\">Adding list items<\/h3>\n\n\n\n<p>To add to the list we created, the button is a different element that\u2019s not accessible, as the accessibility name is empty. Another way to approach this is to use a WebdriverIO function that allows me to add a locator search applicator strategy.<\/p>\n\n\n\n<p>The example applicator strategy basically queries all this on the page to find all divs that have no children and that text of a selector that you provide, and now you should be able to query that custom element. After getting the custom elements located, you can assert that three cards have been created as expected. You can inject your JavaScript script to be run in the browser if you don\u2019t have accessibility selectors to work with.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">  it('can add a card to the list', async () =&gt; {\n    await $('aria\/Add another card').click()\n    await $('aria\/Enter a title for this card...').addValue('Selectors')\n    await browser.keys(Key.Enter)\n    await expect($$('div[data-cy=\"card\"]')).toBeElementsArrayOfSize(1)\n    await $('aria\/Enter a title for this card...').addValue('Shadow DOM')\n    await browser.keys(Key.Enter)\n    await $('aria\/Enter a title for this card...').addValue('Visual Testing')\n    await browser.keys(Key.Enter)\n    await expect($$('div[data-cy=\"card\"]')).toBeElementsArrayOfSize(3)\n\n    await browser.eyesCheck('board with items')\n  })<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-starring-a-board\">Starring a board<\/h3>\n\n\n\n<p>Next, we\u2019ll \u201cstar\u201d our board by traversing the DOM using WebdriverIO commands. We need to first locate the element that has the name of the board title using the attribute selector and going to the parent element.<\/p>\n\n\n\n<p>From that parent element, to get to the star button, we chain the next command and call the next element. Now we can click the star and see it change to an enabled state. So with WebdriverIO, you can chain all these element queries and then add your action at the end. WebdriverIO uses a proxy in the background to transform everything and execute the promises after each other so that they&#8217;re available. One last thing you can also do is query elements by finding links with certain text.<\/p>\n\n\n\n<p>Summarizing Christian\u2019s suggestions for using selectors in WebdriverIO, always try to use the accessibility name of an element. You have the dev tools that give you the name of it. If you don&#8217;t have the accessibility name available, improve the accessibility of your application if possible. And if that\u2019s not an option, there are other tricks like finding an element using JavaScript through propertis that the DOM has.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">  it('can star the board', async () =&gt; {\n    const startBtn = $('aria\/Let the Engineers Speak').parentElement().nextElement()\n    await startBtn.click()\n    await expect(startBtn).toHaveStyle({ color: 'rgba(253,224,71,1)' })\n  })<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-accessing-a-shadow-root\">Accessing a shadow root<\/h3>\n\n\n\n<p>Using a basic web HTML timer component as an example, Christian discussed shadow roots. The example has multiple elements and a nested shadow root. Trying to access a button within the shadow root results in an error that you don\u2019t have access from the main page to the shadow root. WebdriverIO has two things to deal with this challenge. The first method is the deep shadow root selector. This allows you to access all of the shadow root elements or filter by defined attributes of the elements in the shadow root.<\/p>\n\n\n\n<p>A different way to access elements in the shadow is using the browser shadow command, which basically allows you to switch to the search within the shadow root.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">    describe('using deep shadow selector (&gt;&gt;&gt;)', () =&gt; {\n        beforeEach(async () =&gt; {\n            await browser.url('https:\/\/lit.dev\/playground\/#sample=docs%2Fwhat-is-lit&amp;view-mode=preview')\n\n            const iframe = await $('&gt;&gt;&gt; iframe[title=\"Project preview\"]')\n            await browser.waitUntil(async () =&gt; (\n                (await iframe.getAttribute('src')) !== ''))\n            \n            await browser.switchToFrame(iframe)\n            await browser.waitUntil(async () =&gt; (await $('my-timer').getText()) !== '')\n        })\n\n        it('should check the timer components to work', async () =&gt; {\n            for (const customElem of await $$('my-timer')) {\n                const originalValue = await customElem.getText()\n                await customElem.$('&gt;&gt;&gt; footer').$('span:first-child').click()\n                await sleep()\n                await customElem.$('&gt;&gt;&gt; footer').$('span:first-child').click()\n                await expect(customElem).not.toHaveTextContaining(originalValue)\n\n                await customElem.$('&gt;&gt;&gt; footer').$('span:last-child').click()\n                await expect(customElem).toHaveTextContaining(originalValue)\n            }\n        })\n    })<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-integrating-with-applitools\">Integrating with Applitools<\/h3>\n\n\n\n<p>Lastly, Christian shared using Applitools with WebdriverIO. The Applitools Eyes SDK for WebdriverIO is imported to take snapshots of the app as the test suite runs and upload them to the Applitools Eyes server.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">if (process.argv.find((arg) =&gt; arg.includes('applitools.e2e.ts'))) {\n    config.services?.push([EyesService, {\n        viewportSize: {width: 1200, height: 800},\n        batch: {name: 'WebdriverIO Test'},\n        useVisualGrid: true,\n        browsersInfo: [\n            {width: 1200, height: 800, name: 'chrome'},\n            {width: 1200, height: 800, name: 'firefox'}\n        ]\n    }])<\/code><\/pre>\n\n\n\n<p>With this imported, our tests can be simplified to remove some of the functional assertions, because Applitools does this for you. From the Applitools Eyes Test Manager, you can see the tests have been compared against Firefox and Chrome at the same time, even though only one test was run.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-webdriverio-selectors-q-amp-a\">WebdriverIO selectors Q&amp;A<\/h2>\n\n\n\n<p>After Christian shared his WebdriverIO demonstration, we turned it over to our Q&amp;A, where Christian responded to questions from the audience.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-using-chrome-devtools\">Using Chrome DevTools<\/h3>\n\n\n\n<p><strong>Audience question<\/strong>: Is there documentation on how to run WebdriverIO in DevTools like this to be able to use the browser and $ and $$ commands? This would be very helpful for us for day-to-day test implementation.<br><strong>Christian\u2019s response<\/strong>: [The demo] is actually not using DevTools at all. It uses ChromeDriver in the background, which is automatically spun up by the test runner using the ChromeDriver service. So there&#8217;s no DevTools involved. You can also use the DevTools protocol to automate the browser. The functionality is the same. WebdriverIO executes the same XPath. There&#8217;s a compliant DevTools implementation to the WebdriverIO protocol so that the WebdriverIO APIs works on both. But you really don&#8217;t need DevTools to use all these accessibility selectors to test your application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-integrating-with-chrome-console\">Integrating with Chrome Console<\/h3>\n\n\n\n<p><strong>Question<\/strong>: How is WebdriverIO integrated with Chrome Console to type await browser.getHtml() etc.?<br><strong>Christian\u2019s response<\/strong>: With component tests, it&#8217;s similar to what other frameworks do. You actually run a website that is generated by WebdriverIO. WebdriverIO injects a couple of JavaScript scripts and it loads web within that page as well. And then it basically sends commands back to the Node.js world where it&#8217;s then executed by ChromeDriver and then the responses are being sent back to the browser. So basically WebdriverIO as a framework is being injected into the browser to give you all the access into the APIs. The actual commands are, however, run by Chrome Driver.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-testing-in-other-local-languages\">Testing in other local languages<\/h3>\n\n\n\n<p><strong>Question<\/strong>: If we&#8217;re also testing in other languages (like English, Spanish, French, etc.), wouldn&#8217;t using the accessibility text fail? Would the ID not be faster in finding the element as well?<br><strong>Christian\u2019s response<\/strong>: If you have a website that has multiple languages and you have a system to inject those or to maintain the languages, you can use this tool to fetch the accessibility name of that particular language you test the website in. Otherwise, you can say I only tested one language, because I would assume it would not be different in other languages. Or you create a library or a JSON file that contains the same selectors for different languages but the same accessibility name for different languages. And then you import that JSON to your test and just reference the label to have the right language. So there are ways to go around it. It would make it more difficult in different languages, obviously, but still from the way to maintain end-to-end tests and maintain tests in general, I would always recommend accessibility names and accessibility labels.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-using-div-board-or-board\">Using div.board or .board<\/h3>\n\n\n\n<p><strong>Question<\/strong>: Do you have a stance\/opinion on div.board versus .board for CSS selectors?<br><strong>Christian\u2019s response<\/strong>: I would always prefer the first one, just more specific. You know, anyone could add another board class name to an input element or what not. And so being very specific is usually the best way to go in my recommendation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-tracking-api-call-execution\">Tracking API call execution<\/h3>\n\n\n\n<p><strong>Question<\/strong>: How can we find out if an API call has executed when we click on an element?<br><strong>Christian\u2019s response<\/strong>: WebdriverIO has mocking capabilities, so you can look into when a certain URL pattern has been called by the browser. Unfortunately, that&#8217;s fairly based on DevTools because WebdriverIO, the first protocol, doesn&#8217;t support it. We are working with the browser vendors and the new WebdriverIO binary protocol to get mocking of URLs and stubbing and all that stuff to land in the new browsers. And so it&#8217;ll be available across not only Chrome, but also Firefox, Safari, and so on.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-working-with-iframes\">Working with iframes<\/h3>\n\n\n\n<p><strong>Question<\/strong>: Is it possible to select elements from an iframe and work with an iframe like normal?<\/p>\n\n\n\n<p><strong>Christian\u2019s response<\/strong>:&nbsp;An iframe is almost similar to a shadow DOM \u2013 just that an iframe has much more browser context than just a shadow DOM. WebdriverIO has an issue currently. To implement the deep shadow selector for iframes as well, you could do three characters and then name any CSS path and it would make finding an iframe very easy. But you can always switch to an iframe and then query it. So it&#8217;s a little bit more difficult with iframes, but it&#8217;s doable.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group pt-xs pb-xs\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"h-learn-more\">Learn more<\/h2>\n\n\n\n<p>So that covers our expert\u2019s takeaways on locating web elements using WebdriverIO. In the <strong><span style=\"text-decoration: underline;\"><a href=\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-cypress\/\" target=\"_blank\" rel=\"noreferrer noopener\">next article in our two-part series<\/a><\/span><\/strong>, I\u2019ll recap Filip\u2019s tutorial using Cypress, as well as the Cypress Q&amp;A with the audience.<\/p>\n\n\n\n<p>If you want to learn more about any of these tools, frameworks like Cypress, WebDriverIO, or specifically <a href=\"https:\/\/testautomationu.applitools.com\/web-element-locator-strategies\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">web element locator strategies<\/span><\/strong><\/a>, be sure to check out <a href=\"http:\/\/testautomationu.applitools.com\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Test Automation University<\/span><\/strong><\/a>. All the courses and content are free. You can also learn more about visual testing with Applitools in the <a href=\"https:\/\/testautomationu.applitools.com\/learningpaths.html?id=visual-testing-java-path\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">Visual Testing learning path<\/span><\/strong><\/a>.<br>Be sure to register for the <a href=\"https:\/\/app14743.cloudwayssites.com\/resources\/webinars\/test-maintainability-robot-framework-selenium\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><span style=\"text-decoration: underline;\">upcoming Let the Engineers Speak webinar series installment on Test Maintainability<\/span><\/strong><\/a> coming in May. Engineers Maaret Pyh\u00e4j\u00e4rvi from Selenium and Ed Manlove from Robot Framework will be discussing test maintenance and test maintainability with a live Q&amp;A.<\/p>\n\n\n<section class=\"article-group\">\n    <div class=\"is-featured\">\n      <div class=\"title-bar\">\n      <div><\/div>\n    <\/div>      <div class=\"row\">\n        <div class=\"col-md-6\">\n          \t<div class=\"item is-primary\">\n\t\t<a href=\"https:\/\/app14743.cloudwayssites.com\/blog\/let-the-engineers-speak-part-5-audience-qa\/\" >\n\t\t\t\t\t\t\t<picture class=\"image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<source srcset=\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2022\/12\/Title-831x540.jpg\" media=\"screen and (min-width: 768px)\" \/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2022\/12\/Title-384x242.jpg\" width=\"384\" height=\"242\" alt=\"\" loading=\"lazy\">\n\t\t\t\t<\/picture>\n\t\t\t\t\t\t<div class=\"content\">\n\t\t\t\t<h3 class=\"title\">Let the Engineers Speak! Part 5: Audience Q&#038;A<\/h3>\n\t\t\t\t\t\t\t\t\t<div class=\"meta\">\n\t\t\t\t\t\tArticles &mdash; 01.11.2023\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/a>\n\t<\/div>\n        <\/div>\n        <div class=\"col-md-6\">\n          \t<div class=\"item is-secondary\">\n\t\t<a href=\"https:\/\/app14743.cloudwayssites.com\/blog\/let-the-engineers-speak-part-4-changing-frameworks\/\" >\n\t\t\t\t\t\t\t<picture class=\"image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2022\/12\/Title-200x200.jpg\" width=\"200\" height=\"200\" alt=\"\" loading=\"lazy\">\n\t\t\t\t<\/picture>\n\t\t\t\t\t\t<div class=\"content\">\n\t\t\t\t<h3 class=\"title\">Let the Engineers Speak! Part 4: Changing Frameworks<\/h3>\n\t\t\t\t\t\t\t\t\t<div class=\"meta\">\n\t\t\t\t\t\tArticles &mdash; 01.05.2023\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/a>\n\t<\/div>\n\t<div class=\"item is-secondary\">\n\t\t<a href=\"https:\/\/app14743.cloudwayssites.com\/blog\/let-the-engineers-speak-part-3-favorite-test-integrations\/\" >\n\t\t\t\t\t\t\t<picture class=\"image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2022\/12\/Title-200x200.jpg\" width=\"200\" height=\"200\" alt=\"\" loading=\"lazy\">\n\t\t\t\t<\/picture>\n\t\t\t\t\t\t<div class=\"content\">\n\t\t\t\t<h3 class=\"title\">Let the Engineers Speak! Part 3: Favorite Test Integrations<\/h3>\n\t\t\t\t\t\t\t\t\t<div class=\"meta\">\n\t\t\t\t\t\tArticles &mdash; 12.28.2022\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/a>\n\t<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n    <\/section><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Earlier this month, Applitools hosted a webinar, Let the Engineers Speak: Selectors, where testing experts discussed one of the most common pain points that pretty much anyone who&#8217;s ever done&#8230;<\/p>\n","protected":false},"author":89,"featured_media":48943,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[12271],"tags":[16882,16881,16883,10847],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.5 (Yoast SEO v24.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using Web Selectors in WebdriverIO<\/title>\n<meta name=\"description\" content=\"Andy Knight recaps testing expert Christian Bromann&#039;s demo and discussions about locating web elements using selectors in WebdriverIO.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Let the Engineers Speak: Selectors in WebdriverIO\" \/>\n<meta property=\"og:description\" content=\"Earlier this month, Applitools hosted a webinar, Let the Engineers Speak: Selectors, where testing experts discussed one of the most common pain points\" \/>\n<meta property=\"og:url\" content=\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\" \/>\n<meta property=\"og:site_name\" content=\"AI-Powered End-to-End Testing | Applitools\" \/>\n<meta property=\"article:published_time\" content=\"2023-03-30T15:59:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-22T16:31:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"831\" \/>\n\t<meta property=\"og:image:height\" content=\"542\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrew Knight\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Knight\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\"},\"author\":{\"name\":\"Andrew Knight\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/a8038d2c9ccd3531090422b6172b125b\"},\"headline\":\"Let the Engineers Speak: Selectors in WebdriverIO\",\"datePublished\":\"2023-03-30T15:59:26+00:00\",\"dateModified\":\"2024-04-22T16:31:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\"},\"wordCount\":2248,\"publisher\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg\",\"keywords\":[\"locators\",\"selectors\",\"web elements\",\"WebdriverIO\"],\"articleSection\":[\"Getting Started\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\",\"url\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\",\"name\":\"Using Web Selectors in WebdriverIO\",\"isPartOf\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg\",\"datePublished\":\"2023-03-30T15:59:26+00:00\",\"dateModified\":\"2024-04-22T16:31:23+00:00\",\"description\":\"Andy Knight recaps testing expert Christian Bromann's demo and discussions about locating web elements using selectors in WebdriverIO.\",\"breadcrumb\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage\",\"url\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg\",\"contentUrl\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg\",\"width\":831,\"height\":542,\"caption\":\"Christian Bromann\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/app14743.cloudwayssites.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Getting Started\",\"item\":\"https:\/\/app14743.cloudwayssites.com\/blog\/category\/getting-started\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Let the Engineers Speak: Selectors in WebdriverIO\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#website\",\"url\":\"https:\/\/app14743.cloudwayssites.com\/\",\"name\":\"Applitools Visual AI\",\"description\":\"Applitools delivers full end-to-end test automation with AI infused at every step.\",\"publisher\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/app14743.cloudwayssites.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#organization\",\"name\":\"Applitools\",\"url\":\"https:\/\/app14743.cloudwayssites.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2020\/03\/applitools.png\",\"contentUrl\":\"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2020\/03\/applitools.png\",\"width\":156,\"height\":28,\"caption\":\"Applitools\"},\"image\":{\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/a8038d2c9ccd3531090422b6172b125b\",\"name\":\"Andrew Knight\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a1117da4074b1fd8692051ab8a3a9528?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a1117da4074b1fd8692051ab8a3a9528?s=96&d=mm&r=g\",\"caption\":\"Andrew Knight\"},\"url\":\"https:\/\/app14743.cloudwayssites.com\/blog\/author\/andyknight\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using Web Selectors in WebdriverIO","description":"Andy Knight recaps testing expert Christian Bromann's demo and discussions about locating web elements using selectors in WebdriverIO.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/","og_locale":"en_US","og_type":"article","og_title":"Let the Engineers Speak: Selectors in WebdriverIO","og_description":"Earlier this month, Applitools hosted a webinar, Let the Engineers Speak: Selectors, where testing experts discussed one of the most common pain points","og_url":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/","og_site_name":"AI-Powered End-to-End Testing | Applitools","article_published_time":"2023-03-30T15:59:26+00:00","article_modified_time":"2024-04-22T16:31:23+00:00","og_image":[{"width":831,"height":542,"url":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg","type":"image\/jpeg"}],"author":"Andrew Knight","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Andrew Knight","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#article","isPartOf":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/"},"author":{"name":"Andrew Knight","@id":"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/a8038d2c9ccd3531090422b6172b125b"},"headline":"Let the Engineers Speak: Selectors in WebdriverIO","datePublished":"2023-03-30T15:59:26+00:00","dateModified":"2024-04-22T16:31:23+00:00","mainEntityOfPage":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/"},"wordCount":2248,"publisher":{"@id":"https:\/\/app14743.cloudwayssites.com\/#organization"},"image":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage"},"thumbnailUrl":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg","keywords":["locators","selectors","web elements","WebdriverIO"],"articleSection":["Getting Started"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/","url":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/","name":"Using Web Selectors in WebdriverIO","isPartOf":{"@id":"https:\/\/app14743.cloudwayssites.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage"},"image":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage"},"thumbnailUrl":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg","datePublished":"2023-03-30T15:59:26+00:00","dateModified":"2024-04-22T16:31:23+00:00","description":"Andy Knight recaps testing expert Christian Bromann's demo and discussions about locating web elements using selectors in WebdriverIO.","breadcrumb":{"@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#primaryimage","url":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg","contentUrl":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2023\/03\/blog_selectors-in-webdriverio-1.jpg","width":831,"height":542,"caption":"Christian Bromann"},{"@type":"BreadcrumbList","@id":"https:\/\/app14743.cloudwayssites.com\/blog\/using-web-selectors-in-webdriverio\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/app14743.cloudwayssites.com\/"},{"@type":"ListItem","position":2,"name":"Getting Started","item":"https:\/\/app14743.cloudwayssites.com\/blog\/category\/getting-started\/"},{"@type":"ListItem","position":3,"name":"Let the Engineers Speak: Selectors in WebdriverIO"}]},{"@type":"WebSite","@id":"https:\/\/app14743.cloudwayssites.com\/#website","url":"https:\/\/app14743.cloudwayssites.com\/","name":"Applitools Visual AI","description":"Applitools delivers full end-to-end test automation with AI infused at every step.","publisher":{"@id":"https:\/\/app14743.cloudwayssites.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/app14743.cloudwayssites.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/app14743.cloudwayssites.com\/#organization","name":"Applitools","url":"https:\/\/app14743.cloudwayssites.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/app14743.cloudwayssites.com\/#\/schema\/logo\/image\/","url":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2020\/03\/applitools.png","contentUrl":"https:\/\/app14743.cloudwayssites.com\/wp-content\/uploads\/2020\/03\/applitools.png","width":156,"height":28,"caption":"Applitools"},"image":{"@id":"https:\/\/app14743.cloudwayssites.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/a8038d2c9ccd3531090422b6172b125b","name":"Andrew Knight","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/app14743.cloudwayssites.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a1117da4074b1fd8692051ab8a3a9528?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a1117da4074b1fd8692051ab8a3a9528?s=96&d=mm&r=g","caption":"Andrew Knight"},"url":"https:\/\/app14743.cloudwayssites.com\/blog\/author\/andyknight\/"}]}},"_links":{"self":[{"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/posts\/48883"}],"collection":[{"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/users\/89"}],"replies":[{"embeddable":true,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/comments?post=48883"}],"version-history":[{"count":0,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/posts\/48883\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/media\/48943"}],"wp:attachment":[{"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/media?parent=48883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/categories?post=48883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/app14743.cloudwayssites.com\/wp-json\/wp\/v2\/tags?post=48883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}