Handling multiple windows in selenium python - python

After clicking the submit button in my application, there will be three windows opened with title as claims, group benefits and controller. By default, the control is in the claims window. I wanted the control to be moved to group benefits window. To do that, i have used windows_handles function to find the number of windows opened so that i can loop it through to find the exact window to which i want to navigate to. However, the script returns only one window as opened, when there are three windows opened upon clicking the submit button. May i know why the script is returning only one window as opened, when the script have opened 3 windows actually please?
import selenium
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver =
webdriver.Ie("c:\\Users\\n0317311\\Desktop\\IEDriverServer.exe")
time.sleep(3)
driver.get("https://test-groupmarkets.lmig.com/LMAuth/gms1nxtlogin.fcc")
time.sleep(3)
uname = driver.find_element_by_name("USER")
uname.send_keys("USERNAME")
upwd = driver.find_element_by_name("PASSWORD")
upwd.send_keys("Password")
uname.send_keys(Keys.RETURN)
time.sleep(2)
windows = driver.window_handles
number_of_windows = len(windows)
print ("number of windows opened:", number_of_windows)
After running the above code, i am expecting the number of windows to be printed as 3 instead of 1, because the code has opened 3 windows upon clicking the submit button.

Related

SendKeys does not work when computer is locked using Selenium

I use python 3.9.5 and selenium 4.1.0 with Microsoft Edge 98.0.1108.43 on Windows 10 to fill a date in a text box with the code below:
#element is the web element I want to fill
element = "element_name"
date = driver.find_element(By.ID, element)
date.click()
date.clear()
#Positionate cursor at text box beginning
for i in range(1,10):
date.send_keys(Keys.ARROW_LEFT)
#Fill the date
date.send_keys("11022022")
I use a Windows task scheduler to run a python script when the computer is locked.
This code uses to work when I am logged in and using the computer, but when it's locked the send keys fail, it used to work with edge version 95, but in recent versions stopped.
Unfortunately, I can't simply replace the value of the element, apparently, the site has some different mechanism to fill it and I must fill it with the keyboard.
<input name="element_name" type="text" value="04/02/2022" id="ctl00_ContentPlaceHolder1_dtInicial_txtData" class="edt" style="width:90px;">
I also have tried to force windows to always focus on browser windows, so the webpage always has the keyboard focus, but it also does not work.
Any hint of how to solve this question? Is it a Bug?
In Selenium there is a state that called headless, it allows you to work with the web page without actually "seeing" it. There is no window opening and everything works virtually. You set this state in the browser options.
EdgeOptions edgeOptions = new EdgeOptions();
edgeOptions.UseChromium = true;
edgeOptions.BinaryLocation =
#"C:\Program Files
(x86)\Microsoft\Edge\Application\msedge.exe";
edgeOptions.AddArgument("headless");
edgeOptions.AddArgument("disable-gpu");
var msedgedriverDir = #"E:\webdriver";
var driver =
new EdgeDriver(msedgedriverDir, edgeOptions);
In Java, there is a class called Robot which mimic keyboard pressing, so try to find the matching library in Python.

Python Selenium Multithreading Different Chrome Instances

