python selenium unable to select element - selenium

I'm trying to select below element in a webpage.
.active > b:nth-child(1)
This is my code :
timbro = browser.find_element_by_css_selector('.active > b:nth-child(1)')
hover = ActionChains(browser).move_to_element(timbro)
hover.perform()
This is part of the error I'm getting:
Message: Unable to locate element:
{"method":"css selector","selector":".active > b:nth-child(1)"}"
what I'm trying to do is activate a drop down menu so that I can click on another link.
HTML Snippet:
<li>
<b>Menu iniziale</b>
<ul style="display: block;" class="sub-links">
<li>
Anagrafica
</li>
<li>
Fine sessione
</li>
<li>
Home
</li>
<li>
Timbro
</li>
</ul>
</li>

You should try using WebDriverWait to wait until presence of element as below :-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(browser, 5)
menuIniziale = wait.until(EC.presence_of_element_located((By.LINK_TEXT, "Menu iniziale")))
hover = ActionChains(browser).move_to_element(menuIniziale).move_to_element(wait.until(EC.presence_of_element_located((By.LINK_TEXT, "Timbro"))))
hover.click().build().perform()
Edited1 :- If unfortunately LINK_TEXT does not work try using XPATH as below :-
menuIniziale = wait.until(EC.presence_of_element_located((By.XPATH, ".//a[contains(.,'Menu iniziale')]")))
hover = ActionChains(browser).move_to_element(menuIniziale).move_to_element(wait.until(EC.presence_of_element_located((By.XPATH, ".//a[contains(.,'Timbro')]"))))
hover.click().build().perform()
Or try using CSS_SELECTOR as below :-
menuIniziale = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.main-link")))
hover = ActionChains(browser).move_to_element(menuIniziale).move_to_element(wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "ul.sub-links > li:nth-child(4)"))))
hover.click().build().perform()
Edited2 : If this element is inside an iframe, you need to switch that iframe before finding element as below :-
wait.until(EC.frame_to_be_available_and_switch_to_it(("frame name or id")))
#Now after successfully switching to frame do any one of the above steps
Edited3 :- If you are now able to open menu but not able to select subMenu try as below :-
wait.until(EC.frame_to_be_available_and_switch_to_it(("frame name or id")))
menuIniziale = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.main-link")))
hover = ActionChains(browser).move_to_element(menuIniziale)
hover.build().perform()
subMenu = wait.until(EC.visibility_of_element_located((By.XPATH, ".//a[contains(.,'Timbro')]")))
subMenu.click()
Edited4: Final code
menuIniziale = wait.until(EC.presence_of_element_located((By.XPATH, ".//a[contains(.,'Menu iniziale')]")))
hover = ActionChains(browser).move_to_element(menuIniziale)
hover.perform()
subMenu = wait.until(EC.visibility_of_element_located((By.XPATH, ".//a[contains(.,'Timbro')]")))
subMenu.click()
hover = ActionChains(browser).move_to_element(subMenu)
hover.click().perform()

Related

Trying to get download link via Selenium

Trying to get the download link from this website to download the CSV file straight to a pandas dataframe with read_csv, however, having trouble scraping the link (from the href code).
To get to the csv download button, an initial click on the "Download Data" button is needed to open up another window.
The python code I have put together so far is:
driver = webdriver.Chrome(executable_path=r'/usr/local/bin/chromedriver')
URL = 'https://statisticsnz.shinyapps.io/covid_19_dashboard/'
driver.get(URL)
try:
element = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.XPATH, '//*[#id="download_data-show"]'))
)
element.click()
element = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.XPATH, '//*[#id="download_data-downloadData"]'))
)
outer = element.get_attribute('outerHTML')
finally:
driver.quit()
link = outer.find('a',href=re.compile('download_data-downloadData')).get('href') #I don't think this code line will work, but essentially trying to find the link to download with
df = pd.read_csv(URL + link)
The outer object returns the following html code and is missing the link that I need (href field is empty) to use directly in the read_csv file:
In[]: print(outer)
Out[]: <a id="download_data-downloadData" class="btn btn-default shiny-download-link shiny-bound-output" href="" target="_blank" download="">
<i class="fa fa-download"></i>
Download
</a>
When I inspect the 'Download' button from chrome, it gives me the following html code with the link in the href field:
<a id="download_data-downloadData" class="btn btn-default shiny-download-link shiny-bound-output" href="session/c199b49c2d09d042041ee7682c9c5922/download/download_data-downloadData?w=6e59d758" target="_blank" download="">
<i class="fa fa-download"></i>
Download
</a>
Any ideas why the link isn't showing when I scrape through Selenium, or maybe there is a better way of doing this?
Try to get the link directly of your download element like this:
try:
element = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.XPATH, '//*[#id="download_data-show"]'))
)
element.click()
element = WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.XPATH, '//*[#id="download_data-downloadData"]'))
)
link = element.get_attribute('href')
finally:
driver.quit()
df = pd.read_csv(link)

