Click ComboButton item with Selenium - python

I am trying to preform a simple click, but cannot find out what way to find it due to the type of element it is.
<div class="active">
<div class="action-title">Reconcile All</div>
<div class="action-description">Reconcile all IPv4 addresses</div>
</div>
<div class="active">
<img src="/images/icons/small/checks.gif" border="0">
</div>
I have tried doing it several ways. Such as,
driver.find_elements_by_link_text("Reconcile All").click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "Reconcile All"))).click()
I even tried based of the icon
driver.find_element_by_xpath("//*[contains(#src,'/images/icons/small/checks.gif')]").click()
Thanks in advance for any help

Div element can't click using link_text try Use following xpath and Webdriverwait to click.
WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//div[#class='active']//div[#class='action-title'][contains(.,'Reconcile All')]"))).click()

Related

Choosing appropriate locators when scraping dynamic content with Python and Selenium

I am trying to understand the correct way to select specific elements of a webpage using python and selenium, I am uncertain what dictates which approach to take such as xpath or CSS and so on.
https://dutchie.com/embedded-menu/revolutionary-clinics-somerville/menu
<a class="consumer-product-card__StyledLink-ncbvk2-1 jpGhIo" href="/embedded-menu/berkshire-roots/menu/cbd-tincture-2-1-225mg">
<span>CBD Tincture 2:1 225mg Details</span>
<div class="product-card__Container-sc-7s6mw-0 iWHVJj">
<div class="product-card__Content-sc-7s6mw-1 cfcIOW">
<div class="product-information__Container-sc-65h5ke-0 ejVwks">
<img class="product-information__StyledProductImage-sc-65h5ke-1 jupjtQ" width="218" height="218" src="https://images.dutchie.com/0f253b35120facc1465b75b08bfd4d66?auto=format&dpr=1&bg=FFFFFF&crop=faces&fit=fill&w=218&h=218&ixlib=react-7.2.0" alt="" srcset="https://images.dutchie.com/0f253b35120facc1465b75b08bfd4d66?auto=format&dpr=2&bg=FFFFFF&crop=faces&fit=fill&w=218&h=218&ixlib=react-7.2.0 2x, https://images.dutchie.com/0f253b35120facc1465b75b08bfd4d66?auto=format&dpr=3&bg=FFFFFF&crop=faces&fit=fill&w=218&h=218&ixlib=react-7.2.0 3x">
<div class="product-information__ProductInfo-sc-65h5ke-2 bwhblJ">
<div class="product-information__Price-sc-65h5ke-7 eEqLUB">$36.95</div>
<div class="product-information__BrandContainer-sc-65h5ke-5 dlSlvE list-only">
<div class="product-information__Brand-sc-65h5ke-6 ftehWE">Berkshire Roots</div>
</div>
<div class="product-information__TitleContainer-sc-65h5ke-3 fOoVwz list-only false">
<div class="product-information__Title-sc-65h5ke-4 eBIyJW --line2">CBD Tincture 2:1 225mg</div>
</div>
<div class="product-information__TitleContainer-sc-65h5ke-3 fOoVwz mobile-and-card">
<div class="product-information__Title-sc-65h5ke-4 eBIyJW">CBD Tincture 2:1</div>
<div class="product-information__Title-sc-65h5ke-4 eBIyJW --line2"> 225mg</div>
</div>
<div class="product-information__DetailsContainer-sc-65h5ke-9 ifqkuO">
<div class="product-information__Strain-sc-65h5ke-10 eWkod --high-cbd">High CBD</div>
<div class="product-information__PotencyInfo-sc-65h5ke-14 gUReQf"><b>THC: </b>72.3 mg | <b>CBD: </b>160.3 mg</div>
</div>
</div>
</div>
<div class="product-weights__Container-nwgli1-0 gwUwAi">
<div class="product-weights__Weights-nwgli1-1 kiObrJ">
<div aria-label="Add 0.41g to cart for $36.95" data-cy="product-card-weight" class="weight__Container-sc-11f1l3-2 dNvnhd">
<div class="weight__Price-sc-11f1l3-4 ZtHqz">$36.95</div>
<div class="weight__IconContainer-sc-11f1l3-1 zqIJt">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 10 10">
<path fill="#A6ACB3" fill-rule="nonzero" d="M9.176 5c0-.407-.031-.723-.438-.723l-3.022.007.007-3.022c0-.407-.326-.428-.722-.438-.407 0-.723.03-.722.436l.003 3.012-3.022.007c-.406 0-.426.325-.436.722-.01.396.031.722.438.722l3.022-.007.003 3.012c0 .407.326.427.723.438.407 0 .722-.03.721-.437l-.003-3.011 3.012.003c.406 0 .437-.315.436-.722z"></path>
</svg>
</div>
</div>
<div class="product-weights__Fill-nwgli1-2 dtfdkt"></div>
</div>
</div>
</div>
</div>
</a>
How would I use a loop of sorts to access each and every "consumer-product-card" without having scrolled to the bottom of the page? Or would I need to force the page to scroll first? Is the "consumer-product-card" approach correct or would xpath make more sense? With either I find it difficult to understand which is ideal for what reason, or even how to select it in one instance, as well as the next and next until I reach the end.
Thank you.
To find all cards use:
driver.find_elements_by_xpath("//div[contains(#class,'consumer-product-card__InViewContainer-ncbvk2-0 dWfGpk')]")
Then use as an example links I gave you in the previous question.
UPDATE
Solution to start with:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome(executable_path='/snap/bin/chromium.chromedriver')
driver.get('https://dutchie.com/embedded-menu/revolutionary-clinics-somerville/menu')
wait = WebDriverWait(driver, 30)
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".product-card__Content-sc-7s6mw-1.cfcIOW")))
cards = driver.find_elements_by_css_selector(".product-card__Content-sc-7s6mw-1.cfcIOW")
data = []
for card in cards:
name = card.find_element_by_css_selector(".product-information__TitleContainer-sc-65h5ke-3.fOoVwz.list-only").text
data.append(name)
for i in data:
print(i)
It waits for cards and prints their names. But scrolling etc, other elements are completely different questions.
I found css selectors more suitable for this case.
Result is three items:
Rick Simpson Oil (RSO)
Live Sugar - Purple Pineapple Express
Live Sugar - Gelato #33
This is kind of an opinionated question.
I would likely use the simplest CSS Selector I can find that uniquely defines the element. XPath is slower and, I find, likely more brittle and harder to find good selectors for elements. But there is no "correct" approach.
I'm a little confused regarding the goal of the rest of the question. I think we would need some more detail and the code you've used to attempt this.
Also, your HTML is formatted on one line and very hard to view.

