Python Selenium Webdriver Handling Multiple Windows At The Same Time - python

I am working on a project and in this project there are two webpages I need to examine.I have to open these two webpages at the same time in different windows and examine them at the same time.
There must be two windows and there is a function that checks an element's status.But this function must be checking them at the same time.How can I solve this problem?
Thanks

You can open more than one browser at a time:
from selenium import webdriver
driver1 = webdriver.Firefox()
driver2 = webdriver.Firefox()
driver1.get(...)
driver2.get(...)
If you want two windows into the current driver session you can use a little javascipt to open a second window with a single driver:
driver.execute_script("$(window.open('http://www.example.com'))")
window1 = driver.window_handles[0]
window2 = driver.window_handles[1]
# test the first window
driver.switch_to_window(window1)
...
# test the second window
driver.switch_to_window(window2)
...

I'm not sure about doing at at exactly the same time, but you could open one of the pages in a separate tab, then move between the two do your comparison.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
ArrayList<String> tabs = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabs.get(0));
***get value to compare****
driver.switchTo().window(tabs.get(1));
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"Keys.TAB");
***get second value and compare***
If not, perhaps look into using Selenium Grid to run two tests in parallel.
I only spotted that you're working in Python after writing the answer, but im sure there's an equivalent.

Related

Python/Selenium: Select all identical classes of several dropdown menus, select a value, refresh browser and restart script

I work with a CMS where I have to change a user status from "Pending" to "Confirmed". If I do it manually I have to click on a dropdown value. There are 12 dropdowns on the page the dropdown value is always the same. Then I have to refresh the browser and click through the next 12 dropdowns.
I wrote this Python script with Selenium:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.chrome.options import Options
import time
options = Options()
options.add_argument("user-data-dir=selenium")
driver = webdriver.Chrome(options=options)
driver.get("https://url.com")
select = Select(driver.find_element_by_class_name('address-status'))
select.select_by_value('1')
time.sleep(1)
driver.close()
This is the html for the dropdown:
<select name="data[status]" class="address-status" data-id="44980" id="status">
<option value="2">Post card sent</option>
<option value="1">Confirmed</option>
<option value="0" selected="selected">Pending</option>
</select>
My problems which I can't figure out on my own are:
The script only selects the first class of 'adress-status' and selects the value I want but then it stops. But there are 11 more identical classes/dropdown menus where the (same) value has to be selected.
I don't know how to refresh the page to get the next set of dropdowns and restart the selection process/script.
I figured out that I may have to loop parts of the script but I learned and used Python for the first time yesterday and I just can't figure it out in time for this task.
This is my solution
Find all drop down element. It will return a list of all web element have class name = "address-status"
Using loop to select confirmed value
# find all dropdown element
list_drop_down = driver.find_elements_by_class_name("address-status")
# select confirmed value for each dropdown
for drop_down_element in list_drop_down:
select = Select(drop_down_element)
select.select_by_value('1')
I had similar issue. You need to select address-status element by index.
Find no of address-status elements
n_elements = len(driver.find_elements_by_class_name('address-status'))
after each refresh find all the elements again, but choose the one at different index
for idx in range(n_elements):
element = driver.find_elements_by_class_name('address-status')[idx]
# do what you need with the element
...
# refresh the page
...
After learning more about Python and adding all I've learned to the script I finally achieved every step I mentioned in my intial posting.
The steps are:
Open Chrome
I'm opening webdriver.Chrome with my user data because I need to stay logged in to the CMS I'm working with. I'm achieving this by adding an argument to options
Find all identical classes
This particular class represents a dropdown menu
Loop through all dropdowns
Select value
Time sleep of 1s
For some reason the script sometimes won't select all values so this helped. This might have to do with the closing of the browser in the next step but I'm not sure.
Close Chrome
In my case this is necessary to save the selected values to the CMS
Restart script
I defined a while loop of 40 repetitions. Be aware of IndentationError meaning to add a tab to the looped elements (I know this is basic stuff but might be useful for a newbie like me). Otherwise the script won't work. Also see
Nested for loop IndentationError: expected an indented block when using calendar module
Here is my code:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.chrome.options import Options
import time
count = 0
while count < 40:
print(count)
options = Options()
options.add_argument("user-data-dir=selenium")
driver = webdriver.Chrome(options=options)
driver.get(
"https://URL")
# find all dropdown element
list_drop_down = driver.find_elements_by_class_name("address-status")
# select confirmed value for each dropdown
for drop_down_element in list_drop_down:
select = Select(drop_down_element)
select.select_by_value('1')
time.sleep(1)
driver.close()
count = count+1
Thanks to the user Trinh Phat who gave me the necessary push. My work place loves me now ;)

Why a click function of a web page element doesn't work (using Selenium module of Python)?

