I am currently writing a test against an e-commerce website. When a user runs a search for a particular product a list of items are being returned. What I am hoping to do is pass a particular value (e.g. the number 2) into my test scenario, at which point can be passed into my XPath expression (nth-child), enabling the item to be selected.
The XPath is incorrect and not sure how to fix it. Would appreciate if someone could help.
[Then(#"I select item '(.*)' from the search results")]
public static void WaitAndSelectAnItem(int item)
{
{
Driver.Instance.FindElements(By.CssSelector("#productGrid"));
var itemToSelect = Driver.Instance.FindElement(By.XPath(string.Format("//#class='itemContainer:nth-child({0})'", item)));
itemToSelect.Click();
}
}
Result Message: The given selector //#class='itemContainer:nth-child(3)' is either invalid or does not result in a WebElement. The following error occurred:
InvalidSelectorError: Unable to locate an element with the xpath expression //#class='itemContainer:nth-child(3)' because of the following error:
TypeError: The expression cannot be converted to return the specified type.
nth-child is not part of the XPath language and is actually a CSS selector pseudo-class.
Instead, you've probably meant:
(//*[#class='itemContainer'])[{0}]
Note that indexing in XPath starts with 1 - make sure you are actually getting the correct item.
Alternatively, you can use findElements() to find all "itemContainers" and then get the desired one by index. Note that it is 0-indexed here:
Driver.Instance.FindElements(By.XPath("//*[#class='itemContainer']"))[item]
Assuming that the "item container" is a DIV tag, if not div replace div by the right tag, * will work as well but there may be chances that you get more elements which you don't want.
Try this:
(//div[#class='itemContainer'])[1]
Replace 1 by your item indices.
Related
I got the id for capturing.
//button[contains(text(),'Delete')][1]
//button[#id='deletebtn']
but its have 10 duplicate values.can't identify unique thing for capture the element.Please Help me to resolve
As you haven't shared full HTML I am assuming you want use the first locator of 10 matches.
You can use
//(button[contains(text(),'Delete')])[1]
instead of
//button[contains(text(),'Delete')][1]
In case, suppose you want to use an another element then change the match number. Like below,
//(button[contains(text(),'Delete')])[3]
or
//(button[contains(text(),'Delete')])[4]
Note: Selenium by default picks the first element if there are more than one match.
Always check your xPath in chrome console to make sure it is unique.
Press F12 in Chrome.
Go to elements section
Search ( CTRL + F)
Place the xpath and see, if your desired element is getting highlighted with 1/1 matching node. This means, your xPath is unique.
You are using the wrong syntax to write the index based xpath.
Correct syntax for index based XPath-
(//button[contains(text(),'Delete')])[10]
PS: You can verify in SelectorsHub if your xpath is correct or not.
Hope everyone is well. I am having difficulties with the clicking a calendar date.
Basically I click on a button a calendar pops up and when i inspect (google chrome) the date the following td is what I need to click;
<td class="dxeCalendarDay" savedcursor="[object Object]" style="cursor: pointer;">1</td>
I tried the following code but gave me an error;
FromCalendar = Chromedriver.FindElement(By.Id("ctl00_MainContent_dpStart_DDD_C_mt"));
IWebElement FromCalendar1 = Chromedriver.FindElement(By.XPath("//tr/td[contains(text(), '>1<'")); //
FromCalendar1.Click();
The error:
OpenQA.Selenium.InvalidSelectorException: 'invalid selector: Unable to locate an element with the xpath expression //ttr/td[contains(text(), '>1<' because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//ttr/td[contains(text(), '>1<'' is not a valid XPath expression.
Hope someone can help me. Thank you in advance.
The problem with your XPath is that you are trying to locate the element by contained text of >1<. That element doesn't contain >1<, it only contains 1. Change it to //td[#class='dxeCalendarDay'][.='1'] and it should work.
Looking at your code, it looks like you have other issues.
Your first line doesn't do anything... I'm assuming you meant to click to open the calendar?
Chromedriver.FindElement(By.Id("ctl00_MainContent_dpStart_DDD_C_mt")).Click();
In general, if you aren't going to reuse the variable, don't bother storing a reference to the web element. Change
IWebElement FromCalendar1 = Chromedriver.FindElement(By.XPath("//tr/td[contains(text(), '>1<'")); //
FromCalendar1.Click();
to just
Chromedriver.FindElement(By.XPath("//tr/td[contains(text(), '>1<'")).Click();
Since you are clicking an element and a calendar opens, you should assume that it might not be instantly available so you should add a wait. Your final code would look something like this.
Chromedriver.FindElement(By.Id("ctl00_MainContent_dpStart_DDD_C_mt")).Click();
new WebDriverWait(Chromedriver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//td[#class='dxeCalendarDay'][.='1']"))).Click();
Seems you were pretty close. This error message...
OpenQA.Selenium.InvalidSelectorException: 'invalid selector: Unable to locate an element with the xpath expression //ttr/td[contains(text(), '>1<' because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//ttr/td[contains(text(), '>1<'' is not a valid XPath expression.
...implies that the XPath you have used wasn't a valid XPath Expression.
You have a couple of issues as follows:
The > and < are the part of the tags so shouldn't be a part of the XPath Expression. So you need to remove them.
You need to use either contains() or text() but not both.
The XPath Expression needs to be in proper format.
So your own XPath Expression with minor modifications will be as follows:
IWebElement FromCalendar1 = Chromedriver.FindElement(By.XPath("//tr/td[#class='dxeCalendarDay'][text()='1']"));
//or
IWebElement FromCalendar1 = Chromedriver.FindElement(By.XPath("//tr/td[#class='dxeCalendarDay' and contains(.,'1')]"));
Further, as you will be clicking on a button element for calendar popup to appear, you need to induce WebDriverWait for the element to be clickable as follows:
new WebDriverWait(Chromedriver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//tr/td[#class='dxeCalendarDay'][text()='1']"))).Click();
//or
new WebDriverWait(Chromedriver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//tr/td[#class='dxeCalendarDay' and contains(.,'1')]"))).Click();
Note: ChromeDriver is a reserved keyword which shouldn't be used as a user defined variable at any cost.
First I used this code
var query = driver.FindElement(By.Id("...")); // this will be looking for your (id/Css/Xpath..) and I created this 'var query to sent' the current DataTime
DateTime y = DateTime.Today; // this is my string (y) the current time
query.SendKeys(y.ToString()); then I send my string (y) to my query (My problem here was the click, so I created this code to waiting my string (y) and Click
new WebDriverWait(driver,TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementToBeClickable(By.ClassName("rcToday"))).Click();
// Well when my string sent (y) my calendar would show me a DataTime but it weren't clickable, then I found the WebElement over the (y), in my case was (rcToday) and done I could click over it.
var query = driver.FindElement(By.Id("..."));
DateTime y = DateTime.Today;
query.SendKeys(y.ToString());
new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementToBeClickable(By.ClassName("rcToday"))).Click();
In other words, you can try it to pick up the day with this step bellow
driver.FindElement(By.Id**("popupButton")).Click();// look your element
river.FindElement(By.LinkText("13")).Click();// you could try by (Id/CssSelector/Xpath etc...) to click over the day, if the element is unclikable try to put the code bellow and look for the element the day is selected and click.
new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementToBeClickable(By.ClassName("rcWeekend"))).Click();// this class name were my element that i found.
C# Selenium Webdriver
So i need to ensure that none of my pages (around 200 pages) contain a particular known string. Is there any way that i can scan a page for the existence of this string and if it does then return both the ElementID of that element and the entire string?
For example my source is like:
<a id="cancel_order_lnkCancel">Cancel Order</a>
I want to search for the word 'Cancel' on the whole page (<div id="sitewrapper">) and return both
cancel_order_lnkCancel;Cancel Order
Thanks
You can use XPath to find by text. e.g.:
var element = driver.FindElement(By.XPath(string.Format("//*[contains(text(), '{0}')]", value)));
value being the string you are searching for.
Then to get the element's markup and content:
var html = element.GetAttribute("outerHTML");
var text = element.Text;
or
var text = element.GetAttribute("innerHTML");
I haven't worked in C# binding but you can use FindElements to get a list of all elements containing the text. You can by no doubt use #Jarga's xpath. The good thing with FIndElements will be that it won't throw you an exception (atleast this is what happens in java) though you have to use try catch to handle getAttribute if you get null for value of id. And if you iterate over the list you can fetch all texts using getText method.
I can see a way of searching for an element within XML by just going:
if(doc.SelectSingleNode("//mynode")==null)
But what I'm more interested in, is finding an element that matches the part of the name. Something like:
doc.SelectSingleNode ...that contains "table" in it.
So if I had a node called "AlinasTable", I want it to find that. Why it matters is because my node can inconsistently contain anything that comes before "table", like "JohnsTable" - in which case I'd want that to be returned. So something more generic.
Cheers.
You can use the contains function, as in the following XPath expression:
doc.SelectSingleNode("//*[contains(name(), 'Table')]")
I am trying to select all nodes with attribute equal to something, I got the error in title.
My Xpath string looks like //#[id=****], anyone know what's wrong?
Your XPath expression probably should be:
//*[#id='something']
Which means match all elements whose id attributes are equal to something, anywhere in the document.
EDIT: If you want the id attribute nodes themselves and not their parent elements, you can use:
//*[#id='something']/#id
Or even better, as #Dimitre Novatchev suggested:
//#id[. = 'something']
I am trying to select all nodes with
attribute equal to something, I got
the error in title.
My Xpath string looks like
//#[id=****], anyone know what's
wrong?
A lot of issues with this expression:
.1. //#[some-condition] The predicate can only be applied to selected nodes, but //# doesn't select any node. # is an abbreviation for attribute:: and this is an unfinished node-test. It is missing the node-type or node-name here.
What would be correct is: //#*[some-condition] or //#attrName[some-condition]
.2. id=**** is syntactically invalid, unless ** is a valid XPath expression itself. My guess is that you want to get all attributes with value equal to some known, literal value. In any such case the syntax to use is id='someLiteral -- do note the single quotes (they can also be double quotes) surrounding the literal value.
Solution:
//*[#id='something']
This selects all elements in the XML document that have attribute id with value 'something'.
//#id[. = 'something']
This selects all attributes named id in the XML document, whose value is 'something'.
//#*[. = 'something']
This selects all attributes in the XML document (regardless of their name), whose value is 'something'.