msg no such element: Unable to locate element:

HTML:
"Add to cart" object
<button class="button spin-button prod-ProductCTA--primary button--primary" data-automation-id="button" data-tl-id="ProductPrimaryCTA-cta_add_to_cart_button" type="button"><span class="button-wrapper"><span class="spin-button-children">Add to cart</span></span></button>
"Get in stock alert" object
<button class="button spin-button prod-ProductCTA--primary button--primary" data-automation-id="button" data-tl-id="cta_oos_button" aria-expanded="false" aria-label="get in stock alert" role="button" tabindex="0" type="button"><span class="button-wrapper"><span class="spin-button-children">Get in-stock alert</span></span></button>
I do not want to click "Add to cart". I just want to store locator info in WebElement "addToCart". Because objects have very identical properties, I chose this unique property "data-tl-id" but did not work.
Web Driver
WebElement addToCart = driver.findElement(By.xpath("//button[#data-tl-id='ProductPrimaryCTA-cta_add_to_cart_button']"));
Below worked for me but both above objects have the same class name so i cant use the class name.
WebElement addToCart = driver.findElement(By.xpath("//span[#class='button-wrapper']"));
I also tried below ways but none worked for me.
WebElement addToCart = driver.findElement(By.xpath("//span[text()='Add to cart'"));
WebElement addToCart = driver.findElement(By.xpath("//span[contains(#text,'Add to cart')]"));
I get error "No such element: Unable to locate element: ". How to locate the "Add to cart" object?
Your xpath is wrong WebElement addToCart = driver.findElement(By.xpath("//span[text()='Add to cart'"));
Try below solution
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement webElement = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[text()='Add to cart']")));
System.out.println("Printing "+webElement.getText());
Or you can also try xpath with contains
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement webElement = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//span[contains(text(),'Add to cart')]")));
System.out.println("Printing "+webElement.getText());
since this xpath worked for you,
WebElement addToCart = driver.findElement(By.xpath("//span[#class='button-wrapper']"));
Use this to uniquely identify WebElement
driver.findElement(By.xpath("//button[contains(#data-tl-id,'cart')]/span[#class='button-wrapper']"))
you can also use this xpath
//span[contains(text(),'Add to cart')]

Selenium cannot click menu-item from bootstrap dropdown

