<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Selenium – webdriver</title><link>https://trunk--polite-jelly-cc0866.netlify.app/tags/webdriver/</link><description>Recent content in webdriver on Selenium</description><generator>Hugo -- gohugo.io</generator><lastBuildDate>Fri, 08 Dec 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://trunk--polite-jelly-cc0866.netlify.app/tags/webdriver/index.xml" rel="self" type="application/rss+xml"/><item><title>Blog: Removal of AbstractEventListener + EventFiringWebDriver + WebDriverEventListener</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/java-removal-of-deprecated-events-classes/</link><pubDate>Fri, 08 Dec 2023 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/java-removal-of-deprecated-events-classes/</guid><description>
&lt;h3 id="upgrading-to-webdriverlistener-and-eventfiringdecorator">Upgrading to WebDriverListener and EventFiringDecorator&lt;/h3>
&lt;p>Decorating the webdriver&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringWebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">decorate&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="implementing-method-wrappers">Implementing method wrappers&lt;/h3>
&lt;p>One may find the need to have their own custom implementations be used for underlying decorated method calls. An example may be wanting to use your own findElement implementation to store metadata from web elements. One can go down a deep rabbit hole of decorators ( extending WebDriverDecorator and such ), so to keep things simple we will extend EventFiringDecorator since we want a single decorator to handle all our listener events.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebDriverWrapper&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebDriverWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">driver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">By&lt;/span> &lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">testDecorator&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Decorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;?&amp;gt;&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">throws&lt;/span> &lt;span style="color:#000">Throwable&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">String&lt;/span> &lt;span style="color:#000">methodName&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;findElement&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">equals&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">methodName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebDriverWrapper&lt;/span> &lt;span style="color:#000">newDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">WebDriverWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getOriginal&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">newDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">super&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Some notes about the above example, we are only overriding the ‘general’ call method and checking the method name against every call made.
Without going too deep decorators one can also override calls made by class instances to offer a more targeted approach.
Just to expose some more functionality, let&amp;rsquo;s modify our example.
We can modify WebElement context since we might care about child elements and elements found by WebDriver ( WebDriver and WebElement both extend the SearchContext ).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">WebElementWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">element&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">By&lt;/span> &lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">by&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">WebElementDecorator&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Decorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">WebElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&lt;/span> &lt;span style="color:#000">createDecorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">original&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">DefaultDecorated&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;(&lt;/span>&lt;span style="color:#000">original&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">this&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">throws&lt;/span> &lt;span style="color:#000">Throwable&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">String&lt;/span> &lt;span style="color:#000">methodName&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;findElement&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">equals&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">methodName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span> &lt;span style="color:#000">element&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">WebElementWrapper&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">getOriginal&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">((&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">super&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">call&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">};&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the sample above, we are still doing a very similar approach of overriding the call method but now we are also targeting WebElement instances.&lt;/p>
&lt;h3 id="registering-listeners">Registering Listeners&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringWebDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">).&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener1&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">).&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener2&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">EventFiringDecorator&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">listener1&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">listener2&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="listening-to-events">Listening to Events&lt;/h3>
&lt;p>A quality of life change that is featured in WebDriverListener class is the use of ‘default’.
In Java, the &lt;code>default&lt;/code> keyword, when used in the context of an interface method, indicates that the method has a default implementation.
If a class implementing the interface chooses not to override the method, it will inherit the default implementation.
This change allows for splitting up listeners without needing to implement the unnecessary methods you don&amp;rsquo;t need or care about.&lt;/p>
&lt;h4 id="listening-to-specific-events-using-beforeafter-methods-call">Listening to specific events using before/after methods call&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// Old approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">AlertListener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAlertAccept&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// implement every method in interface
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// New approach
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">AlertListener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAccept&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Alert&lt;/span> &lt;span style="color:#000">alert&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// custom implementation goes here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// does not need to implement every method in interface
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="listening-to-generic-events">Listening to Generic Events&lt;/h4>
&lt;p>A change that was brought on is the ability to listen to generic events.
One use case is logging information in a parallelized test suite.
Rather than create a listener and override every method to add a simple log statement, there is now a simpler alternative of overriding one method call.
Below I override beforeAnyCall, but afterAnyCall exists as well which also has the results of the call to the decorated method.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">Listener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">static&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">Logger&lt;/span> &lt;span style="color:#000">LOGGER&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">Logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getLogger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Listener&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Object&lt;/span> &lt;span style="color:#000">target&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There also was an addition listening to more specific generic events.
Going back to the logging example, beforeAnyCall is a good method for debugging information or tracking the actions of a thread but might generate too much noise.
In the same use case we might only care about WebDriver or WebElement calls.
One can override instances of WebDriver and derived objects( WebElement, Alert, etc.) for before/after events.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">Listener&lt;/span> &lt;span style="color:#204a87;font-weight:bold">implements&lt;/span> &lt;span style="color:#000">WebDriverEventListener&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">private&lt;/span> &lt;span style="color:#204a87;font-weight:bold">static&lt;/span> &lt;span style="color:#204a87;font-weight:bold">final&lt;/span> &lt;span style="color:#000">Logger&lt;/span> &lt;span style="color:#000">LOGGER&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#000">Logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getLogger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Listener&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyWebDriverCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebDriver&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#5c35cc;font-weight:bold">@Override&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">beforeAnyWebElementCall&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">WebElement&lt;/span> &lt;span style="color:#000">element&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Method&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#000">Object&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">[]&lt;/span> &lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logger&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">debug&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Thread: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Thread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">currentThread&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Name: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">method&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getName&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34; | Method Args: &amp;#34;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#000">Arrays&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">toString&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">args&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>So that&amp;rsquo;s some general examples on how to transition your code!
Happy testing!&lt;/p></description></item><item><title>Blog: InvalidSelectorException has changed</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/invalid-selector-exception-has-changed/</link><pubDate>Fri, 21 Apr 2023 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2023/invalid-selector-exception-has-changed/</guid><description>
&lt;p>Before Selenium 4.8.2 in Java and C#, when an invalid locator was used to identify an element, the resulting behavior would be
inconsistent in our bindings.&lt;/p>
&lt;p>For example, let&amp;rsquo;s check the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">ArrayList&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;?&lt;/span> &lt;span style="color:#204a87;font-weight:bold">extends&lt;/span> &lt;span style="color:#000">Exception&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#000">expectedExceptions&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">ArrayList&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">NoSuchElementException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">StaleElementReferenceException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ElementNotInteractableException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">add&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">org&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">openqa&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">selenium&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">InvalidElementStateException&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">class&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">FluentWait&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">&amp;lt;&amp;gt;(&lt;/span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">withTimeout&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Duration&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ofMillis&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">ELEMENT_IDENTIFICATION_TIMEOUT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">pollingEvery&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">Duration&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ofMillis&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">ELEMENT_IDENTIFICATION_POLLING_DELAY&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">ignoreAll&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">expectedExceptions&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">until&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">nestedDriver&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&amp;gt;&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">nestedDriver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">findElement&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">xpath&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;invalid-xpath&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)).&lt;/span>&lt;span style="color:#c4a000">click&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ce5c00;font-weight:bold">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The expected result &lt;em>before this change&lt;/em> would be that the driver waits until the timeout expires and then throw an &lt;code>InvalidSelectorException&lt;/code>.&lt;/p>
&lt;p>This doesn&amp;rsquo;t make much sense because a broken/invalid selector would never fix itself, and hence should throw immediately.&lt;/p>
&lt;p>This was discussed and agreed during the &lt;a href="https://www.selenium.dev/meetings/2022/tlc-08-17/#proposals">TLC meeting on August 17, 2022&lt;/a>,
and implemented through the pull request &lt;a href="https://github.com/SeleniumHQ/selenium/pull/11727">11727&lt;/a> and the following
&lt;a href="https://github.com/SeleniumHQ/selenium/commit/f28144eb72ae1df18f267a5250db6b9b41dc1fdc">commit&lt;/a>.&lt;/p>
&lt;p>With the changes mentioned above, an invalid selector will throw an &lt;code>InvalidSelectorException&lt;/code> immediately.&lt;/p>
&lt;p>Please note that this may have an impact on backwards compatibility if you are not expecting this exception to be thrown while
handling invalid locators.&lt;/p>
&lt;p>Stay tuned for updates by following &lt;a href="https://twitter.com/seleniumhq">SeleniumHQ&lt;/a>!&lt;/p>
&lt;p>Happy testing!&lt;/p></description></item><item><title>Blog: BELLATRIX Test Automation Framework for C# and JAVA</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/</link><pubDate>Wed, 16 Nov 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/</guid><description>
&lt;p>Over the last decade, a large ecosystem of Open Source projects has sprouted up around Selenium. Selenium is often used for automating web applications for testing purposes, but it does not include a testing framework.
Nowadays, Selenium Ecosystem initiatives try to give popularity to popular open-source test automation frameworks maintained by people outside of the core Selenium maintainers.
One of these frameworks is BELLATRIX, invented by &lt;a href="https://www.linkedin.com/in/angelovstanton/">Anton Angelov&lt;/a>. It has two versions - C# and Java.
A testing framework is an abstraction in which common code provides generic functionality (which can be selectively overridden) for testing different aspects of our applications- UI, API, security, performance, and many others.&lt;/p>
&lt;h2 id="bellatrix-test-automation-framework">BELLATRIX Test Automation Framework&lt;/h2>
&lt;p>The first version of &lt;strong>&lt;a href="https://bellatrix.solutions/">BELLATRIX&lt;/a>&lt;/strong> appeared on 26 December 2017. It was available only for C# initially, but written on the new back then .NET Core, allowing the framework to be used on all major operating systems (cross-platform).
One huge advantage of BELLATRIX is its cross-technology readiness. It allows you to write tests for different technologies such as Web, Mobile, Desktop, and API. In BELLATRIX, we strive for the API for all modules to be as identical as possible.&lt;/p>
&lt;p>The usage is simple. We suggest cloning BELLATRIX as a GIT sub-module. Then, any customizations, tests, and project-specific plug-ins should be placed in a project outside the BELLATRIX cloned repository. This way, you can quickly update to the latest version.&lt;/p>
&lt;p>&lt;a href="https://bellatrix.solutions/">&lt;strong>BELLATRIX official website, download and releases info&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://github.com/AutomateThePlanet/BELLATRIX">&lt;strong>BELLATRIX official C# GitHub Page&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://github.com/AutomateThePlanet/BELLATRIX-Java">&lt;strong>BELLATRIX official Java GitHub Page&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://docs.bellatrix.solutions/overview/">&lt;strong>BELLATRIX C# Documentation&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://docs.java.bellatrix.solutions/overview/">&lt;strong>BELLATRIX Java Documentation&lt;/strong>&lt;/a>&lt;/p>
&lt;p>Let&amp;rsquo;s investigate how easy it is to create your first test with BELLATRIX in 15 minutes. The sample will showcase how to create a very basic test login into a website:
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/login-form.png"/>
&lt;/figure>
&lt;/p>
&lt;ol>
&lt;li>Open the &lt;strong>BellatrixTestFramework.sln&lt;/strong>&lt;/li>
&lt;/ol>
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/open_the_sln.png"/>
&lt;/figure>
&lt;ol start="2">
&lt;li>Under the &lt;strong>starthere&lt;/strong> folder, find the project you prefer: web, mobile, desktop, API&lt;/li>
&lt;/ol>
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/bellatrix-projects-structure.png"/>
&lt;/figure>
&lt;ol start="3">
&lt;li>Open the &lt;strong>BellatrixLoginTest.cs&lt;/strong> file. There you will find a sample test automating the login.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000">[TestClass]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">class&lt;/span> &lt;span style="color:#000">LoginTestsMSTest&lt;/span> &lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#000">MSTest&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">WebTest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">override&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">TestInit&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Navigation&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Navigate&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;http://demos.bellatrix.solutions/my-account/&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c4a000"> [TestMethod]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">public&lt;/span> &lt;span style="color:#204a87;font-weight:bold">void&lt;/span> &lt;span style="color:#000">SuccessfullyLoginToMyAccount&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">userNameField&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateById&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">TextField&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;username&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">passwordField&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateById&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Password&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;password&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">loginButton&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByXpath&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Button&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;//button[@name=&amp;#39;login&amp;#39;]&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">userNameField&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">SetText&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;info@yourverybusywebsite.com&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">passwordField&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">SetPassword&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;yourverysecretp4ssw0rd$&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">loginButton&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Click&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">myAccountContentDiv&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByClass&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Div&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;woocommerce-MyAccount-content&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">myAccountContentDiv&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateInnerTextContains&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Hello John&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">var&lt;/span> &lt;span style="color:#000">logoutLink&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">App&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Components&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CreateByInnerTextContaining&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Anchor&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Log out&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logoutLink&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsVisible&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">logoutLink&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Click&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All available services are available through the main &lt;strong>App&lt;/strong> class. The &lt;strong>Components&lt;/strong> property provides various &lt;strong>Create&lt;/strong> methods for finding elements. They are generic, so you need to mention the type of the searched element. We have different elements because, for each of them, BELLATRIX offers various additional methods and assertions on top of native WebDriver methods.
The sample code uses MSTest as the default test framework, but by changing the attributes, it will also work out of the box for NUnit. Of course, you need to change the base class namespace too.&lt;/p>
&lt;h2 id="why-bellatrix">Why BELLATRIX?&lt;/h2>
&lt;p>Let&amp;rsquo;s quickly list some of the essential things the framework brings to the table:&lt;/p>
&lt;h3 id="multiple-test-environments-configuration">Multiple Test Environments Configuration&lt;/h3>
&lt;p>Every aspect of the framework can be controlled via a rich JSON configuration designed to work for many test environments. &lt;a href="https://docs.bellatrix.solutions/web-automation/control-browser/#configuration">&lt;strong>Web Project Configuration&lt;/strong>&lt;/a>.&lt;/p>
&lt;h3 id="customization">Customization&lt;/h3>
&lt;p>One of the hardest things to develop is to allow these generic frameworks to be extendable and customizable. Knowing how essential customization is, we utilize different ways to achieve it. The major one is about &lt;a href="https://bellatrix.solutions/features/web/extend-the-framework-to-fit-your-needs/">&lt;strong>writing your own plug-ins&lt;/strong>&lt;/a>.&lt;/p>
&lt;h3 id="test-reliability">Test Reliability&lt;/h3>
&lt;p>One of the biggest problems in test automation is handling timeouts and performing actions on elements that may not be on the page right now. BELLATRIX hides the complexity of searching and &lt;a href="https://bellatrix.solutions/features/web/boost-test-reliability/">&lt;strong>waiting for elements&lt;/strong>&lt;/a>. Furthermore, when you perform an action or assertion against an element, we guarantee that once returned, it will be present.&lt;/p>
&lt;p>A significant part of your tests are the assertions - checking whether some conditions are met. To handle such scenarios, we created elements &lt;strong>Validate&lt;/strong> methods. They internally handle the whole complexity of waiting for some condition to happen.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">updateCart&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsDisabled&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">totalSpan&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;120.00€&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">timeout&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">30&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">sleepInterval&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">2&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">messageAlert&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ValidateIsNotVisible&lt;/span>&lt;span style="color:#000;font-weight:bold">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="complex-controls">Complex Controls&lt;/h3>
&lt;p>BELLATRIX provides API that makes handling HTML tables and grids much easier &lt;strong>&lt;a href="https://docs.bellatrix.solutions/web-automation/complex-components/">HTML tables and grids&lt;/a>&lt;/strong>.
&lt;figure class="img-responsive w-50">
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/bellatrix-test-automation-framework/grid-html-example.png"/>
&lt;/figure>
Here is an example for asserting grid cells:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ForEachCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">cell&lt;/span> &lt;span style="color:#000;font-weight:bold">=&amp;gt;&lt;/span> &lt;span style="color:#000">cell&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">AssertFontSize&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;14px&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Firstname&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;Mary&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">0&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;John&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">TestGrid&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">GetCell&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;lt;&lt;/span>&lt;span style="color:#000">Employee&lt;/span>&lt;span style="color:#000;font-weight:bold">&amp;gt;(&lt;/span>&lt;span style="color:#000">cell&lt;/span> &lt;span style="color:#000;font-weight:bold">=&amp;gt;&lt;/span> &lt;span style="color:#000">cell&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">PersonalEmail&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">ValidateInnerTextIs&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;mary@hotmail.com&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There is much more complex stuff that you can do with both components so check the &lt;strong>&lt;a href="https://docs.bellatrix.solutions/web-automation/complex-components/">official documentation&lt;/a>&lt;/strong>.&lt;/p>
&lt;h2 id="integrations">Integrations&lt;/h2>
&lt;p>Seamlessly integrate the framework with your existing tools and processes. Execute tests in the clouds, distribute and publish test results in reporting solutions. Maybe the most significant differentiators of the framework are its many integrations with popular tools such as Jira/qTest/Allure/ReportPortal and clouds such as AWS, Microsoft Azure, + many more. All these integrations leverage BELLATRIX plug-in architecture. For example, we have plug-ins for automatically generating/updating test cases based on our automated tests in qTest and AzureDevops or similarly creating automatic bug reports with steps to reproduce in Jira or Azure.&lt;/p>
&lt;h3 id="dynamic-test-cases">Dynamic Test Cases&lt;/h3>
&lt;p>Dynamic test cases are a unique feature in BELLATRIX, where the framework automatically generates test cases in a popular test case management system based on your automated tests. It will populate the title, description, and other necessary properties automatically. Moreover, it will generate human-readable steps and expected results. The most significant benefit is that it will keep up to date with your auto-generated test cases over time, no matter what you change in your tests. It is an excellent functionality which allows the non-technical people of your company to see what your tests are doing.&lt;/p>
&lt;h3 id="ai-validation-of-pdfs-and-image">AI Validation of PDFs and Image&lt;/h3>
&lt;p>Azure Computer Vision is a service that can be used to extract printed and handwritten text from images and documents with mixed languages and writing styles. In contrast, Azure Form Recognizer is an AI-powered document extraction service that understands your document.
You are not limited to PDFs only. You can use the same feature for extracting text from complex images. BELLATRIX comes with similar functionality based on the AWS cloud.&lt;/p>
&lt;h3 id="email-testing">Email Testing&lt;/h3>
&lt;p>BELLATRIX offers a few utilities for email testing. There are a few scenarios where we need such integration. The first one is related to creating unique email inboxes and using them to submit various online forms. Later, we can read the emails via the services and check the content of the emails. It might be enough to verify the content via regular C#, or in some cases, we might need to interact with the email content in the browser.&lt;/p>
&lt;p>There are tons of other integrations that we use on a daily basis in many big enterprise projects, such as cloud secrets management for securely storing credentials and other secrets.
&lt;strong>&lt;a href="https://docs.bellatrix.solutions/product-integrations/">All BELLATRIX Integrations&lt;/a>&lt;/strong>&lt;/p>
&lt;p>Using BELLATRIX in your projects might save months/years of effort even if you have the required programming knowledge. This way, you can quickly focus on writing automated tests for your project.
Usually, there are 4-6 major releases each year, including all bug fixes and new features. Check our &lt;strong>&lt;a href="https://bellatrix.solutions/roadmap/release-3-6-0-0-chamaeleon/">release notes history&lt;/a>&lt;/strong>. The framework is fully covered with over 4000 automated tests and offers rich documentation. We make sure to merge the new feature branches only when we are sure that everything is working. If some issue emerges after a major release, it is quickly fixed within a few days.&lt;/p>
&lt;p>For feature requests or bug reports, you can submit them to our GitHub repositories. If you believe that the functionality you developed can be added to the CORE framework or you have a bug fix, please submit a PR so we can discuss it and potentially merge it. For anything else, you can reach us via our &lt;strong>&lt;a href="https://bellatrix.solutions/contact-us/">contact us form&lt;/a>&lt;/strong>.&lt;/p></description></item><item><title>Blog: Dev and Beta Channel Browsers via Docker Selenium</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/dev-and-beta-channel-browsers-via-docker-selenium/</link><pubDate>Tue, 23 Aug 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/dev-and-beta-channel-browsers-via-docker-selenium/</guid><description>
&lt;p>The Docker Selenium browser Beta and Dev channel releases are now regularly published to &lt;a href="https://hub.docker.com/u/selenium">Docker Hub&lt;/a> and updated every two days. This enables testers and developers to test their applications on pre-release versions of Google Chrome, Mozilla Firefox, and Microsoft Edge before their official releases, using container tools, such as Docker. This empowers teams to stay ahead of the curve and catch potential showstoppers in their CI environment &lt;em>before&lt;/em> those issues have an impact on their users.&lt;/p>
&lt;h3 id="what-are-release-channels">What are &amp;ldquo;release channels&amp;rdquo;?&lt;/h3>
&lt;p>Here&amp;rsquo;s some background on release channels: Google, Mozilla, and Microsoft all maintain different &amp;ldquo;channels&amp;rdquo; for their respective browser releases. Most end users use the &amp;ldquo;Stable&amp;rdquo; channel. The Stable channel releases have passed rigorous testing, and these versions are considered &amp;ldquo;production-ready&amp;rdquo;. Up until now, this was the only option for a tester or developer when using Docker Selenium. Today, we&amp;rsquo;re pleased to announce teams can also test on versions of these browsers yet to be released to the general population. These are the Beta and Dev channels.&lt;/p>
&lt;p>For clarity, here is Google&amp;rsquo;s description of these 3 channels from &lt;a href="https://www.chromium.org/getting-involved/dev-channel/">their &amp;ldquo;Chrome Release Channels&amp;rdquo; page&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Stable channel:&lt;/strong> This channel has gotten the full testing and blessing of the Chrome test team, and is the best bet to avoid crashes and other issues. It&amp;rsquo;s updated roughly every two-three weeks for minor releases, and every 6 weeks for major releases.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>&lt;strong>Beta channel:&lt;/strong> If you are interested in seeing what&amp;rsquo;s next, with minimal risk, Beta channel is the place to be. It&amp;rsquo;s updated every week roughly, with major updates coming every six weeks, more than a month before the Stable channel will get them.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>&lt;strong>Dev channel:&lt;/strong> If you want to see what&amp;rsquo;s happening quickly, then you want the Dev channel. The Dev channel gets updated once or twice weekly, and it shows what we&amp;rsquo;re working on right now. There&amp;rsquo;s no lag between major versions, whatever code we&amp;rsquo;ve got, you will get. While this build does get tested, it is still subject to bugs, as we want people to see what&amp;rsquo;s new as soon as possible.&lt;/p>
&lt;/blockquote>
&lt;h3 id="standalone-usage">Standalone Usage:&lt;/h3>
&lt;p>To use these new Docker Selenium container images in Standalone mode, run the following commands:&lt;/p>
&lt;p>&lt;strong>Chrome Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Chrome Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Firefox Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Firefox Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Edge Beta:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:beta
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Edge Dev:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="selenium-grid">Selenium Grid&lt;/h3>
&lt;p>To run these container images in a Selenium Grid, we&amp;rsquo;ll use docker-compose. For instance, this example shows how to run a Selenium Grid with Chrome, Firefox, and Edge on the Beta channel:&lt;/p>
&lt;p>&lt;strong>docker-compose-v3-beta-channel.yml:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># To execute this docker-compose yml file use `docker-compose -f docker-compose-v3-beta-channel.yml up`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># Add the `-d` flag at the end for detached execution&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"># To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3-beta-channel.yml down`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>version: &lt;span style="color:#4e9a06">&amp;#34;3&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>services:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chrome:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-chrome:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> edge:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-edge:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> firefox:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/node-firefox:beta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shm_size: 2gb
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> depends_on:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> environment:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_HOST&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_PUBLISH_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4442&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#000">SE_EVENT_BUS_SUBSCRIBE_PORT&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">=&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">4443&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> selenium-hub:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> image: selenium/hub:latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> container_name: selenium-hub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ports:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4442:4442&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4443:4443&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#4e9a06">&amp;#34;4444:4444&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To run on the more cutting edge &amp;ndash; and hence potentially more buggy &amp;ndash; Dev channel, simply replace the &amp;ldquo;beta&amp;rdquo; tags with &amp;ldquo;dev&amp;rdquo;.&lt;/p>
&lt;h3 id="support">Support&lt;/h3>
&lt;p>These Beta and Dev images represent pre-release browsers and WebDrivers, and they&amp;rsquo;re not guaranteed to be 100% stable. Should you run into any issues with these images, support from the Selenium community is limited and is dependent on the browser vendors. However, if you believe the issue is related to Selenium, please contact us in the &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/support/">various support channels&lt;/a>.&lt;/p></description></item><item><title>Blog: Removing Legacy Protocol Support</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</link><pubDate>Fri, 20 May 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/legacy-protocol-support/</guid><description>
&lt;p>The Selenium team prides itself on how seriously it takes backwards compatibility.
A lot of care has gone into the Java bindings, especially, to ensure very few breaking changes over the years.
There is Selenium code written 15 years ago that can still run with Selenium 4 libraries!
Providing this exceptional amount of support comes with a large maintenance burden, though,
and we need to be able to properly meet the needs of the vast majority of our userbase.&lt;/p>
&lt;p>TL/DR:&lt;/p>
&lt;ul>
&lt;li>Support for the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
will be removed from Java Selenium 4.9 (other languages have already removed this support)&lt;/li>
&lt;li>Protocol conversions will stop in Selenium 4.9 Grid&lt;/li>
&lt;li>You can ensure your sessions are W3C compliant by using
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/#after">Browser Options classes&lt;/a>
instead of the deprecated Desired Capabilities classes (and avoid using &amp;ldquo;set capability&amp;rdquo; methods directly)&lt;/li>
&lt;li>If you rely on the current protocol conversion functionality, and it works for you,
you can continue to use it with Selenium Grid 4.8&lt;/li>
&lt;/ul>
&lt;p>By far the biggest challenge in the past seven years of Selenium development has been
transitioning the underlying implementation from the legacy &lt;a href="https://www.selenium.dev/documentation/legacy/json_wire_protocol/">JSON Wire Protocol&lt;/a>
to the new standardized &lt;a href="https://w3c.github.io/webdriver/">W3C WebDriver Protocol&lt;/a>.
Because the WebDriver specification was being actively developed at the time,
Selenium 3 supported both protocols simultaneously.
We implemented &amp;ldquo;handshake&amp;rdquo; code to determine which protocol to use.
When starting a session, Selenium would package the provided capabilities in both legacy and W3C formats,
send them to the driver/server, and use whichever protocol was returned.
This worked well for the most part. For many users, no changes were necessary to get
W3C compliant sessions from new browsers (Firefox 47+ and Chrome 75+).&lt;/p>
&lt;p>For the Java bindings, it was decided to take this approach one step further.
Instead of just sending along what was provided in both formats,
the code converted capabilities from the legacy protocol to the W3C protocol on behalf of the user.
The Selenium Grid makes use of this code, so, regardless of which client language sends legacy capabilities to it,
the Grid translates it to the W3C protocol for communication with the driver and then
re-translates the results back to the legacy protocol.
Because the code must make some assumptions and guesses for this to work, there are a lot of frustrating edge cases.&lt;/p>
&lt;p>For Selenium 4.0, the Ruby, JavaScript, and .NET bindings, each removed the handshake code,
so no legacy commands are used. Due to some issues that couldn&amp;rsquo;t be resolved before freezing the 3.x code,
Python is waiting until Selenium 4.9 to remove its handshake code.
The Selenium team intended to continue to support both protocols in the
Grid and Java bindings throughout the 4.x releases, but running test suites written for Selenium 2
on the Selenium 4 Grid resulted in a larger than expected number of failures.
Half a dozen bugs were discovered, some with a large effect.&lt;/p>
&lt;p>The code in question is sufficiently complex that fixing the bugs
without causing new problems would be a significant challenge.
As such, we’ve decided to start simplifying the code base again by explicitly
not supporting capabilities and commands from the legacy protocol in any of the Selenium codebase.
If you are using the latest version of Java Selenium, everything that will be removed
has already been marked deprecated, so double-check your usage to ensure there aren&amp;rsquo;t any surprises.&lt;/p>
&lt;p>If you’re interested in the nitty-gritty details of some of the issues we found
exploring this problem, you can look at the discussion in
&lt;a href="https://github.com/SeleniumHQ/selenium/issues/10374">Selenium Issue #10374&lt;/a>.&lt;/p>
&lt;p>For more information on ensuring compatibility with the Grid, please follow our
&lt;a href="https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/">Selenium 4 Upgrade Guide&lt;/a>&lt;/p></description></item><item><title>Blog: Locate your locators - Python bindings changes upcoming</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/python-locators-se4/</link><pubDate>Tue, 01 Feb 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/python-locators-se4/</guid><description>
&lt;p>In real estate, the mantra for finding a new house or office space is
&amp;ldquo;location, location, location!&amp;rdquo;.
It could be said that when working with Selenium, a critical aspect of
writing tests is &amp;ldquo;locators, locators, locators!&amp;rdquo;.
Having a robust locator strategy - in your app under test and in
your test framework - is highly important for effective testing.&lt;/p>
&lt;p>If you are a Pythonista like myself and using Selenium for your test automation,
then there are some important changes coming to how locators are defined and used.&lt;/p>
&lt;p>Sometime after Selenium 4.2, the Python Selenium bindings will remove
locator-specific methods for finding elements. This means that the methods&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_id&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_id&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_name&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_tag_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_tag&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_css_selector&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_selector&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_class_name&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_class&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_link_text&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_text&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_partial_link_text&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_other_text&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_xpath&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;some_xpath&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>will be removed. All of these methods are in fact special cases of&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By_object&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;some_locator&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>so this approach is now preferred (required, even) with the Python bindings.&lt;/p>
&lt;p>Note that it&amp;rsquo;s good practice to use the
&lt;a href="https://www.selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.by.html#module-selenium.webdriver.common.by">By object&lt;/a>
which has specific values for using particular locator strategies. For example, this line&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_id&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element_by_css_selectors&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>becomes&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ID&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">By&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">CSS_SELECTOR&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you&amp;rsquo;re really desperate however you can use strings instead of the By object:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;id&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;submit_button&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">click&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">find_element&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#39;css selector&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;.myelement child&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">text&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you have any plans to upgrade your Selenium client for your Python tests
to recent versions of Selenium 4, definitely keep these changes in mind.
It&amp;rsquo;s a good time to update your locator strategy and structure.&lt;/p>
&lt;p>(This article was originally posted
&lt;a href="https://simplythetest.tumblr.com/post/674917293614039040/locate-your-locators-python-bindings-changes">here&lt;/a>.
Thanks to the Selenium core contributors for adding this here!)&lt;/p></description></item><item><title>Blog: IE Mode in Edge supported by IEDriver</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/ie-edge-support/</link><pubDate>Tue, 18 Jan 2022 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2022/ie-edge-support/</guid><description>
&lt;p>With the retirement of Internet Explorer 11 (IE 11) later this year, the folks in Redmond have helped the
Selenium project with getting IE Mode in Microsoft Edge working in IEDriver.&lt;/p>
&lt;p>IE 11 is due to retire on 15 June 2022 for certain versions of Windows 10. After this date, the Selenium project
recommends that you test your IE sites with IE Mode in Microsoft Edge. The Selenium Project will not remove
support for IE 11 when it retires but we will not actively fix issues as we have done with previous versions of IE.&lt;/p>
&lt;p>The Microsoft Edge team have committed to supporting IE Mode in Edge until 2029 when support for Windows 10 is retired.&lt;/p>
&lt;p>Microsoft have written up all the details on &lt;a href="https://techcommunity.microsoft.com/t5/windows-it-pro-blog/new-testing-tools-to-help-prepare-for-ie-retirement/ba-p/3059947">how to use and how to migrate your site&lt;/a>
and we recommend you go read and follow their steps to make sure you&amp;rsquo;re ready.&lt;/p></description></item><item><title>Blog: A Tour of 4: New Commands</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/a-tour-of-4-new-commands/</link><pubDate>Wed, 13 Oct 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/a-tour-of-4-new-commands/</guid><description>
&lt;p>Before we ship Selenium 4, I thought it would be nice to introduce
some of the new features in-depth. Of course, all of the features
we&amp;rsquo;re covering are in the main &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/documentation/webdriver/">WebDriver documentation&lt;/a>, so if
you&amp;rsquo;re not one for reading blog posts, then feel free to dive in
there!&lt;/p>
&lt;p>You may well be familiar with how to start a Selenium server: you just
do something like &lt;code>java -jar selenium-server-4.0.0.jar standalone&lt;/code> and
away you go! But with Selenium 4, there are some more things you can
do with this jar.&lt;/p>
&lt;p>Least obviously, the server jar is an exectuable on its own. If you&amp;rsquo;re
using Linux or macOS, and have Java installed, you can make the jar
executable (eg. &lt;code>chmod 755 selenium-server-4.0.0.jar&lt;/code>), rename it to
something like &lt;code>selenium&lt;/code> and put it on your &lt;code>$PATH&lt;/code>. That way, rather
than writing &lt;code>java -jar ...&lt;/code> you can simply run &lt;code>selenium&lt;/code>.&lt;/p>
&lt;p>Now you&amp;rsquo;ve done that, if you run &lt;code>selenium&lt;/code> with &lt;code>selenium --help&lt;/code>
you&amp;rsquo;ll get a handy list of the available sub-commands you can
execute. There are the old favourites, such as &lt;code>standalone&lt;/code> (for
starting a standalone selenium server), and &lt;code>hub&lt;/code> and &lt;code>node&lt;/code> (for
starting a Selenium &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/documentation/grid/setting_up_your_own_grid/#hub-and-node">Hub and Node&lt;/a> setup), but there are
other interesting commands that are new to Selenium 4.&lt;/p>
&lt;p>The first of these is &lt;code>info&lt;/code>. We&amp;rsquo;ve added this to provide easy to find
and access documentation on common tasks when using the selenium
server. If you run &lt;code>selenium info&lt;/code> on its own, you&amp;rsquo;ll see something
like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">Info&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">====&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>You can find out more about topics concerning Selenium Grid by running the
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#4e9a06">&amp;#34;info&amp;#34;&lt;/span> &lt;span style="color:#204a87">command&lt;/span> followed by:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* config - Help on how to configure Selenium
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* tracing - Help on how distributed tracing works with selenium
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* security - Help on how how to secure communications to and within selenium
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* sessionmap - Help on different types of sessionmap and how to start them.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Each topic will give you enough information to &lt;span style="color:#204a87">help&lt;/span> you get started, and contains
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>some pointers on our site to provide more &lt;span style="color:#204a87">complete&lt;/span> information.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To get more information on a particular topic, just add the name of
the topic, for example &lt;code>selenium info security&lt;/code>. The hope is that this
will make it less daunting to deal with Selenium, and give you a great
place to get started with some of the more complicated topics around
running a Selenium Grid.&lt;/p>
&lt;p>Although it&amp;rsquo;s incredibly flexible, the &lt;code>selenium&lt;/code> command offers a
daunting list of command line flags. How are you supposed to remember
them all? You&amp;rsquo;re not! Instead, let &lt;code>selenium completion&lt;/code> take the
strain for you. If you&amp;rsquo;re a zsh user, then just &lt;code>source &amp;lt;(selenium completion zsh)&lt;/code>, and now you have tab completion for the
sub-commands, as well as for all the flags, including examples of how
to use them.&lt;/p>
&lt;p>And, finally, there are some hidden flags. We hid them because they
can be a little bit confusing to use or understand what they&amp;rsquo;re meant
to do, but one that can be very useful when debugging how your Grid is
configured is the &lt;code>--dump-config&lt;/code> flag. When run with a server command
such as &lt;code>standalone&lt;/code> or &lt;code>hub&lt;/code>, it will dump the configuration options
used by the Grid as a JSON blob. This can be helpful for tracking down
subtle issues with configurations, especially when using environment
properties for configuration.&lt;/p></description></item><item><title>Blog: A Tour of 4: Authentication</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/a-tour-of-4-authentication/</link><pubDate>Sun, 10 Oct 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/a-tour-of-4-authentication/</guid><description>
&lt;p>Before we ship Selenium 4, I thought it would be nice to introduce
some of the new features in-depth. Of course, all of the features
we&amp;rsquo;re covering are in the main &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/documentation/webdriver/">WebDriver documentation&lt;/a>, so if
you&amp;rsquo;re not one for reading blog posts, then feel free to dive in
there!&lt;/p>
&lt;p>The first thing I&amp;rsquo;d like to introduce you to is Selenium 4&amp;rsquo;s new-found
ability to authenticate to websites. We&amp;rsquo;ve always been able to handle
&amp;ldquo;form-based&amp;rdquo; authentication, where a login page has some &lt;code>INPUT&lt;/code>
elements that you need to enter the user name and password, but
handling sites that use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication">basic or digest
authentication&lt;/a> has always been harder. When using
Selenium 3, the advice has been to get the login cookie and set it on
your session before accessing the site, but you can now just call a
&lt;code>register&lt;/code> method to add a user name and password (or, in the future,
other kinds of authentication credentials)&lt;/p>
&lt;p>In short, in Selenium 4, the process has become less
complicated. Perhaps an example will help?&lt;/p>
&lt;ul class="nav nav-tabs" id="tabs-0" role="tablist">
&lt;li class="nav-item">
&lt;button class="nav-link active"
id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
data-td-tp-persist="java" aria-controls="tabs-00-00" aria-selected="true">
Java
&lt;/button>
&lt;/li>&lt;li class="nav-item">
&lt;button class="nav-link"
id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
data-td-tp-persist="ruby" aria-controls="tabs-00-01" aria-selected="false">
Ruby
&lt;/button>
&lt;/li>
&lt;/ul>
&lt;div class="tab-content" id="tabs-0-content">
&lt;div class="tab-pane fade show active"
id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-Java" data-lang="Java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// This &amp;#34;HasAuthentication&amp;#34; interface is the key!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#000">HasAuthentication&lt;/span> &lt;span style="color:#000">authentication&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#000">HasAuthentication&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">)&lt;/span> &lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// You can either register something for all sites
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#000">authentication&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(()&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&amp;gt;&lt;/span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">UsernameAndPassword&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;admin&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;admin&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// Or use something different for specific sites
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">&lt;/span>&lt;span style="color:#000">authentication&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">register&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">uri&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&amp;gt;&lt;/span> &lt;span style="color:#000">uri&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#c4a000">getHost&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">().&lt;/span>&lt;span style="color:#c4a000">contains&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;mysite.com&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">new&lt;/span> &lt;span style="color:#000">UsernameAndPassword&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;AzureDiamond&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;hunter2&amp;#34;&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;div class="tab-pane fade"
id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-Ruby" data-lang="Ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000">driver&lt;/span>&lt;span style="color:#ce5c00;font-weight:bold">.&lt;/span>&lt;span style="color:#000">register&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">username&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;admin&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">password&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#4e9a06">&amp;#39;admin&amp;#39;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;/div>
&lt;p>Once you&amp;rsquo;ve done this, every time the &lt;code>driver&lt;/code> loads a page that needs
authentication, it will automatically use the user name and password
you&amp;rsquo;ve given it.&lt;/p>
&lt;p>This feature is currently implemented on top of Selenium 4&amp;rsquo;s &lt;a href="https://chromedevtools.github.io/devtools-protocol/">CDP&lt;/a>
support, and so only works on those browser that support that
protocol, but as we push forwards with development of &lt;a href="https://w3c.github.io/webdriver-bidi/">WebDriver
Bidi&lt;/a> implementations will switch to that when they can.&lt;/p></description></item><item><title>Blog: Results of the first ever selenium survey</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-survey-results/</link><pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2021/selenium-survey-results/</guid><description>
&lt;p>Below is a summary of the Selenium survey that was collected.&lt;/p>
&lt;h2 id="batteries-included">Batteries included&lt;/h2>
&lt;h3 id="browser-management">Browser Management&lt;/h3>
&lt;p>Unsurprisingly, people find having to manage browsers a task they wish they didn’t have to do and wish that Selenium did this. 59.5% of respondents want Selenium to manage the browsers for them. This, though the question didn’t ask this, is to include the browser drivers.&lt;/p>
&lt;h3 id="frameworks">Frameworks&lt;/h3>
&lt;p>The results show an interesting view into framework usage. 61% of users use a framework. When we look closer at some of the responses there could be a little language bias in there. Some responses in the “both” category are “depends on the language” or “depends on the project”. Frameworks, from a couple responses seem to be around JavaScript mostly.&lt;/p>
&lt;h2 id="how-tests-are-run">How tests are run&lt;/h2>
&lt;p>One of the questions that was the most surprising was that people dislike running their tests in headless. 57% of people don’t want headless. This is surprising since puppeteer and playwright are up and coming tools that default to headless.&lt;/p>
&lt;h3 id="browsers">Browsers&lt;/h3>
&lt;p>People tend to favour evergreen, or the latest version from auto updating browsers, with over 55% of people wanting that. When we look at the data closer then people tend to do evergreen and then a specific version for IE.&lt;/p>
&lt;p>People are also, overwhelmingly I should add, wanting to test on multiple browsers. 78% of people test with multiple browsers. This goes against the Chrome only support that we see on social media. The most used browsers for testing are (Percentage of respondents testing with browser):&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Google Chrome (98%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Firefox (67%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Microsoft Edge (33%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Safari (29%)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>IE (13.5%)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>One thing that is clear is that Testing against multiple browsers is hard. 51.6% say it’s hard and a further 27.3% being 3 out of 5. This is likely where some frameworks are becoming popular as it removes some of the need to understand the asynchronicity of browsers. This still has its problems in puppeteer and playwright as they add similar wait libraries to what Selenium has.&lt;/p>
&lt;h3 id="mobile-browsers">Mobile Browsers&lt;/h3>
&lt;p>One of the most surprising things to have come out of survey was the want to use mobile browsers more.&lt;/p>
&lt;p>Of the 410 respondents 367 want to test on mobile. Interestingly, this goes well past just Chrome for Android and Safari for iOS.&lt;/p>
&lt;p>Below is a list of browsers and percentage of users wanting to use it. Questions were designed for Android unless it said iOS. See note at the end of the section.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Firefox for Android: 38%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Chrome: 91%*&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Microsoft Edge: 14%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Samsung Internet: 16.6%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Safari on iOS: 69%&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>*Note that the questionaire only mentioned Chrome so it could be a conflation between platforms here. 1 Person used the other field to add Chrome for iOS.&lt;/p>
&lt;h3 id="language-support">Language support&lt;/h3>
&lt;p>Language support is what one would suspect with most users using Java or python.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>java: 67%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>python: 31%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>ruby: 6.1%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>.NET: 17.6%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>JavaScript: 21.4%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>PHP: 1.5%&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="improvements">Improvements&lt;/h2>
&lt;p>After reviewing the “What one thing would you improve about Selenium I was able to narrow most of the responses down to similar types.&lt;/p>
&lt;p>Below is a breakdown of the issues that people would like to see improved.&lt;/p>
&lt;figure>
&lt;img src="https://trunk--polite-jelly-cc0866.netlify.app/images/blog/2021/breakdown_of_answers.png"
alt="Breakdown of answers of areas needing improvement. Main 3 areas are flakiness, documentation, Browser Management, Shadow DOM"/>
&lt;/figure>
&lt;h2 id="happiness">Happiness&lt;/h2>
&lt;p>Of the 410 respondents, 219 had something nice to say about Selenium and were thankful for the product being around.&lt;/p>
&lt;p>Some of the main reasons are simplicity of APIs, good backwards compatibility, and it being open source&lt;/p></description></item><item><title>Blog: Browser Testing and Tools WG Meeting @ TPAC 2020</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/webdriver-tpac-meeting-2020/</link><pubDate>Thu, 29 Oct 2020 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2020/webdriver-tpac-meeting-2020/</guid><description>
&lt;p>It&amp;rsquo;s that time of the year where working groups from the W3C meet up to discuss the various standards that
are being worked on.&lt;/p>
&lt;p>Within the Browser Testing and Tools Working Group, there are 2 different standards.&lt;/p>
&lt;p>We have:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://w3c.github.io/webdriver/">WebDriver&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://w3c.github.io/webdriver-bidi">WebDriver-Bidi&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The first is what is commonly supported by the Selenium Project and has support from Apple, Mozilla, Microsoft, and Google in their browsers. It is also supported by various Selenium in the cloud providers like Sauce Labs and BrowserStack.&lt;/p>
&lt;p>As the world has moved on we have felt the need to add new APIs and move Selenium to be more event-driven. This is where we are learning, and collaborating, with projects like Puppeteer to make sure that we can improve the Browser Automation space. This is where the &lt;a href="https://w3c.github.io/webdriver-bidi">WebDriver-Bidi&lt;/a> Specification comes in. It has broad support from the browser vendors so you can use official browsers and not be limited by the JavaScript sandbox. Some of the newer frameworks can&amp;rsquo;t guarantee that.&lt;/p>
&lt;p>If you&amp;rsquo;re curious about we discussed this week, feel free to read it up on the &lt;a href="https://www.w3.org/wiki/WebDriver/2020-TPAC">W3 Wiki&lt;/a>.&lt;/p>
&lt;p>This post was originally shared on David Burns&amp;rsquo; &lt;a href="https://www.theautomatedtester.co.uk/blog/2020/webdriver-tpac-meeting-2020/">Blog&lt;/a>&lt;/p></description></item><item><title>Blog: Atoms have come to Selenium IDE</title><link>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/atoms-have-come-to-selenium-ide/</link><pubDate>Thu, 09 Dec 2010 00:00:00 +0000</pubDate><guid>https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/atoms-have-come-to-selenium-ide/</guid><description>
&lt;p>As mentioned in Simon’s &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/going-atomic-why/">Going Atomic: Why?&lt;/a> and &lt;a href="https://trunk--polite-jelly-cc0866.netlify.app/blog/2010/going-atomic-how/">Going Atomic: How&lt;/a>, part of the merging of Selenium and WebDriver is to share common code between the two. And as of the 1.0.10 release of Selenium IDE, this merged code, ‘atoms’ is now included.&lt;/p>
&lt;p>Some early users of this release are noticing that this the atom that drives assertAttribute and verifyAttribute is causing their scripts to break. This post explains the ‘why’ and suggests how to fix them as well.&lt;/p>
&lt;p>The HTML spec has the notion of a &lt;em>boolean attribute&lt;/em> which is one that does something just by being there rather than by its value; &lt;em>checked&lt;/em> and &lt;em>selected&lt;/em> are two such examples of this. Optionally, you could give these boolean attributes a value that is the same as their name (checked=”checked”) and your page would still validate, but really, the browsers only care that the attribute exist.&lt;/p>
&lt;p>Prior to 1.0.10, it was not uncommon for people to do something like&lt;/p>
&lt;pre tabindex="0">&lt;code> assertAttribute | checkbox@checked | checked
&lt;/code>&lt;/pre>&lt;p>which fetches the value of the checked attribute on the checkbox with the id or name of checkbox and fails the script is the value is not checked.&lt;/p>
&lt;p>In 1.0.10 though, that will fail &lt;em>even if it is checked&lt;/em>. This is because checked is a boolean attribute and will now return either true or throw an exception saying the attribute doesn’t exist. Redoing the above step check that the boolean attribute is set results in:&lt;/p>
&lt;pre tabindex="0">&lt;code> assertAttribute | checkbox@checked | true
&lt;/code>&lt;/pre>&lt;p>Thankfully, most of the real-world interaction with boolean attributes is focused on checked, disabled, hidden and selected and in these cases using assertAttribute is not really the right thing to do. Instead, the Selenium API provides wrappers for you to use.&lt;br />&lt;/p>
&lt;table>
&lt;tr>
&lt;td>checked&lt;/td>
&lt;td>assertChecked(locator), assertNotChecked(locator), verifyChecked(locator), verifyNotChecked(locator)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>disabled&lt;/td>
&lt;td>assertEditable(locator), assertNotEditable(locator), verifyEditable(locator), verifyNotEditable(locator)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>hidden&lt;/td>
&lt;td>assertVisible(locator), assertNotVisible(locator), verifyVisible(locator), verifyNotVisible(locator)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>selected&lt;/td>
&lt;td>assertSelected*(locator, pattern), assertNotSelected*(locator, pattern), verifySelected*(locator, pattern), verifyNotSelected*(locator, pattern)&lt;/td>
&lt;/tr>
&lt;/table>
&lt;p>Checking for the absence of a boolean attribute that doesn’t have a nice wrapper is a bit of a pain though. In this example I am checking that the boolean attribute &lt;em>multiple&lt;/em> is not on the select element with the name elephants.&lt;/p>
&lt;pre tabindex="0">&lt;code> assertEval | this.browserbot.findElement(&amp;#34;css=select[name=elephants]&amp;#34;).getAttribute(&amp;#34;multiple&amp;#34;); | null
&lt;/code>&lt;/pre>&lt;p>If you find yourself doing this very often, I suggest you wrap it up in a user-extension inside a &lt;a href="http://seleniumhq.org/projects/ide/plugins.html">plugin&lt;/a> as something like&lt;/p>
&lt;pre tabindex="0">&lt;code> assertBooleanAttribute | css=select[name=elephants]@multiple | false
assertBooleanAttribute | css=select[name=elephants]@multiple | true
&lt;/code>&lt;/pre>&lt;p>Hopefully this addresses some of the eventual ‘why the heck did my script break!?!?!’ problems that will no double crop up once Selenium IDE 1.0.10 gets wider distribution.&lt;/p></description></item></channel></rss>