Nested Span element URL text value - Selenium - selenium

I am trying to get the value #2011 which is a URL text from the HTML below. I tried the below code but didnt work. It says it is unable to locate the class
driver.find_element(By.XPATH, '//span[#class = "data-issue-and-pr-hovercards-enabled"]').get_attribute('a')
Can anyone help to correct the mistake? I am new to selenium.
<span data-issue-and-pr-hovercards-enabled>
<span><span> ยท Fixed by #2011</span><span></span></span>
</span>
Here is the link to the website - github.com/mlpack/mlpack/issues/2008 I want to get the #2011 which is next to the Fixed by Text (below the title of the issue). Is it possible to do this?

Try the below XPath:
This relative xpath will search for all tag names(*) which contains the text "#2011"
//*[contains(text(),'#2011')]
Or try the below one: Very similar explanation as above but this will search only within <a> tag
//a[contains(text(),'#2011')]
Update:
Try the below XPath:
//span[contains(text(),'Fixed by')]//a
Use .text method to fetch the required value. This will get you the below text value.

In the given HTML data-issue-and-pr-hovercards-enabled is an attribute but not the value of class.
To extract the text #2011 ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following locator strategies:
Using CSS_SELECTOR and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "span[data-issue-and-pr-hovercards-enabled] a[data-hovercard-type='pull_request'][data-hovercard-url='/mlpack/mlpack/pull/2011/hovercard']"))).text)
Using XPATH and get_attribute("innerHTML"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[#data-issue-and-pr-hovercards-enabled]//a[#data-hovercard-type='pull_request' and #data-hovercard-url='/mlpack/mlpack/pull/2011/hovercard']"))).get_attribute("innerHTML"))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
References
Link to useful documentation:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium

Related

Auto-checkin script for united airlines

Trying to submit the check in form for United Airlines (https://www.united.com/en/us/checkin). I can't get the continue button to automate. The xpath is dynamic so is css selector. Can't find a name or id browser to find. How can I find this element? Never coded before so this is all I have been able to pickup from youtube
html for button
<button class="app-components-Button-styles__button--LbfHO app-components-Button-styles__tertiary--20H47 app-components-Button-styles__contained--2kXyi" type="submit">Continue</button>
Code so far:
from selenium import webdriver
browser = webdriver.Chrome('/Users/jeff/chromedriver/chromedriver')
browser.get('https://www.united.com/en/us/checkin')
browser.find_element('name', 'confirmationNumberModel.number').send_keys('AAAA1')
browser.find_element('name', 'confirmationNumberModel.lastName').send_keys('LastName')
browser.implicitly_wait(3)
Try to locate button by XPath:
browser.find_element(By.XPATH, '//button[.="Continue"]').click()
You can also call submit method from any element inside form node:
browser.find_element('name', 'confirmationNumberModel.lastName').submit()
P.S. Note that browser.implicitly_wait(3) should be called before locating elements
Given the HTML:
<button class="app-components-Button-styles__button--LbfHO app-components-Button-styles__tertiary--20H47 app-components-Button-styles__contained--2kXyi" type="submit">Continue</button>
All the classnames are dynamically generated. So we can't use them and have to look out for the static element attributes.
Solution
To click on Continue you can use either of the following locator strategies:
Using css_selector:
driver.find_element(By.CSS_SELECTOR, "div[title='Confirmation or eTicket number'] button[type='submit']").click()
Using xpath:
driver.find_element(By.XPATH, "//button[#type='submit' and text()='Continue']").click()

How to get the text before & after the hyperlink using Selenium and Xpath

I am trying to find cases using Xpath/Selenium where there is no white-space before the hyperlink.
e.g.
<p>Click on thislinkto access the data</p>`
This renders as Click on thislinkto access the data
Problem : Locate all the <a> elements and test if they have white-space before and after
Is there any elegant way to get the text before/after of anchor? I am thinking of using XPath query such as //a/parent::* which returns <p> element but the <a> tag is not separated. Can I somehow get the immediate text before/after the anchor tag?
Since you're using selenium, I'm assuming xpath 1.0.
This should select a elements that don't have a preceding or following space...
//a[substring(preceding-sibling::text()[1],string-length(preceding-sibling::text()[1]) )!=' ' or substring(following-sibling::text()[1],1,1)!=' ']
As per the HTML, there are two text nodes with text Click on this and to access the data and a <a> element within their parent element.
<p>
Click on this
link
to access the data
</p>
Solution
To print text before the <a> element you have to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using Python, XPATH, childNodes and strip():
print(driver.execute_script('return arguments[0].firstChild.textContent;', WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[contains(., 'link')]//ancestor::p[1]")))).strip())
Using Python, XPATH, get_attribute() and splitlines():
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[contains(., 'link')]//ancestor::p[1]"))).get_attribute("innerHTML").splitlines()[1])
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

How to click on the class which contains particular text using Selenium

<h3 _ngcontent-ydk-c51="" matline="" class="mat-line">Text1</h3>
<h3 _ngcontent-ydk-c51="" matline="" class="mat-line">Text2</h3>
There are many links with class ="mat-line", but i want to click on link which contains Text1, how to do it ?
To click on the element with text as Text1 you need to induce WebDriverWait for the elementToBeClickable() (Java) / element_to_be_clickable() (Python) and you can use either of the following Locator Strategies:
Using Java and xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//h3[#class='mat-line' and text()='Text1']"))).click();
Using Python and XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//h3[#class='mat-line' and contains(., 'Text1')]"))).click()
Note: Using Python client you have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
To get an h3 class of mat-line with text Text1 try the following xpath.
//h3[contains(text(), "Text1") and #class="mat-line"]
Found these two xpath working for Selenium with C#
"//h3[contains(text(),'Text1')]"
"//*[#class='mat-line'][.='Text1']"

Selenium WebDriver - Find Element

I've gone through the Selenium Documentation for locating elements, but I can't seem to figure out how to find the element in my code.
Here is my code from my .cshtml:
<a onclick="alter('#key', '#value')" href="#edit" id="#key-display">#value</a>
I am trying to locate and click the #value at the end.
Here is what it looks like when I inspect the value on Chrome:
<a onclick="alter('February 9, 2018', '1.00000')" href="#edit" id="February 9, 2018-display">1.00000 gallons</a>
I am able to locate the element by link text like this:
chromeDriver.FindElementByLinkText("1.00000 gallons").Click();
However, the link text will change constantly and I want to be able to locate it after it changes.
I have tried locating by several ways:
chromeDriver.FindElementByLinkText("#value").Click();
chromeDriver.FindElementByXPath("//a[#id='#key-display']").Click();
chromeDriver.FindElementById("#key-display").Click()
You will have to locate the element by the HTML in the page after it's rendered so the cshtml variable name can't be used. Having said that, you should be able to find a locator that will work. I would start with a CSS selector like
a[href='#edit']
That should work unless you have multiple edit links on the page. If that doesn't work, I would try
a[href='#edit'][id$='-display']
To find the element and invoke click() on the element you can use either of the following Locator Strategies :
xpath (where ID contains -display and href is #edit)
"//a[contains(#id,'-display') and #href='#edit']"
You can be more granular adding the onclick attribute as :
"//a[contains(#id,'-display') and #href='#edit' and starts-with(#onclick,'alter')]"
cssSelector (where ID ends with -display and href is #edit)
"//a[id$='-display'][href='#edit']"
You can be more granular adding the onclick attribute as :
"//a[id$='-display'][href='#edit'][onclick^='alter']"

How do I locate a Span in HTML with specific text "Update" using Selenium

I'm trying to find 'span' element with a text 'update' within. I'm using following code to do so.
<<span class="update-btn-text">Update</span>
This fails and selenium is unable to find the element. How can I find an element with specific text with span?
You can use any one of the following locators.
Using className:
driver.findElement(By.className("update-btn-text")).click();
Using CSS selector:
driver.findElement(By.cssSelector("span.update-btn-text")).click();
Using XPath:
driver.findElement(By.xpath("//span[#class="update-btn-text"])).click();
driver.findElement(By.xpath("//span[text()='Update']")).click();