Python Selenium - Iframe Dynamically Change Id and Name But Src is Same - python-3.x

Issue : - Unable to detect the iframe and switch to iframe as the iframe id and name dynamically changes at each time it loads but the src remain the same.
Unable to identify the xpath as well. Found iframe tag using driver.find_element_by_tagname("iframe") but cant view the tag <iframe> in the HTML of the page source. Therefore unable to find the xpath by right click and iframe tag.
Already tried to find the number of frame size using 'frame.size' but since its not callable, it provide answer in dict which is 'height:0,weight:0'
Require to switch to this iframe and work with the element inside the iframe which is to
1) enter text field into the iframe
2) select radio button in the iframe
Unable to select element after switch to iframe
Screenshot of the code
enter image description here

By default, each frame is assigned an integer number. So you can always do:
driver.switchTo().frame(0)
or
driver.switchTo().frame(1)

You can wait until frame to be loaded as given below.
wait = WebDriverWait(driver, 300)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,'//iframe')))

I was able to answer this, by determining the number of iframe. I've used 'find_element's'_by_tagname('iframe') instead of find_element_bytagname('iframe') which was able to find more than 1 iframe if exist in the page source.
This provides me total 3 iframe tag. Then i proceed to loop into the iframe and find the attribute of the each iframe such as id,name and src.
Then i noticed one of the iframe src, refers to the web address that has the element which i was looking for. Then i proceed to switch to that particular frame using if statement.
Once switch to the iframe, i proceed to get the element.
This solved on how to switch between frame using python-selenium and detect element upon switch the frame.
The key here is to detect on which frame does the element exist within and able to switch to that frame. The frame could be either nested within one frame or list of frame in the main window.
Upon detect and switch the frame. Then would be able to locate the element.
This solves the challenges

Related

Getting error Element not interactable on trying to send Page Down keys to div

I am trying to scroll Telegram using selenium in python. In the attached screenshot I have shared I have selected 'Members' as the element to send Keys.PAGE_DOWN as it is stick all the time to top and is static while scrolling so it should be visible all the time and can be the perfect element to send Keys.PAGE_DOWN to.
But on sending page_down I get error 'Element not Interactable'.
Any suggestions what I am doing wrong?
I have attached the script and screenshot.
I am using python 3.10 and selenium latest version.
`driver.find_element(By.XPATH, "//*[#id='RightColumn']/div[2]/div/div/div[2]/div[2]/div[1]").send_keys(Keys.PAGE_DOWN)`
I have tried all the answers currently available on the internet and they don't work here. This looks like some complex issue.
I think Selenium is throwing the right error message as this div is not an interactable element and you are trying to send keystrokes into the element.
Another approach for scrolling is using Javascript commands.
Find an element locator you need to scroll to.
(Ex: if you need to scroll to the bottom find the element at the bottom)
Use the below code to scroll
# Find the element in the page to scroll to
element = driver.find_element_by_xpath("//element/at/bottom/of/the/page")
# Fire javascript command to scroll in to view
driver.execute_script("arguments[0].scrollIntoView();", element)

How to find elements in containers that open when buttons are pressed