Actions action = new Actions(driver);
WebElement we = driver.findElement(By.xpath("//*[#id='ctl00_Sitemap1_HyperLink1']"));
action.moveToElement(we).build().perform();
WebElement tmpElement= driver.findElement(By.xpath("//*[#id='ctl00_Sitemap1_HyperLink1']"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", tmpElement);
List<WebElement> dd_list = driver.findElementsByXPath("//*[#id='masterNavigation']/ul/li[1]/ul/li");
for (WebElement ele : dd_list)
{
System.out.println("Values " + ele.getAttribute("innerHTML"));
if (ele.getAttribute("innerHTML").contains("Event Dashboard")) {
ele.click();
break;
}
}
}
Hi I am trying to Automate bootstrap drop-down menu. It's visibility is hidden by default.Once you hover mouse on it, its visibility property shows visible.I am able to click on drop-down , but after clicking on drop-down my selenium script is not selecting value from drop-down.
Error: Exception in thread "main"
org.openqa.selenium.ElementNotVisibleException: Cannot click on
element
HTML Code Snippet
<a class="ui-button-text-icons" id="ctl00_Sitemap1_HyperLink1" href="javascript:void(void);">
<span style="padding-right: 1.3em;">Dashboards</span>
<span class="ui-button-icon-secondary ui-icon ui-icon-triangle-1-s"></span>
</a>
<ul style="visibility: hidden;">
<li class="first featureGranted">
Classic Dashboard
</li>
</ul>
Few things
You don't need to traverse though all li elements to find your desire element you can do it with Xpath
I have no Idea why you are using JavaScript to click first Element, but unless click method provided by Selenium is not working I would suggest not to use JavaScript Click
Error suggests that element is not visible, it could be due to multiple reasons. You could wait using Explicit wait until element is visible as mentioned below. it might resolve your issue
Code
Actions action = new Actions(driver);
WebElement we = driver.findElement(By.xpath("//*[#id='ctl00_Sitemap1_HyperLink1']"));
action.moveToElement(we).build().perform();
WebElement tmpElement= driver.findElement(By.xpath("//*[#id='ctl00_Sitemap1_HyperLink1']"));
JavascriptExecutor js = (JavascriptExecutor) driver;
// I have no idea why you are clicking using JavaScript
js.executeScript("arguments[0].click();", tmpElement);
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement eventDashboardMenu = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//li[contains(text(),'Event Dashboard')]")));
eventDashboardMenu.click();

I would like to click on New Contact button from web page for my selenium script

I would like to click on a "New Contact" button for my selenium script. I have tried:
driver.findElement(By.id("btn-group.contact_list-menu-contact_add")).click();
And by xpath as well, but it is not working. How could I get this working?
<div class="btn-group left">
<a id="contact_list-menu-contact_add" class="Button btn-contactadd primary SaveItem" href="javascript:">New Contact</a>
</div>
You are searching by an incorrect id value, use contact_list-menu-contact_add instead:
driver.findElement(By.id("contact_list-menu-contact_add")).click();
Or, by a CSS selector:
driver.findElement(By.cssSelector(".btn-group .btn-contactadd")).click();
driver.findElement(By.cssSelector(".btn-group #contact_list-menu-contact_add")).click();
driver.findElement(By.cssSelector("#contact_list-menu-contact_add")).click();
Or, by a link text:
driver.findElement(By.linkText("New Contact")).click();
If the target element is inside an iframe, you would need to switch into the context of the frame before searching for the element. Assuming that your frame has contactURL id, this is how to switch to it:
driver.switchTo().frame("contactURL");
If you are getting NoSuchElementException as you have mentioned in the comment, There are may be two reason :-
May be when you are going to find element, it would not be present on the DOM, So you should implement WebDriverWait to wait until element visible and clickable as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement el = wait.until(ExpectedConditions.elementToBeClickable(By.id("contact_list-menu-contact_add")));
el.click();
May be this element is inside any frame or iframe. If it is, you need to switch that frame or iframe before finding the element as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("contactURL"));
WebElement el = wait.until(ExpectedConditions.elementToBeClickable(By.id("contact_list-menu-contact_add")));
el.click();
Edited :- As I see from your provided HTML this button is inside <div id="btn-new-group" class="btn-group-actions left" style="display: none;"> which is set to be invisible, that's why you are not able to find button. You should make it visible first then try to find as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("contactURL"));
WebElement invisibleDiv = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("btn-new-group")));
//Now make it visible first
((JavascriptExecutor)driver).executeScript("arguments[0].style.display = 'block';", invisibleDiv);
//Now find contact button
WebElement el = wait.until(ExpectedConditions.elementToBeClickable(By.id("contact_list-menu-contact_add")));
el.click();
Hope it helps...:)

How do i make Selenium pull out the sidebar menu tree

I have a iframe-sidebar which appears as soon as a widget is hovered over , since it uses the onchange javascript event, and hides back when the sidebar is clicked again. There is a listbox in this sidebar which needs to be clicked for my chain to continue. How do i program Selenium webdriver in Python to pull out this sidebar ?
Thanks
On reading answers to question, I added this :-
element = driver.find_element_by_xpath('//*[#id="leftSiderBarForm:moduleMenu"]')
element = driver.find_element_by_id("leftSiderBarForm:moduleMenu")
hover = ActionChains(driver).move_to_element(element)
hover.perform()
but get error :-
MoveTargetOutOfBoundsException: Message: u'Offset within element cannot be scrolled into view: (72.5, 8.5): [object XrayWrapper [object HTMLSelectElement]]' ;
This is the HTML of that element that i copied from Chrome. I changed actual values to ABC and so on.
<select id="leftSiderBarForm:moduleMenu" name="leftSiderBarForm:moduleMenu" class="comboboxnowidth leftSideMenuSelect " size="1" onchange="jQuery('.submitMenuSelection').click()" style="z-index: 0;"> <option value="">-- Select --</option>
<option value="ABC">abc</option>
<option value="DEF">def</option>
Could i use Javascript to trigger that Jquery ?
from selenium.webdriver.common.action_chains import ActionChains
def hover_over_item(self):
driver = webdriver_connection.connection
element = driver.find_element_by_id(locator)
hover = ActionChains(driver).move_to_element(element)
hover.perform()
Reference