How to iterate sub elements of <ul> in Selenium with C# - c#

I am trying to iterate <li> items of <ul> object in Selenium with C#. I am very new to it and trying to find a easy way write a code for my test project.
here is my sample html code, I would like to access those links below...
<ul class="list-menu">
<li>
<ul>
<li><a class="head" href="/seramik-banyo-urunleri">Seramik Banyo Ürünleri</a></li>
<li>Lavabo</li>
<li>Klozet</li>
my c# code is like below
IList<IWebElement> results = driver.FindElements(By.XPath("//div[#class='list-menu']/li/lu/li"));
but it doesn't get the links. what can I do to fix this?

You have a typo in the XPath expression, replace:
//div[#class='list-menu']/li/lu/li
with:
//div[#class='list-menu']/li/ul/li
Or, you can use a more compact CSS selector instead:
driver.FindElements(By.CssSelector(".list-menu > li > ul > li"));
where > means a direct parent-child relationship.

Related

XPath select all child nodes of the first child or an element?

I'm trying to get a collection of li elements (child nodes) with Selenium using xpath but its returning null?
Javascript pseudo code:
document.getElementsByClassName("jSC57 _6xe7A")[0].firstChild.childNodes
I want to get that in XPATH - but its returning null?
document.DocumentNode.SelectNodes("//*[#class='jSC57 _6xe7A']//div//li");
HTML sample:
<div class="isgrP">
<ul class="jSC57 _6xe7A">
<div class>
<li class="wo9IH">
<div class="li-container">
testing
</div>
</li>
</div>
</ul>
</div>
Based on your statement document.getElementsByClassName("jSC57 _6xe7A")[0].firstChild.childNodes, I am making an assumption about what you want to retrieve here. getElementsByClassName("jSC57 _6xe7A") will return a list of ul element. Then, your [0] gets the first ul. firstChild will grab the first div element, and childNodes refers to the li elements that appear under div.
To get the li elements you are trying to retrieve from your tree, I might not use those class names -- they appear to be dynamic and might change each time you load the page.
I would use this XPath instead:
document.DocumentNode.SelectNodes("//ul/div//li");
This will get all of the div nodes that appear under the li element.
But this might be too general for your purposes -- If you want to use the class name, you can modify as such:
document.DocumentNode.SelectNodes("//ul[#class='jSC57 _6xe7A']/div/li");

Find element in Selenium using XPATH or CSS Selector