I am using headless Firefox on Selenium and XPath Helper to identify insanely long paths to elements.
When the page initially loads, I can use XPath Helper to find the xpath of any element of interest, and selenium can find the element when given the xpath.
However, several buttons that I need to interact with on the page open menus when pressed that are either small or take up the whole "screen". No matter their size, these containers are overlaid on the original page, and although I can find their xpaths using XPath Helper, when I try to use those xpaths to find the elements using selenium, they can't be found.
I've checked, and there's no iframe funny business happening. I'm a bit stumped as to what could be happening. My guess is that the page's source code is being dynamically changed after I press the buttons that open the menu containers and when I call find_element_by_xpath on new elements in the containers, the original source is being searched, instead of the new source. Could that be it?
Any other ideas?
As a workaround, I can get around this issue by sending keystrokes to the body of the page, but I feel this solution is rather brittle and likely to fail. Would be a much more robust solution to actually specify all elements.
EDIT:
With selenium I can find the export button, but not the menu it opens.
Here is the code for the export button itself:
The element of interest for me is "Customize Export" which I have not been able to find using selenium. Here is the code for this element:
Notice the very top line of this last image (cdk-overlay-container)
Now, when I refresh the page and do NOT click the export button, the cdk-overlay-container section of the code is empty:
This suggests my that my hypothesis is correct -- that when the page loads initially, the "Customize Export" button is nowhere in the source code, but appears only after "Export" is clicked, and that selenium is using the original source code only --not the dynamically generated code that appears after clicking "Export" -- to find elements
Selenium could find the dynamic content after doing
driver.execute_script("return document.body.innerHTML")
The WebDriverWait is what you need to use to wait for a certain condition of elements. Here is an example of waiting for the elements to be clickable before the click with a timeout in 5 seconds:
wait = WebDriverWait(driver, 5)
button = wait.until(EC.element_to_be_clickable((By.XPATH, 'button xpath')))
button.click()
wait.until(EC.element_to_be_clickable((By.XPATH, 'menu xpath'))).click()
identify insanely long paths
is an anti pattern. You can try to not use XPath Helper and find xpath or selector yourself.
Update:
wait = WebDriverWait(driver, 10)
export_buttons = wait.until(EC. presence_of_all_elements_located((By.XPATH, '//button[contains(#class, "mat-menu-trigger") and contains(.="Export")]')))
print("Export button count: ", len(export_buttons))
export_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(#class, "mat-menu-trigger") and contains(.="Export")]')))
export_button.click()
cus_export_buttons = wait.until(EC. presence_of_all_elements_located((By.XPATH, '//button[contains(#class, "mat-menu-item") and contains(.="Customize Export")]')))
print("Customize Export button count: ", len(cus_export_buttons))

Selenium: failing to find element by XPATH Python

I am a little bit new to programming but python really made get into it. I am trying to create a programm that automatically checks for updates in a website. I've successfully implemented the neccessary code to call the page of enrollment but yet there is one element that cannot be located. Since I have to do it for multiple courses and iterate throught them there is no specific id, I've tried to find it by title but also this didn't work.
Is there a way you can locate the button with the title "enroll".
I've tried
driver.find_element_by_xpath("//a\[#title ='enroll']").click()
but this didn't work and I always get
NoSuchElement
error.
The XPATH for the button is simply: //*\[#id="id572"\]
Here is the part of the HTML code:
From the screenshot of HTML code you provided, the element is <button>, not <a>.
Try this xpath expression //button[#title='enroll']
This should do it if it's not in any iframes. Just grab the button whose title is enroll and click. Your css selector was an a tag and it might get id dynamically.
driver.find_element_by_css_selector("button[title ='enroll']").click()

Tool to find xpath and iframe id

I'm automating a web page which contains several nested iframes. This makes it hard for me to find the proper locator for the elements. I use firebug, the f12 tools ... to get xpath etc. but I miss something here, the iframe id.
Does someone know a tool where I can point on an element on the web page, and get the xpath and the iframe id?
THX
Firebug displays the iframes containing the inspected element within its ancestor path:
By clicking on the buttons within the ancestor path you can jump to the related iframe.
To get the XPath for an iframe right-click on it within the HTML panel and choose Copy Minimal XPath or Copy XPath from the context menu.

List of all frames on a page

I am working on a problem where I need to enter data into a form in a iFrame.
The problem is that the iframe does not have an ID or name. It is the
first iframe (or frame) on the page, so I was planning to get a list
of the frames on the page and select the first one in the returned
list. I have done something simliar with windows
ie:
order_window = page.driver.browser.window_handles[0]
page.driver.browser.switch_to.window(order_window)
can something similar be done with frames?
if so how?
cucumber (1.0.6)
Capybara (1.1.1)
selenium-webdriver (2.5.0)

Resources