Unable to find element in Selenium WebDriver By Name and XPath - c#-4.0

I am working with Selenium WebDriver and wrote a small code to find and element (i.e a button) and click on it.
Here is the HTML code for the button:
<input type="submit" name="j_id0:j_id2:j_id3:j_id4:j_id7" value="New Master Health Program" onclick="AddLink()" class="btn">
Here is the C# code for the Test Case:
IWebElement newMasterHealthProgramsLink = driver.FindElement(By.Name("j_id0:j_id2:j_id3:j_id4:j_id7"));
newMasterHealthProgramsLink.Click();
I tried using XPath as well:
IWebElement newMasterHealthProgramsLink = driver.FindElement(By.XPath("//input[#id='j_id0:j_id2:j_id3:j_id4:j_id5']"));
newMasterHealthProgramsLink.Click();
I found a solution saying that you must not have implemented Wait for this. Page does not wait to load completely and tries to find the element. So I added wait command but nothing useful happened. Still getting the same error:
TestAutomation.Driver.Login:
OpenQA.Selenium.NoSuchElementException : The element could not be found

Since your element is in an IFrame, you'll need to 'switch' to that IFrameusing the WebDriver API.
By default, Selenium will use the 'top' frame, and therefore any 'find element' queries will be directed to the most top frame, and ignore any child IFrames.
To solve this, 'switching' to the current IFrame directs Selenium to shove any requests to that frame instead.
driver.SwitchTo().Frame()
Note that you'll need a way of accessing the frame, either by it's ID, index (the top frame is 0, next frame down is 1, etc...) or name.
Another note is that any further requests will be directed to that IFrame, ignoring any others, which includes the top one...so if you need to access the top frame, you'll need to switch back:
driver.Switch().DefaultContent().

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))

Performing search opertaion while using chrome but not in firefox(Selenium)

This is the code snippet for chroome:
driver.get("https://www.youtube.com/")
driver.find_element_by_xpath('//*[#id="search"]').send_keys("kao")
driver.find_element_by_xpath('//*[#id="search-icon-legacy"]').click()
The browser automatically opens Youtube and searches for the passed string[which is the task I intend to do]
The main problem appears when i start using firefox.The page loads properly.I am basically using the same code but every time I run it, it throws the following error:
Message: Element <g id="search"> is not reachable
I cannot pass any string to the search bar or even click it.
There is a slight error in the xpath //*[#id='search'] that it returns two elements as in below screen. The reason being the * in the above xpath acts as a wild card and matches the other ytd-searchbox<id="search"> tag in the page. The same is true for //*[#id="search-icon-legacy"].
So you must try changing to the xpath like below to locate the web elements uniquely
//input[#id='search']
//button[#id='search-icon-legacy']
Errored Xpath:
Your Xpath is not correct. It's Unable to locate search field and buttton
You can use this one
driver.get("https://www.youtube.com/")
driver.find_element_by_xpath("//input[#id='search']").send_keys("kao")
driver.find_element_by_xpath("//button[#id='search-icon-legacy']").click()

Selenium can not click on one element

I am using Selenium Chromedriver and my problem looks like this:
My program is clicking element on website and a list of elements appear.
Than it is choosing one of element from list using checkbox.
Nextly it is trying to click other element but the program crashes.
When the mentioned list appear if I am clicking anywhere on website using inspect option the code of inspected element looking like this:
<div id="__selectOverlay" style="display: block;"></div>
how can I click any element from website after the list appear?
looking at the html snippet shared, "__selectOverlay" might be the overlay which comes on top of the web page(like a loading spinwheel/panel) .
To get rid of the error, you can try the following
* Wait for panel/overlay to disappear
* Close the panel , if there is a panel close button.
And then click on any element on the web page
As per the HTML you have shared the WebElement seems to me as a Overlay within a div tag. Moreover this div tag doesn't have a onClick() event associated. So we won't be able to click the WebElement straight away. Possibly you might be trying to invoke click() method on some other element which is having this temporary / permanent Overlay through the div tag.
Solution
Depending on the type of Overlay there are two possible solutions as follows :
Temporary Overlay :
In this case induce ExplicitWait with ExpectedConditions set to invisibilityOfElementLocated for the Overlay to be invisible.
WebDriverWait wait1 = new WebDriverWait(driver, 10);
wait1.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ele_to_inv")));
Permanent Overlay :
Use JavascriptExecutor to send the click directly on the element.
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);

Python: finding elements of a webpage to scrape in python when page content is loaded using Java script

I am trying to scrape content of a page.
Let's say this is the page:
http://finance.yahoo.com/quote/AAPL/key-statistics?p=AAPL
I know I need to use Selenium to get the data I want.
I found this example from Stackoverflow that shows how to do it:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://finance.yahoo.com/quote/AAPL/profile?p=AAPL")
# wait for the Full Time Employees to be visible
wait = WebDriverWait(driver, 10)
employees = wait.until(EC.visibility_of_element_located((By.XPATH, "//span[. = 'Full Time Employees']/following-sibling::strong")))
print(employees.text)
driver.close()
My question is this:
In the above example to find Full Time Employees the code that has been used is:
employees = wait.until(EC.visibility_of_element_located((By.XPATH, "//span[. = 'Full Time Employees']/following-sibling::strong")))
How the author has found that s/he needs to use:
"//span[. = 'Full Time Employees']/following-sibling::strong"
To find the number of employees.
For my example page: http://finance.yahoo.com/quote/AAPL/key-statistics?p=AAPL how can I find for example Trailing P/E?
Can you please tell me the steps you took to find this? I do right click and choose Inspect, but then what shall I do?
A picture is worth of thousand words.
In web dev. tools (F12) you do the following steps:
Choose Elements tab
Press Element Selector button
With that button pressed you click an element in the main browser window.
In the DOM-elements window you right-click that highlighted element.
The context menu gets transpired and you choose Copy.
Choose Copy XPath in a sub menu. Now you have that element xpath in a console buffer.
NOTE!
The browser makes/composes an element xpath based on its own algorithm. It might not be the way you think or the way that fits to your code. So, you have to understand xpath in nature, be acquainted with it.
See what xpath the Chrome browser has issued for Trailing P/E:
//*[#id="main-0-Quote-Proxy"]/section/div[2]/section/div/section/div[2]/div[1]/div[1]/div/table/tbody/tr[3]/td[1]/span
'//h3[contains(., "Valuation Measures")]/following-sibling::div[1]//tr[3]'
Here I have the answer for all your confusions.
It will be better to look on some xpath tutorials and do practice from yourself, then you will be able to decide what you have to use .
There are so many site. You can start Here or Here
Now come to your Query -
Suppose I am using following xpath to locate the element
//h3/span[text()='Financial Highlights']/../preceding-sibling::div//tr[3]/td/span
Your requirement to find Trailing P/E in your page, definatly you will look unique xpath which won't change. If you try to find this using firepath it shows some lengthy xpath
Now you will check alternative and find another element (may be sibling, child or ancestor of your element) based on that you can to locate your element
in My case, first will find the Financial Highlights text which I will be able to find using //h3/span[text()='Financial Highlights']
Now I move its parent tag which is h3 and I will do this using /..
I have Trailing P/E element in just above the current node so move on just above node using /preceding-sibling::div
And finally find your element in that <div> like -//tr[3]/td/span
See the screens as well -
Step 1 :
Step 2 :
Step 3 :
Step 4 :

Resources