I m trying to find the element "import" using Selenium Webdriver in C#. Have tried the following codes but nothing find it.
driver.FindElement(By.XPath("//*[#class='menu_bg']/ul/li[3]")).Click();
driver.FindElement(By.XPath("//*[#id='import']/a")).Click();
driver.FindElement(By.CssSelector("#import>a")).Click();
driver.FindElement(By.XPath("//*[#class='menu_bg']/ul/li[3]/a")).Click();
driver.FindElement(By.CssSelector("ul[#class='menu_bg']>li[value='3']")).Click();
Please help me out. Design page looks like below:
<body>
<div class="header_bg"></div>
<div class="menu_bg">
<ul class="menu">
<li id="retrieve"></li>
<li id="scan" class="test"></li>
<li id="import">
<a target="main" href="import/import.aspx" onclick="clickme(this,'import')">Import</a>
</li>
<li id="admin"></li>
<li id="help"></li>
<li style="float: right;"></li>
</ul>
</div>
</body>
All the time I got the error as below:
unable to find the element
XPath indexers are 1-based, as opposed to most other languages whereby they are 0-based.
This means you are actually targetting the 2nd li element, which has no anchor element.
So:
//*[#class='menu_bg']/ul/li[3]/a
However, this XPath query is not great and is too strict on position - thus although this newly fixed XPath above should work, I'd advise you to think of something else.
By reviewing this link(Thanks to #Arran), the above issue was fixed. 'switching' to the current IFrame directs Selenium to show any requests to that frame instead.
driver.SwitchTo().Frame()
You can do this by chaining Selenium 'FindElement' like so;
driver.FindElement(By.Id("import")).FindElement(By.TagName("a"));
which will give you the child of the element with ID that has a tag of 'a'.
Another way you could do this is by casting your Driver to an IJavascriptExecutor and executing javascript directly in the browser using a JQuery selector. I find this better for more complex Selenium lookups;
((IJavascriptExecutor)Driver).ExecuteScript("$("a[target='main'][href='import/import.aspx'])").click();

<li class=disabled not working for disable an option in the menu

I will like to know how to disable ChoiceC from this menu if the user is not logon to the
current site using the loging page.
The ChoiceC option will be only available to the user which have connected to the site had been approved.
Can you provide me link or example on how to perform this task with C# ?
I tried to had the class="disabled" but it didn't do anything ie the option is still available.
<div id="menu">
<ul id="menua"; class="ul menua">
<li style="text-align:center;padding:9px;" class="smallwhitetext"></li>
<li>ChoiceA</li>
<li>MenuA
<ul>
<li>option 1</li>
<li>option 2</li>
</ul>
</li>
<li>Choice B</li>
<li class="disabled">
Choice C
</li>
</ul>
</div>
I'd recommend a two-step approach. First, don't have the C# code output the link in the list item if they're not logged in. Second, change the style of the list item by applying a class to that item to indicate to the user that they're not logged in and thus the item is unavailable.
Simply applying a class to that item wont work.
I'm not sure what method you use to build the menu and choices, but normally this could best be done when the page is generated at the server. Just wrap your conditional choice inside an if-statement where you check the approval. Here is some pseudo code for the old style:
<ul>
<li>ChoiceA</li>
<li>MenuA
<ul>
<li>option 1</li>
<li>option 2</li>
</ul>
</li>
<li>ChoiceB</li>
<% if( userIsAuthenticated) { %>
<li>ChoiceC</li>
<% } %>
</ul>
Now I know there are many ways to go about outputting HMTL with MVCs and templates and stuff, but since you didn't mention any specific technique I went for the old style.
Hope it helps!
EDIT
You could also skip the mixing of C# and HTML like one used to do in ASP and still do in PHP and others by simply:
if(userIsAuthenticated) {
Response.Write(#"<li>Choice C</li>");
}
The downside is that when you get a lot of quotes its easier to miss some and a bit harder to read. Plus you wont get code coloring for the HTML.
Note: The # is for verbatim string literals which escape every special character except quotes. You escape these using double quotes instead of the usual \.
<ul id="menua"; class="ul menua">
<li>Option A</li>
<li>Option B</li>
<% if(userIdAuthenticated) { %>
<li>Option C </li>'
<% } %>
</ul>
This is working but still have a small error.
The only error I got is the top ul which is underline in green with the following error message Validation (XHTML5) Text is not allowed between the opening and closing tag for element ul.

How to achieve (auto) code format selection of any html code via jQuery / C# ? (Any solution)

Our application can share code. For example user is sharing the html code as follows
<div id="nav-vert-one">
<ul>
{{for GroupCollection}}
<li>
{{:Name}}
('{{:GroupId}}')">
</li>
{{/for}}
</ul>
which is not in a perfect format .... Now i need to achieve the (auto) code formatting ...
i.e. after auto code format click, it should look like
<div id="nav-vert-one">
<ul>
{{for GroupCollection}}
<li> {{:Name}}
('{{:GroupId}}')"></li>
{{/for}}
</ul>
So, is there ready made plugin available or is there any way(s) to achieve it either via jQuery or C#?
There is a jQuery plugin called jquery-htmlClean: http://code.google.com/p/jquery-clean/
I tried it with your code sample, this is the output:
<div>
<ul>
{{for GroupCollection}}
<li>
{{:Name}} ('{{:GroupId}}')">
</li> {{/for}}
</ul>
</div>
You can try it here: http://www.antix.co.uk/Content/Demos/jQuery-htmlClean/Test.htm

Xpath where parent and child both have attribute - htmlagilitypack

I have something like this,
<div class="rightpanel">
.
.
<ul..>...</ul>
<ul class="side-panel categories"></ul>
.
</div>
I am trying to select the ul having class side-panel categories with the htmlagilitypack.
I have tried,
HtmlDocument.DocumentNode.SelectNodes("//div[#class='right-panel']/ul[#class='side-panel categories']")
but it's giving me a nullreference exception ...
please help.
In the HTML, the div has the class rightpanel, but in your XPath it's right-panel. Please try this:
HtmlDocument.DocumentNode
.SelectNodes("//div[#class='rightpanel']/ul[#class='side-panel categories']")
And if the <ul> is not a direct child of the <div> (i.e. if it had a parent that was not the <div> itself, you would need this:
HtmlDocument.DocumentNode
.SelectNodes("//div[#class='rightpanel']//ul[#class='side-panel categories']")
with a double-slash before the ul.

Categories