selenium python find link by href text and click it

I have my script to login to a site. i then need to click on another link which is contained in an
<a href> </a>
I have tried multiple methods without success. The link I need "Available Deployments" only appears after clicking a dropdown box called "Job Board".
The site code looks like this:
<li class="">
<a aria-expanded="false" class="dropdown-toggle" data-toggle="dropdown" href="portalPost?s=a1W390000045MxAEAU&p=a1V39000003y7e1EAA" role="button">Job Board <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>
<a href="portalPage?s=a1W390000045MxAEAU&p=a1V39000003y7dbEAA">Available Deployments
</a>
</li>
i've tried a couple of versions, without success:
-SNIP-
driver.find_element_by_name("logmein").click()
driver.find_element_by_linkText("Job Board").click()
driver.find_element_by_linkText("Available Deployments").click()
and
-SNIP-
driver.find_element_by_name("logmein").click()
driver.find_element_by_xpath(u'//a[text()="Job Board"]').click()
driver.find_element_by_xpath(u'//a[text()="Available Deployments"]').click()
The errors I get typically look like:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//a[text()="Available Deployments"]"}
It looks like there is a whitespace in text of the element.
You have to use normalize-space to trim text. See an example below.
driver.find_element_by_xpath(u'//a[text()="Job Board"]').click()
waitForPresence = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.XPATH,'//a[normalize-space(text())="Available Deployments"]')))
driver.find_element_by_xpath('//a[normalize-space(text())="Available Deployments"]').click()
I solved this with the following:
driver.find_element_by_link_text("Job Board").click()
driver.find_element_by_link_text("Available Deployments").click()

Clicking button within span with no ID using Selenium

I'm trying to have click a button in the browser with Selenium and Python.
The button is within the following
<div id="generate">
<i class="fa fa-bolt"></i>
<span>Download Slides</span>
<div class="clear"></div>
</div>
Chrome's dev console tells me the button is within <span> but I have no idea how to reference the button for a .click().
Well, if you just want to click on an element without an id or name, I'd suggest three ways to do it:
use xpath:
driver.find_element_by_xpath('//*[#id="generate"]/span')
use CSS selector:
driver.find_element_by_css_selector('#generate > span')
Just try .find_element_by_tag_name() like:
driver.find_element_by_id('generate').find_elements_by_tag_name('span')[0]
Note that this way first try to get the generate <div> element by it's id, and then finds all the <span> elements under that <div>.
Finally, gets the first <span> element use [0].

Selenium wait for element to be clickable python