I am writing a code in python that opens 20 threads (each going through the same function), each thread opens a different selenium browser instance, each thread is been given a different url as parameter. So I have 20 selenium browsers opened, each on 20 different urls. This works perfect, until I add the user-data-dir selenium chrome option to every browser, in the thread function. I do this, because I want the selenium browsers opened on the same chrome icon on the taskbar (so it won't visually disturb the user). But the problem is : now I have 20 different selenium browsers opened, but all the thread commands are executed on just one (that single one browser navigates to all the 20 given urls, leaving the other 19, basically doing nothing). How can I solve this issue? Can I mix the selenium browsers in one chrome icon in a different way? This is very strange and I looked it up, for days, but nothing seems to solve my problem. I really want to solve this and if anyone knows what might be the problem, I would really appreciate some help. (I hope you understand the question.)
EDIT :
As https://stackoverflow.com/users/6393476/enriquebet mentioned in the comments, I tried using ProcessPoolExecutor, but that did no good, because my program also has a tkinter GUI app, therefore, by implementing this method, it freezes. So I figured I should use a basic multiprocessing program. It worked fine : the 20 drivers opened, with user-data-dir option, the GUI didn't freeze. But my program, also includes a close_browser button for each driver, that closes that specific driver. The problem is : I can't access the driver field, that is initiated after. I hope this code explains my issue (Note: I narrowed it down to just one driver, for avoiding complications) This is the code:
import tkinter as tk
import os
import time
import multiprocessing
import queue
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
class Browser():
pass
def close_browser():
print("Closing browser...")
browser.driver.close()
def start_browser_process(browser):
print("Starting browser...")
browser.driver = webdriver.Chrome(ChromeDriverManager().install())
while True:
browser.driver.get(browser.url)
time.sleep(5)
def start_browser():
browser.process = multiprocessing.Process(target=start_browser_process, args=(browser,))
browser.process.start()
if __name__=='__main__':
browser = Browser()
browser.url = 'https://facebook.com'
root = tk.Tk()
button_start_browser = tk.Button(root, command=start_browser, width=50, height=4, bg='red', text='Start Browser')
button_start_browser.pack()
button_close_browser = tk.Button(root, width=50, height=7, bg='red', command=close_browser, text='Close Browser')
button_close_browser.pack()
root.mainloop()
So, first I create a Browser instance, that, for now, has just one field (an url) and initialize the Tkinter GUI App. Then, I press the Start Browser button, that opens for me a fresh selenium driver on https://facebook.com, that keeps reentering that url, every 5 seconds, also, I assign a new field to the Browser instance : driver. But then, when I press the Close Browser button, I want to access that browser.driver field, in order to close it, they give me this error : AttributeError: 'Browser' object has no attribute 'driver'. This means that I have to dynamically share the driver field between processes. I tried this with Queue, but that still didn't work as python doesn't let you pass queue objects as process arguments. How can I share variables between processes, in this case? Is there another way? I've been searching for 4 days now, but still didn't find the answer. Any answer is much appreciated. If you have questions regarding my issue, please announce me so I can edit the question.

how to switch to windows security window and insert credentials

Here are my steps
1.Using selenium webdriver I am opening Edge
2.Then after click a link it opens popup security window. I am attaching a screenshot
3. I tried to switch that window using many different ways. It is not an alert because when I called for alert it says no such alerts are open.
I tried to call following but it gives error
window_after = driver.window_handles[1]
Following two lines gave me 1 handles:
handles = driver.window_handles
print("Number of handles ", len(handles))
Output:
Number of handles 1
if it is not alert, not a window, what is it? view source code does not print anything.
All i need is insert user name and password and then click "OK" button
I put the program for sleep 20 seconds and then manually selected the cursor to user name text box. The executed following code but it does nothing
ActionChains(driver).send_keys("Test").perform()
Side Note: Need answer for only for Microsoft Edge.
Selenium only works for browser automation. The Windows Security pop-up is an OS-level dialog and Selenium will not be able to recognize it. You could use third party tools like AutoIt with Selenium to automate non-browser based functionality. For the detailed steps, you could refer to this article.

Selenium-Python: interact with system modal dialogs

I am running an app in the browser; and for some actions I was able to simulate actions with keystrokes; but I have a peculiar problem: some actions in my app cause system prompt to pop up, like for example for save or confirm quit.
Is there a way to control these in Selenium python? As example imagine to use keystroke to save a page; then the system dialog (which is not part of the web app), appear and ask you where to save the file. Or imagine the prompt that ask you if you are sure to close the browser window if you have multiple tabs open.
I did try to look for a different window, assuming that I can switch context between windows in the browser, but I find nothing beside the main app, because these are system windows. Is there a workaround for this?
If you are talking about system dialogs, then it's not possible to interact with them using selenium.
However, for browser popups (alerts), just navigate to the popup:
driver.switch_to_alert()
Then, use the methods from the Alert class to interact with the popup. The Alert class contains methods for dismissing, accepting, inputting, and getting text from alert prompts.
Some examples:
Alert(driver).accept()
Alert(driver).dismiss()
Alert(driver).authenticate()
Alert(driver).send_keys(keys_to_send)
Alert(driver).text()
see: https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.alert.html
You could make usage of the Selenium methods to check current window and move to another one:
You can use
driver.window_handles
to find a list of window handles and after try to switch using following methods (selenium documentation).
driver.switch_to_alert()
driver.switch_to.active_element
driver.switch_to.default_content
driver.switch_to.window
Since the application you work on, seems to respond to Selenium commands here it is a working example about opening a popup window, switching selenium scope on it, extract data and close the popup.
The process is repeated for all the products:
for item in driver.find_elements_by_class_name("products"):
item.click() # clicking on item activate a popup
driver.switch_to_alert() #switch to new window
# Get data
driver.find_elements_by_css_selector(".ui-dialog-titlebar-close.ui-corner-all")[0].click() #close window

Is it possible to have the new window opened in selenium, focus as the primary window on your screen?

I'm new to selenium.
I have tried many answers on stack overflow including:
Get focus on the new window in Selenium Webdriver and Python
and
Make sure that browser opened by webdriver is always in focus
None of the questions i have seen seem to work for me.
I'm using python 3.5 and the latest selenium. The window opens and executes anything I tell however it's in the background and never focuses. Is there something I'm missing?
I have tried iterating over the windows and focusing each one but none of this works.
I would really like this to happen as watching the browser as the script executes is the reason why i'm using this tool.
Any suggestions are welcome.
Thanks.
AFAIK you cannot control visibility of content of each opened tab/window automatically. However, you can handle last opened tab/window as below and see what exactly happens on current tab/window:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.google.com")
google_window = driver.current_window_handle # Define main window
print(driver.title) # Title now is "Google". It is currently visible
driver.execute_script("window.open('http://www.bing.com');") # Open Bing window
bing_window = [window for window in driver.window_handles if window != google_window][0] # Define Bing window
driver.switch_to_window(bing_window)
print(driver.title) # Title now is "Bing". It is currently visible
driver.execute_script("window.close();") # Close Bing window
driver.switch_to_window(google_window)
print(driver.title) # Now title is again "Google". It is currently visible
Also you can use driver.get(URL) to open new page in current window and navigate in history with driver.back() and driver.forward()

Categories