How To Solve Selenium Focus Issues [2024]
Himanshu Sheth
Posted On: March 26, 2024
135499 Views
17 Min Read
Do you know that every website or web application comprises different web pages containing different web elements like buttons, text boxes, progress bars, etc.? However, the web is asynchronous in nature. Hence, all the web elements may not be loaded simultaneously, i.e., the web elements might be loaded dynamically using AJAX (Asynchronous JavaScript And XML).
While performing Selenium, your test code or test script could result in erroneous results if it is interacting with a web element that is not yet loaded in the Document Object Model (DOM). Or if it is on another iFrame, tab, or window which is not in focus, or any such scenarios. These types of unexpected erroneous outcomes are known as Selenium focus element issues.
Selenium can only control a browser when its window is in focus. How do you ensure that the Selenium test code interacts with web elements when they are in focus? You can use workarounds like the addition of minimal delay (in seconds) to ensure that the element on which the testing is performed has loaded. Still, that solution is not foolproof as any change in web page design could make the test inefficient. If you are preparing for an interview you can learn more through Selenium interview questions.
This article will cover what the common Selenium Focus Element issues are and how to solve these issues, with examples.
- Selenium Focus Element Issues With Multiple iFrames
- Selenium Focus Element Issues With Multiple Tabs
- Selenium Focus Element Issues With onfocus() And onblur() Callbacks
- How To Handle Selenium Focus Element Issues With Incomplete Page Loading
- Solving Selenium Focus Element Issues On Cloud Selenium Grid
Before we get started, let’s look at some of the prerequisites required for the development. You need to have Python & Selenium installed on your machine. You can download Python installation files for Windows from their official site.
To install Selenium, you should execute pip install selenium on your terminal. PyCharm IDE (Community Edition) is used for implementation, and you can download it from their official site. Next, you should download the WebDriver of the browser on which testing is performed; mentioned below are the locations from where you can download WebDriver for browsers like Firefox, Chrome, Internet Explorer, etc.
For in-depth information about Python’s usage with the Selenium framework for automated cross browser testing.
Now that the setup is ready let’s look at some of the ways to fix Selenium Focus Element issues.
Selenium Focus Element Issues With Multiple iFrames
You would have come across many websites that have advertisements or follow a design where an HTML document is embedded inside another HTML document. That particular web element is called an iFrame. iFrame is defined by the < iframe >< /iframe >
tag in a web page. To switch between different iFrames, you can make use of switch_to(self, frame-reference) API.
For demonstration purposes, we use the webpage, which contains three iFrames. Below is the HTML code of the page, which only details information about the iFrames
1 2 3 4 5 6 7 8 |
iFrame code of the web page https://seleniumhq.github.io/selenium/docs/api/java/index.html <frameset cols="20%,80%" title="Documentation frame" onload="top.loadFrames()"> <frameset rows="30%,70%" title="Left frames" onload="top.loadFrames()"> <frame src="overview-frame.html" name="packageListFrame" title="All Packages"> <frame src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)"> </frameset> <frame src="overview-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes"> <noframes> |
As shown in the HTML code above, the three frames’ names are packageListFrame, packageFrame, and classFrame. To understand the Selenium Focus Element issue better, let us see an example. In the below code, we will be using the iFrames of this webpage. We will simply try to click on “com.thoughtworks.selenium” present on “classFrame.”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# Example - Show Selenium lose focus issue with iFrames from selenium import webdriver from selenium.webdriver.chrome.options import Options import time from time import sleep from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait driver = webdriver.Chrome() driver.get("https://seleniumhq.github.io/selenium/docs/api/java/index.html") # iFrame code of the web page https://seleniumhq.github.io/selenium/docs/api/java/index.html #<frameset cols="20%,80%" title="Documentation frame" onload="top.loadFrames()"> #<frameset rows="30%,70%" title="Left frames" onload="top.loadFrames()"> #<frame src="overview-frame.html" name="packageListFrame" title="All Packages"> #<frame src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)"> #</frameset> #<frame src="overview-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes"> #<noframes> driver.maximize_window() print("Window is maximized") # Test 1 print("[1] - Test on classFrame") driver.find_element_by_link_text("com.thoughtworks.selenium").click() driver.implicitly_wait(20) print("Completion of tests") # Free up the resources driver.close() driver.quit() |
Upon execution, the above test gives the following error:
This error occurs because the WebDriver instance is unable to focus on iFrame “classFrame” upon which the element com.thoughtworks.selenium is present. Similarly, in many such scenarios, when the instance’s focus is on some other iFrame, and the required element is on other, the Selenium Focus Element issues happen.
How To Solve Selenium Lose Focus Issue With Multiple iFrames
There are several ways through which you can navigate between iFrames on a webpage. One of the most simple and popular methods is by using switch_to().frame(). The switch_to().frame() method is used to conveniently switch between iFrames. Let us see how to use the switch_to().frame() method to solve the Selenium lose focus issue:
Name of the iFrame – Each iFrame has a name associated with it. You can find the name using the Inspect Tool in the web browser. The name of the iFrame to which you want to switch to can be passed to driver.switch_to.frame(‘frame_name’) API. In the above case, if you plan to navigate to classFrame iFrame, you simply have to use driver.switch_to.frame(“classFrame”).
If your focus is already there on another iFrame, you need to switch back to the parent frame using the following APIs
1 2 |
driver.switch_to.default_content() driver.switch_to.parent_frame() |
ID of the iFrame – You can also switch between iFrames by using the id associated with the iFrame. driver.find_element_by_id(‘frame-id’) where frame-id is used as a locator to switch to a specific iFrame.
Tag name & Index combination – You can make use of the API driver.find_elements_by_tag_name() along with the index of the destination iFrame.
1 2 |
Iframe-name = driver.find_elements_by_tag_name('tag-name')[index] driver.switch_to.frame(iframe-name) |
Now that we have looked into different ways to switch between iFrames let’s look at an example of switching between three iFrames on the webpage.
driver.switch_to.frame() API is used with the frame-name as the parameter to switch between different iFrames. You can use the HTML source of the webpage to get the iFrame related information or hover over the designated iFrame & inspect element using the Inspect option in the web browser.
Once you are on the required iFrame, search for a particular link using find_element_by_link_text(), and click operation is performed. An implicit wait of 20 seconds (driver.implicitly_wait(20)) is added between different operations performed on two iFrames so that there is enough time to switch to the parent frame. You need to do a trial & error before zeroing on the wait time; however, care has to be taken that the wait time is not too high else it would delay the execution of the other tests.
Selenium Focus Element Issues With Multiple Tabs
There would be multiple test scenarios when using automation testing with Selenium, where tests need to be performed on different browser windows. In such cases, multiple browser windows or multiple tabs have to be opened, and test operations on one browser have to be performed. This is also applicable for automation tests that are done in parallel, which is where Selenium’s focus issues are more common.
Let us see the Selenium lose focus issue with multiple tabs with the help of an example. In the below example, we will try to open multiple tabs (2) and try to run some tests on them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# Example - Selenium lose focus issue with multiple tabs from selenium import webdriver from selenium.webdriver.chrome.options import Options import time from time import sleep from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait primary_url = 'https://www.duckduckgo.com' secondary_url = 'https://www.lambdatest.com' driver = webdriver.Chrome() driver.get(primary_url) print("[1] - Current Page Title is : %s" %driver.title) # Add sleep for checking the results time.sleep(10) driver.execute_script("window.open('');") driver.get(secondary_url) print("[2] - Current Page Title is : %s" %driver.title) # Let us perform some test on the DuckDuckGo tab, i.e. Tab 1 print("Performing operations on the first tab now") # Clicking on "Add DuckDuckGo to Chrome" button self.driver.find_element_by_xpath(self,'//*[@id="content_homepage"]/div[2]/div/div/div/span').click() print("DuckDuckGo added to Chrome") # Free the resources driver.close() driver.quit() |
Upon executing the above test, we will get an error:
This error occurred because the WebDriver instance did not focus on the first tab when we tried to perform tests on it. Instead, the focus was on the second tab because we recently created a new tab. Similarly, when dealing with multiple tabs or windows, this Selenium lose focus issue is very common to occur.
How To Solve Selenium Focus Element Issue With Multiple Tabs
Each window has a window handle associated with it, and that handle is a unique number. For example, if there are two browser windows/browser tabs opened simultaneously, one window’s window handle will be ‘0’, and the other one will be ‘1’. The window handle will be freed once the browser window/tab is closed. To switch tabs, we make use of the driver.window_handles[handle-number] API. So, for instance, to switch to the window with window handle ‘1’, you can use driver.switch_to.window(driver.window_handles[1]).
To open a new tab i.e. child window from the parent browser window, we use the JavaScript executor driver.execute_script(“window.open(”);”). To open a new browser window, you should use driver.execute_script(“window.open(‘secondary-url’, ‘new window’)”)
As seen in the execution snapshot below, the parent window with the test URL DuckDuckGo is first opened. The window handle of this browser window is ‘0’. After a sleep of 10 seconds, a new tab is opened with the test URL LambdaTest, and the window handle associated with this tab is ‘1’. driver.switch_to.window(driver.window_handles[0]) is used to switch back to the parent window (i.e. window handle – 0).
Selenium Focus Element Issues With onfocus() And onblur() Callbacks
There are many websites where you would have encountered a form validation code. For example, suppose you came across a website asking you to create a desired username as per the set criteria. But as soon as you enter the username and move out of the text box, a warning appears stating the entered username is incorrect along with the rules of setting username. These pop-ups or warnings stating messages like the entered password does not meet the requirements, or the password field is left empty, etc. are created with the help of onfocus() and onblur() methods. onfocus() and onblur() events are used in the majority of websites/web applications.
The onfocus() event is fired when a particular web element gets focus. The web element could be a hyperlink (< a >
), input element (< input >
), select element (< select >
), etc. For example, in the below code, the input window’s color would change when it gets focus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <body> Email: <input type="text" onfocus="lambdaTestFunction(this)"> <p>The above text box gets colored as soon as its gets focus, with help of onfocus() event.</p> <script> function lambdaTestFunction(x) { x.style.background = "aqua"; } </script> </body> </html> |
Output:
Before triggering onfocus event
After triggering onfocus event
On the other hand, the onblur() event is fired when the control is shifted from a web element without any change in the web element’s value. For example, the user keeps the user-name field empty, and the focus is shifted to the next field. In the below example, the onblur event will convert all input box characters to lowercase as soon as it loses focus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <body> Email: <input type="text" onblur="LTFunction(this)"> <p>The entered input gets converted to lowercase as soon as the input box loses focus, with help of onblur() event.</p> <script> function LTFunction(x) { x.value = x.value.toLowerCase(); } </script> </body> </html> |
Output:
Before triggering onblur event
After triggering onblur event
Now when these events are triggered simultaneously during automation testing in Selenium, there can be situations when one or the other callback event doesn’t happen or gets triggered. One such scenario is with a dropdown. Suppose there is a dropdown whose value you want to select using Selenium, such that the value of the dropdown changes when the onblur() event is triggered. In such a scenario, the Selenium WebDriver instance might not be able to trigger the onblur() event, thereby resulting in Selenium lose focus issue.
How To Handle Selenium Lose Focus Issues With onfocus() And onblur() Callbacks
Now let us see an example to see how to handle Selenium Focus Element issues using onfocus and onblur events. The example below shows the demonstration of onfocus() and onblur() events on the URL https://output.jsbin.com/remozek/1. execute_script() method through the WebDriver instance is invoked to trigger the required events. driver.execute_script(“arguments[0].blur();”, textfield_path) has arguments[xx] as parameter which is passed from Python code to the JavaScript code that has to be executed.
As shown in the implementation above, the textbox element is located using the XPath expression, where the id of the web element is passed as the input argument.
1 |
textfield_path = driver.find_element_by_xpath("//*[@id='textField']") |
Inspect Element is used to get information about the id of the web element, i.e., text box and JavaScript code that needs to be executed on the execution of the onfocus() and onblur() events.
The code is executed using python < file-name.py >
command, as shown in the output snapshot; the onfocus() and onblur() events are triggered using JavaScript code triggered via Selenium Webdriver.
How To Handle Selenium Focus Element Issues With Incomplete Page Loading
As mentioned in the blog’s starting, the majority of the Selenium Focus Element issues occur when the operation is performed on a web element that is not yet loaded, or the loading of the web page is not yet complete. In this article, we will see two ways to handle such Selenium lose focus issues:
- Wait until the required Web Element’s loading is found, using presence_of_element_located()
- Find the Web Element by inspecting HTML Source, using elem.get_attribute()
In the cases mentioned above of Selenium Focus Element issues, WebDriverWait() with a specified time duration can be used to check the web element’s presence on the page. If the required web element is not present, TimeoutException is invoked, the next set of instructions is executed.
The unittest framework is used to demonstrate automation testing with Selenium. To fetch details about the web locator, i.e., XPath, CSS Selector, Name, Link Text, ID, etc., we again use the Inspect Element option in the web browser. In the example below, we have used the NAME and XPath Selenium locators to perform actions on those web elements.
As seen in the implementation, a WebDriverWait() of 10 seconds is used for the two web elements. Once the web elements are loaded, the required operations are performed on them. However, if the time duration of 10 seconds elapses, TimeOutException() occurs, and the error message No element found is printed. Below is the snapshot of the execution window:
Apart from these mechanisms, there are other ways to tackle Selenium Focus Element issues. One of them is inspecting the HTML source code when doing automation testing with Selenium and checking the presence of an element on the page.
How To Handle Selenium Focus Element Issue By Inspecting HTML Source
Apart from using presence_of_element_located() to check the presence of web elements to handle Selenium Focus Element issues, another approach is to inspect the HTML source for the presence of the required web element. To get the HTML source of a webpage, elem.get_attribute(“innerHTML”) is used, and a search for the required web element is performed to check the presence of the element on the web page.
In the example shown below, the HTML source of the URL under test LambdaTest is written into an external file (optional step), and search for the button home-btn is performed. It matches the string in the HTML source; hence the search operation may take time if the source code is large in size.
These are some mechanisms that can be used in automated cross browser testing for fixing Selenium Focus Element problems. Selenium Focus Element issues are more prevalent when doing parallel testing since the control might shift from one window to another.
This is a common issue when automation testing with Selenium is done using the local Selenium WebDriver. Even if Remote Selenium WebDriver is used for automated cross browser testing, the approach might not be scalable since you cannot have an in-house setup with different combinations of web browsers, operating systems, and devices.
Parallel testing has to be used when using automation testing with Selenium as it improves the test process’s overall efficiency. Rather than local automated cross browser testing, a better approach is to use remote automated cross browser testing on the cloud.
Using a platform like LambdaTest, LambdaTest is an AI-powered test orchestration and execution platform that lets you run manual and automated tests at scale with over 3000+ real devices, browsers and OS combinations. you can perform automated and live interactive automated cross browser testing on 3000+ real browsers and operating systems online. Since tests can be executed in parallel, there is a huge reduction in the overall turn-around time of the testing phase. Also, tests being executed can be triggered on different machines, thereby minimizing the chances of Selenium Focus Element problems that you encounter with automation testing with Selenium on a local machine.
Solving Selenium Focus Element Issues On Cloud Selenium Grid
To get started with automated cross-browser testing on the cloud, you need to create an account on LambdaTest. Once the account is created, you should note the username and access-key are located at your profile section. This combination is used to access the Selenium Grid on LambdaTest. Though we have used the Python language for implementation, you can use other development languages like C#, Perl, Ruby on Rails, etc. to perform automation testing with Selenium on LambdaTest’s Remote Selenium Grid.
Every test that is performed on the LambdaTest grid has a unique test-id associated with it. The Automation tab contains the information of all the automated tests that have been executed so far. To set the browser capabilities, you should use the LambdaTest Capability Generator. Select the development language as Python and choose the correct settings of the browser, operating system, resolution, etc.
For demonstration, we use Chrome 67.0 on macOS (OS X Mavericks) operating system. Now that the setup is ready, we port the implementation that demonstrated the usage of onfocus() and onblur() events in automation testing with Selenium.
As seen in the source code, there are minimal changes to port from local Selenium Grid to Selenium Grid on LambdaTest. The combination of username & pass-key is passed to the remote URL where the execution is performed.
1 |
remote_url = "http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub" |
The remote URL and browser capabilities that were generated using the LambdaTest capabilities generator are passed to the Selenium WebDriver API. Apart from these changes, the rest of the implementation is the same. Using parallel testing, you can perform multiple tests that do automation testing with Selenium.
The code is executed in a similar manner using the local terminal window. You should visit the Automation Tab to check the status of the automation test.
In case you want to perform automated cross browser testing on locally hosted pages, you can use the LambdaTest underpass tunnel app. Using the LambdaTest tunnel app, you can test your locally hosted pages on the LambdaTest Selenium automation platform. You can connect to the LambdaTest servers from your local machine using SSH based integration.
For more guidance on various automation testing tutorial you can Subscribe to the LambdaTest YouTube channel and get complete video guide on topics like Selenium testing, Cypress testing, Playwright testing, and more.
Conclusion
Though automation testing with Selenium is a very popular approach for automated cross browser testing, you might encounter Selenium Focus Element issues, which may impact the tests’ efficiency. Selenium Focus Element issues can be more frequent when tests are executed in parallel. You can use Implicit wait or Explicit wait to ensure that the required web element is present in the DOM, but a better approach would be to use a WebDriverWait() with a wait duration of a few seconds. You can also execute JavaScript code in the Selenium WebDriver, where JavaScript runs in the context of the current frame/window. The automated cross browser testing activity can be shifted to a cross browser testing platform like LambdaTest for improved efficiency and better scalability.
Thank you for reading. If you have any questions, don’t hesitate to reach out via the comment section below.
Got Questions? Drop them on LambdaTest Community. Visit now