All, I'm needing a little assistance with Selenium waits. I can't seem to figure out how to wait for an element to be ready.
The element that I am needing to wait I can locate and click using my script via the code below...
CreateJob = driver.find_element_by_xpath(".//*[#id='line']/div[1]/a")
or
CreateJob = driver.find_element_by_partial_link_text("Create Activity")
I'm needing to wait for this element to be on the page and clickable before I try to click on the element.
I can use the sleep command, but I have to wait for 5 seconds or more and it seems to be unreliable and errors out 1 out of 8 times or so.
I can't seem to find the correct syntax to use.
the HTML code for this is below.
<document>
<html manifest="https://tddf/index.php?m=manifest&a=index">
<head>
<body class="my-own-class mozilla mozilla48 mq1280 lt1440 lt1680 lt1920 themered" touch-device="not">
<noscript style="text-align: center; display: block;">Please enable JavaScript in your browser settings.</noscript>
<div id="wait" style="display: none;">
<div id="processing" class="hidden" style="display: none;"/>
<div id="loading" class="hidden" style="display: none;"/>
<div id="loadingPartsCatalog" class="hidden"/>
<div id="panel">
<div id="top-toolbar" class="hidden" style="display: block;">
<div id="commands-line" class="hidden" style="display: block;">
<div id="line">
<div class="action-link">
<a class="tap-active" href="#m=activity/a=set" action_link_label="create_activity" component_gui="action" component_type="action">Create Activity</a>
</div>
<div class="action-link">
<div class="action-link">
<div class="action-link">
</div>
<div id="commands-more" style="display: none;">
<div id="commands-list" class="hidden">
</div>
<div id="provider-search-bar" class="hidden center"
Here is a link to the 'waiting' section of the Python Selenium docs: http://selenium-python.readthedocs.io/waits.html#explicit-waits
You wait should look like this:
element = WebDriverWait(driver, 10).until(
EC.visibility_of((By.XPATH, ".//*[#id='line']/div[1]/a"))
)
I find this to be the easiest:
driver.implicitly_wait(10)
Where it waits for up to 10 seconds before the script might crash if expected conditions aren't met. I think it's better than always checking for the visibility of, the clickability of, or whatever it is about the element. Less effective and more error prone, however. So it would depend more on why you use selenium.
It also lets me cut down on try/except statements in my selenium scripts, and since I've found out about this I've reduced many time.sleep() functions as well.

Unable to click on element with link in selenium python

I am trying to interact with a sign out button but I just can't seem to click on it using link text or xpath.
I have tried following these answers with no luck:
Why Cant I Click an Element in Selenium?
Unable to click link using selenium webdriver in python
Here is my code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from xatu.tests.base import login
from xatu.tests.bagon import BagonBaseTestCase
class BasicTestCase(BagonBaseTestCase):
#login
def test_logout(self):
self._wait_until_id_presents("quotes-form")
WebDriverWait(self, 10).until(
EC.presence_of_element_located((By.XPATH, "//a[#href='/login/clear']/i")))
self.browser.find_element_by_xpath("//a[#href='/login/clear']/i").click()
self.implicitly_wait(2)
self._title_check("Login")
The first line under test_logout calls a function that waits for a certain element to appear on the webpage so I can see that the page has been loaded. Then I try to click the sign out button.
This is the HTML(element is at class="btn" href="/login/clear"):
<div class="navbar navbar-fixed-top screen-only">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
<a class="brand" href="/">
<div class="nav-collapse collapse">
<ul class="nav">
<p class="pull-right" style="margin-top: 4px; margin-left: 4px;">
<a class="btn" href="/login/clear">
<i class="icon-off"/>
Sign out
</a>
</p>
<p class="navbar-text pull-right"> Logged-in as D. V. Lauper </p>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
When I try finding by link_text, the element can't be found. Running this code gives me a stacktrace error saying:
ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with
Edit: I've tried Saifur's answer and updated my code to his answer but now I get: AttributeError: 'BasicTestCase' object has no attribute 'find_element'. I've tried changing "self" to "self.browser" as an argument in WebDriverWait() but I would then get my original error.
Use explicit wait and relativexpath
like //a[#href='/login/clear']/i
from xatu.tests.base import login
from xatu.tests.bagon import BagonBaseTestCase
class BasicTestCase(BagonBaseTestCase):
#login
def test_logout(self):
self._wait_until_id_presents("quotes-form")
WebDriverWait(self, 10).until(
EC.presence_of_element_located((By.XPATH, "//a[#href='/login/clear']/i")))
self.browser.find_element_by_xpath("//a[#href='/login/clear']/i").click()
self.browser.implicitly_wait(2)
self._title_check("Login")
You need an explicit wait. See docs. Example code:
element = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH,'//a[#href="/login/clear"]')))
And then just click the element.
element.click()
Note I added my answer b/c -- in my tests at least -- you don't need to worry about the italics tag. That's for the text, not the button -- and you're not clicking the text. So find By.XPATH and select a unique attribute (i.e., the href in this case and very likley not the class attr), and then click your element.
EDIT:
please try this line:
element = WebDriverWait(self.browser, 30).until(EC.visibility_of_element_located((By.XPATH,'//a[#class="btn" and #href="/login/clear"]')))

Categories