Goal:
Select the second link, from top, by using By.LinkText
<a class="ng-binding" href="#/test/id_var1">324 fff</a>
<a class="ng-binding" href="#/test/id_var2">44 gggg</a>
Problem:
In this context the link text 44 gggg is not static because the link text changes every time the page is refreshed.
My idea is to retrieve all class="ng-binding" and then use the second link as a linkText, but I don't know how do it?
The answer is simply that it is impossible. You cannot get an element by link text if this text is dynamic and you don't know the value.
You could select it using other methods though.
css-selector
a[class='ng-binding']
tag-name (not recommended as it is probably not unique)
a
class-name
ng-binding
xpath
//a[#class='ng-binding']
Find the elements in a list and pull out the one you need.
Another option is selecting the 2nd element immediately using xpath.
(//a[#class='ng-binding'])[2]
use the below as cssSelector:
a.ng-binding[href$='/test/id_var2']// this will return the second link.
if u want to get all the elements using the
ng-binding
class, use the below as cssSelector
a.ng-binding//return all elemtns using the ng-binding class
You can also use below xpath:
//a[#href="#/test/id_var2"]
Related
enter image description here
I need to click the 'Practice Form' tag highlighted in the attached image using C# Selenium here.
The url of form is https://demoqa.com/forms
and the upon clicking 'Practice Form' it will be redirected to https://demoqa.com/automation-practice-form.
I need to achieve this through clicking, not by navigating.
This XPATH should perfectly work:
//span[contains(.,'Practice Form')]//ancestor::li[#class='btn btn-light ']
Short explanation:
You find span containing specified text
You go to ancestor to get button's xpath.
You need to find it with selenium and use Selenium's click()
This is one of xpaths you can use.
Another option is just going a level up:
//span[contains(.,'Practice Form')]/..
I like both.
Option 3:
//span[contains(.,'Practice Form')]//parent::li[contains(#class,'btn btn-light')]
I am not sure why yours isn't working, but this works fine for me:
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.demoqa.com/forms");
driver.FindElement(By.XPath("//span[contains(.,'Practice Form')]//parent::li[#id='item-0']")).Click();
It takes me to:
https://www.demoqa.com/automation-practice-form
With the Student Registration form shown in the middle
BTW in your original comments you said you had to use XPath for this because that field is "dynamic". It is not dynamic. The element has more than one ID: item-0, maybe that is what you meant by couldn't use ID. But the element itself is not "dynamic"
This simple XPath works for me
//span[text()='Practice Form']
You may use the below xpath
//li[#class[contains(.,'btn-light')]][contains(.,'Practice Form')]
I am trying to create this simple test where you head to the URL, enter your login credentials and then click the button to sign in. It is doing everything, except for clicking the button. I am trying to doing it by calling up ClassName. Can anyone look at my test and see what I am doing wrong?
public void test_search()
{
var driver2 = new ChromeDriver(#"C:\Users\MyName\Desktop\NUnitTestProject1\NUnitTestProject1\bin\Debug\netcoreapp2.1");
driver2.Navigate().GoToUrl("https://portal.crushdata.com/");
driver2.FindElement(By.Name("Email")).SendKeys("email#email.com");
driver2.FindElement(By.Name("Password")).SendKeys("Password");
driver2.FindElement(By.ClassName("btn bg-teal btn-block btn-lg waves-effect")).Click();
}
This is my classname for my button.
Use CSS selector as shown below:
By.ClassName("btn.bg-teal.btn-block.btn-lg.waves-effect")
Each dot represents a class.
See this page for more info and here is an example from that page:
.name1.name2
Selects all elements with both name1 and name2 set within its class attribute
To click on the SIGN IN button you have to induce WebDriverWait for the desired ElementToBeClickable() and you can use either of the following Locator Strategies:
CssSelector:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("button.btn.bg-teal.btn-block.btn-lg.waves-effect"))).Click();
XPath:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//button[text()='SIGN IN']"))).Click();
Try making use of the button xpath.
Open the dev tools. Right click on the button you want to be clicked > Select Inspect >Then right click the html in the dev tools window and Copy Xpath from the Copy option.
Then in you code replace FindElement with FindElementByXPath:
driver2.FindElementByXPath("//*xpath/goes/here")).Click();
Given your shared html block, the following XPath will suffice.
//div[contains(#class = "text-center")]//button[contains(#class, 'btn bg-teal btn-block btn-lg waves-effect') and #type = 'submit']
If the driver is still unable to click you should consider the following:
Is the XPath unique? paste the xpath in chrome's devtools search box in the inspect element tab and make sure the provided xpath is targeting the element you are intending. If this is not the case then you should make the xpath more unique.
Is the element in an iframe? if the element is in an iframe the driver won't be able to locate it by default. In such cases you will need to first switch to the iframe and then attempt to locate and interact with the element.
Is the element clickable, visible and enabled? To check these properties first find the element and store in a separate variable and then check the said properties are true.
I have been trying various locators and can't find a simple solution to locating the number (which is dynamic and changing each page load) inside this span in C# Selenium. I am just trying to locate the span itself to start with.
<span inventory="Livecount">129</span>
I get the NoSuchElement exception, i.e. unable to locate element.
Last context-related thing: this span and its number live inside of a widget, which I have been able to locate just fine. That widget doesn't have a unique class or id, but a custom tag-name, so I'm only able to locate it reliably using the FindElement(By.TagName("inventorySearch")), which works. If there was a way I could use a CSS selector to start with that widget element (the parent) - and then chain down to the span inside it (there's only one span in each instance, so it would be easy to locate), that would solve it. My problem there is, I don't know how to indicate tagname inside a Seleniums CSS selector (i.e. classes and Id's have their . # symbols - is there a tagname equivalent in C# Selenium? Thanks.
Answering the question in the title, it is possible to locate a <span> with the text '129 via XPath:
//span[text()='129']
However I suspect that this number will change, so you may also want to consider locating the <span> where its inventory attribute equals 'Livecount':
CSS Selector:
span[inventory='Livecount']
XPath:
//span[#inventory='Livecount']
Usage:
driver.FindElement(By.CssSelector("span[inventory='Livecount']"));
driver.FindElement(By.XPath("//span[#inventory='Livecount']"));
Paraphrasing your last question, you asked if it's possible to use a CSS selector with a custom tag-name. This is also possible.
Given the following HTML:
<inventorySearch>
<span inventory="Livecount">129</span>
</inventorySearch>
To select the <span> within the <inventorySearch> element, use the following CSS selector:
inventorySearch > span
This is also possible using CSS
JQuery has a :contains pseudo selector
i.e. span:contains('129')
You will need to use the Selenium NuGet Support Package to get this functionality.
Install-Package Selenium.WebDriver.Extensions
This gives access to the Sizzle JQuery Selector Engine which provides the pseudo selector support.
I am supposed to click the link (highlighted blue, refer to image above), but LinkText does not work. I also tried using CSSSelector and XPath, but both:
_driver.FindElement(By.CSSSelector("HH3"]")).Click();
_driver.FindElement(By.XPath("div[text()="HH3"]")).Click();
doesn't work. Help?
Your tried locator looks incorrect, you should try using xpath with text to locate desire element as below :-
_driver.FindElement(By.XPath(".//div[text()='HH3']")).Click();
Try _driver.FindElement(By.XPath("//div[contains(text()='HH3')]")).Click();
Here's a simulation of the HTML I am trying to use my XPath on:
<div class="stream-links">
<div>
value I need
</div>
<div>
value I need
</div>
<div>
value I need
</div>
</div>
Now, when I use the XPath pattern //div[#class='stream-links']/div/a in my browser it selects the <a ...> node. Everytime I press enter it selects the next one, but when I use the pattern //div[#class='stream-links']/div/a/text() it gets stuck on the text of the first <a ...> node so when I press enter it does not move to the next. (Using Firebug plugin on FireFox btw to inspect element)
I'm coding a program in C# and the amount of divs under the parent div is a variable so I can't use //div[#class='stream-links']/div[number here]/a/text() because I need to get all of them.
My code for using the Xpath is HtmlNodeCollection NODECOL1 = MEDOC.DocumentNode.SelectNodes("//div[#class='stream-links']/div/a[1]");
So my questions are:
1) Is there a particular reason Firebug doesn't jump to the next <a...> or is it a 'bug' on the plugin's side?
2) Will my code work nevertheless or do I need to approach it in another way?
There're a few things not right with the rest of my code so I can't see if that part of my code actually works or not, wouldn't ask question 2 if I could test it myself right now.
For your HTML, this XPath selects three a elements:
//div[#class='stream-links']/div/a
This XPath selects three text nodes:
//div[#class='stream-links']/div/a/text()
This XPath selects one a element:
//div[#class='stream-links']/div/a[1]
My code for using the Xpath is HtmlNodeCollection NODECOL1 =
MEDOC.DocumentNode.SelectNodes("//div[#class='stream-links']/div/a[1]");
1) Is there a particular reason Firebug doesn't jump to the next
or is it a 'bug' on the plugins side?
//div[#class='stream-links']/div/a[1] only selects one a element.
2) Will my code work nevertheless or do I need to approach it in
another way?
There's a few things not right with the rest of my code so I can't see
if that part of my code actually works or not, wouldn't ask question 2
if I could test it myself right now.
That's not a reasonable question to ask given what you've shown us. Perhaps knowing what the above XPaths return will help you answer it for yourself.