I am trying to automate a task which can save me thousands of clicks.
I searched a bit for available modules in Python and I have selected to work with Selenium.
I installed Firefox drivers and did some progress but I am stuck for a long time. I finally gave up, opened a Stack Overflow account and wanted to bring this problem into this helpful medium.
My code can successfully do some clicks, but I could not make the code click a button like element. I have to click such items so that page opens some new elements. (Hopefully I am going to click on these new elements to save some excels files automatically).
Here is the part which works as expected:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
browser = webdriver.Firefox()
url = "https://www.tbb.org.tr/tr/bankacilik/banka-ve-sektor-bilgileri/istatistiki-raporlar/59"
browser.get(url)
time.sleep(2)
bank_reports_element_xpath = "//*[#title= 'Tüm Raporlar']"
bank_reports_element = browser.find_element_by_xpath(bank_reports_element_xpath)
bank_reports_element.click()
time.sleep(2)
second_item = "//div[#data-catid = '52']"
finance_tables_element = browser.find_element_by_xpath(second_item)
finance_tables_element.click()
years_item = "//div[#class = 'years']"
years_element = finance_tables_element.find_element_by_xpath(years_item)
year_elements = years_element.find_elements_by_xpath("a")
There I would like to click on the years.
a screenshot of the years that I can't click using Selenium
As an example, I get the element related to year 2004.
year2004 = year_elements[2]
Issuing a year2004.click() command gives an ElementNotInteractableException exception.
year2004.click() # ElementNotInteractableException: Element could not be scrolled into view
Based on searching similar posts, I tried the following (executing the click via javascript). I got no error but it does not do anything. When I click the year2004 button with mouse, a list pops-up in the page. But when I run the below code, no list pops up in the page.
browser.implicitly_wait(4)
browser.execute_script("arguments[0].scrollIntoView();", year2004)
browser.execute_script("arguments[0].click()", year2004)
I tried also the following code. I get "TypeError: rect is undefined"
browser.implicitly_wait(4)
action = ActionChains(browser)
action.move_to_element(year2004) # gives: TypeError: rect is undefined
action.click(on_element = year2004) # gives: TypeError: rect is undefined
action.perform()
I tried using Chrome Driver and got similar results. The errors definitions were not exactly the same. Instead of the above "rect is undefined" error, Chrome error is like: "Javascript error: Failed to execute 'elementsFromPoints' on 'Document': Provided double value is non-finite"
I don't know if it is relevant but year2004.location dictionary has a 0 value for "x".
I would appreciate any answer,
Keep safe
Use this xpath will give you all the elements of year in 52 category
//div[#data-catid='52']/descendant-or-self::*/div[#class='years']/child::a
for scrolling try
browser.send_keys(Keys.PAGE_DOWN)
I checked manually and page down button is working for me press it twice for desire element

How to click arrow_down and enter in download display in firefox with selenium

I have to download some file with selenium and I stuck on firefox download display.
I cannot change any of setting in selenium-webdriver, so i have to send arrow_down and enter to download display:
How should I do that?
Not sure that code matters but:
def save_file(self):
save_button = "save-file"
send_button = "confirm"
time.sleep(5)
self.wait_for_visibility((By.ID, save_button))
self.click_button(save_button)
self.click_button(send_button)
It's two steps download procedure.
1st step: click button "save"
2nd step: after first step there is additional confirmation.
language is of course python
You can't interact with OS windows with selenium. What you could do is to tell Firefox to save the file without asking questions. Then you can find the file in the downloads folder.
You should start your Firefox with some extra parameters:
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.manager.showWhenStarting", False)
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "text/plain,text/html, application/xml");
driver = webdriver.Firefox(fp)
In case you want to specify a target location where to save, you can do it by:
fp.set_preference("browser.download.dir", **target_download_directory**)
EDIT:
In case "flying blind" is not an issue for your test/program, you can just press buttons and stuff like:
import pyautogui
pyautogui.press('down')
pyautogui.press('enter')
You need to pip install pyautogui first. Please note that in case any popup appears on screen (which takes focus), the code snippet above may not be enough. If I was you I'd use the first approach to make the program failsafe.

Selenium Python Chrome: Last element in drop down list is not visible in Headless mode

I want to use Selenium to click an element in a menu drop down list. Unfortunately the element I want to click is all the way at the bottom of the list. My Selenium Python Chrome code runs perfectly in foreground mode, but when I run it in background / headless mode I get a timeout, or not clickable error (see notes below). Here is the code, using the actual public url, so you can test it out if you want:
# define chrome options
options = webdriver.ChromeOptions()
# make sure browser is maximized so all elements are visible
options.add_argument('--start-maximized')
# define driver
driver = webdriver.Chrome(chrome_options=options)
# define function used to get button
def getbutton(driver, xpath, waittime=10):
return WebDriverWait(driver, waittime).until(EC.element_to_be_clickable((By.XPATH, xpath)))
# navigate to url
driver.get('http://oasis.caiso.com/mrioasis/logon.do')
# another two different ways to make sure browser window is maximized
# I'm going through this trouble just in case selenium needs the window
# maximized to see the element
driver.fullscreen_window()
driver.maximize_window()
# choose dropdown menu
button1 = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='ATLAS REFERENCE']", waittime=120)
hover = ActionChains(driver).move_to_element(button1)
hover.perform()
time.sleep(5)
# see about navigating to the second to last button in the drop down
# menu list - not what I want, but a test
testing = True
if testing:
# move to second to last button - interestingly this works in foregraound AND background / headless modes
button1a = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='Intertie Scheduling Limit and Tie Mapping']")
hover = ActionChains(driver).move_to_element(button1a)
# THIS WORKS in foreground AND backgroubd modes
hover.perform()
time.sleep(10)
# Now try and click the button I really want - the LAST button in the drop down menu list
button2 = getbutton(driver, "//span[contains(#id, 'LBL_')][text()='Master Control Area Generating Capability List']", waittime=120)
button2.click()
button2 = getbutton fails with the following error message:
selenium.common.exceptions.TimeoutException
Interestingly, if I turn testing to False, I get the following error message:
selenium.common.exceptions.WebDriverException: Message: unknown error:
Element <span ...></table>">Master Control Area Generating Capability List</span>
is not clickable at point (128, 599). Other element would receive the click
It seems like selenium is unable to see the element in background / headless mode, even though neither of these exceptions occur when running in foreground mode.
I'm running Python in Windows Server 2012 R2 for what it's worth.
Thanks for any help!
I've changed a few things in your code and I no longer get the errors. I'm not sure if it's loading the correct webpage though since it's headless and everything seems to be dynamically loaded.
# another two different ways to make sure browser window is maximized
# I'm going through this trouble just in case selenium needs the window
# maximized to see the element
#driver.fullscreen_window()
#driver.maximize_window()
# choose dropdown menu
button1 = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='ATLAS REFERENCE']")
hover = ActionChains(driver)
hover.move_to_element(button1)
# see about navigating to the second to last button in the drop down
# menu list - not what I want, but a test
testing = True
if testing:
# move to second to last button - interestingly this works in foregraound AND background / headless modes
button1a = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='Intertie Scheduling Limit and Tie Mapping']")
hover.move_to_element(button1a)
# THIS WORKS in foreground AND backgroubd modes
# Now try and click the button I really want - the LAST button in the drop down menu list
button2 = driver.find_element_by_xpath("//span[contains(#id, 'LBL_')][text()='Master Control Area Generating Capability List']")
hover.click(button2)
hover.perform()
I'm selecting the elements with .find_element_by_xpath() and I'm queuing up all the ActionChains to execute them all at the end with hover.perform().
After further analysis, I'm unable to locate the "masterControlAreaGenCapGrid_GRID_LABEL" element with driver.find_element_by_id("masterControlAreaGenCapGrid_GRID_LABEL").text
It works when the browser isn't headless though...
So I finally figured out what the problem is: Running Windows task scheduler with option 'run whether user is logged on or not' only opens a small browser (1024x768) that CANNOT be resized, even with all the great suggestions being offered here. So I simply cannot see the element I want to click.
See the same issue resolved here: screen resolution in mode "Run whether user is logged on or not", in windows task scheduler
So the less than ideal workaround is to only run when user is logged on.
Thanks for all your help!

Selenium not printing out the right URL

I'm practicing with selenium right now but I can't seem to get it to print the correct URL.
import time
from selenium import webdriver
driver = webdriver.Firefox()
home_page = ''
driver.get(home_page)
time.sleep(15)
for i in range(1,9):
listing_page = driver.find_element_by_xpath('//*[#id="m_property_lst_cnt_realtor_more_'+str(i)+'"]').click()
realtor_url = driver.find_element_by_xpath('//*[#id="lblMediaLinks"]/a').click()
print(driver.current_url)
driver.get(home_page)
time.sleep(5)
I need the URL of the webpage that opens up when selenium clicks on the element in realtor_url. It instead prints the URL of the first click from listing_page.
(Note: webpage that is opened from realtor_url is a completely different website, if that helps)
You need to switch to the newly opened window before printing the URL, then close the newly opened window and switch back to the original window.
// do the click that opens another window
WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 2)
driver.switch_to_window(driver.window_handles[1])
print(driver.current_url)
driver.close()
driver.switch_to_window(driver.window_handles[0])
A couple other things...
.click() returns void, i.e. nothing, so there's nothing ever stored in listing_page or realtor_url variables.
sleep() is a bad practice. Don't use it. Google it to find out the details why. Replace sleep() with a relevant WebDriverWait.
I believe you need to change the "focus"of the window in order to print the correct url. The current window handler may be pointing to the previous click and not changed focus to the new window.
Try and get to change the "window handler". Every new window opened has a handler.
I hope this helps. window_handles Or this Handle multiple window in Python
EDIT:
The below should bring you to the latest open window.
driver.switch_to_window(driver.window_handles[-1])

Categories

Resources