Selenium : xpath following-sibling where siblings have more children - c#

I hope I describe my problem/question in a comprehensible way.
I have and html that looks like this:
<div class="class-div">
<label class="class-label">
<span class="class-span">AAAA</span>
</label>
<div class="class-div-a">
<textarea class="class-textarea">
</textarea>
</div>
</div>
<div class="class-div">
<label class="class-label">
<span class="class-span">BBBB</span>
</label>
<div class="class-div-a">
<textarea class="class-textarea">
</textarea>
</div>
</div>
I want the Xpath for the TextArea where the value of the Label is AAAA to populate it with a value in Selenium.
So somelike like this...
wait.Until(ExpectedConditions.ElementIsVisible(
By.XPath("//div[#class='class-div']/label[#class='class-label'][span[#class='class-span' and text()='AAAA']]/following-sibling::div[#class='class-div-a']/textarea[#class='class-textarea']"))).SendKeys(valueTextArea);

Problem could be in this waiter condition, ExpectedConditions.ElementIsVisible
The thing is that your <textarea> is not 'visible' in selenium context, visibility means that element is present in DOM (which is true) and it's size is greater then 0px which could be false for your <textarea> element. In java you would use ExpectedConditions.presenceOfElement() instead of ExpectedConditions.visibilityOfElement(), not sure how it goes in C# but you get the picture.
Try and see if it solves your problem.

Let me quickly rephrase the question to make sure I understand, you need an xpath to find the textbox associated with the label where the text is AAAA.
You'll have to go back up the tree in this case, here are a couple of ways I might do that, although your xpath looks correct:
Using ancestor to be clear about which element you're moving up to (better IMO)
By.XPath("//label/span[text()='AAAA']/ancestor::div[#class='class-div']//textarea");
Or just moving back up the tree with ..
By.XPath("//label/span[text()='AAAA']/../../..//textarea");
If your xpath exists, use asikojevics answer. The C# method is ExpectedConditions.ElementExists(By)
****UPDATE****
Based on your comment of a trailing space after the text value, here is another xpath that should find the textarea in that case, using contains instead of text()=.
By.XPath("//label/span[contains(text(),'AAAA')]/ancestor::div[#class='class-div']//textarea");

Related

Selenium C#: How to identify element without particular child element

I have following elements on the page:
<span class="card-body">
<span>No tickets</span>
<h5 class="card-title">..</h5>
<p class="card-text card-text-top">..</p>
<p class="card-text">..</p>
</span>
There are several the same card-body elements in the DOM, however, I would like to identify the first one that does not contain <span>No tickets</span> child element.
What is the most correct locator which I should use, while working with selenium and C#?
To identify the first element that does not have a decendent <span>No tickets</span> element you can use the following xpath based locator strategy:
//span[#class='card-body'][not(.//span[text()='No tickets'])]
Your effective line of code will be:
driver.FindElement(By.XPath("//span[#class='card-body'][not(.//span[text()='No tickets'])]"))
Snapshot of the example:
//span[#class='card-body'][not(span[text()='No tickets'])]
Gets the span with class card-body that does not have span with text "No tickets".

c# selenium finding element using xpath

I am trying to find an element which is a div inside a div...
here is example of the code:
<div class="col-md-4">
<div style="display: none;" id="multiplier-win" class="label label-success multiplier">2X</div>
<div style="display: block;" id="multiplier-lose" class="label label-danger multiplier">0X</div>
<div style="display: none;" id="multiplier-tie" class="label label-warning multiplier">1X</div>
</div>
I want to find the class="label label-success multiplier" and check if her style="display:none".
How do I write this in c#?
Please help me
thank you!
In your case, the elements have a unique ID. So instead of finding them by class name (which could lead to multiple/inaccurate results), you should use By.Id(...). It is more easy to write by hand than xpath, too.
Let's say your IWebDriver instance is called driver. The code looks like this:
IWebElement element = driver.FindElement(By.Id("multiplier-win"));
String style = element.GetAttribute("style");
...
I don't want to offend you, but you should probably use google before you post here. This is very basic code you will find in multiple tutorials about selenium.
Edit: In case you are looking for multiple elements of a class:
ReadOnlyCollection<IWebElement> elements = driver.FindElements(By.ClassName("..."));
foreach (IWebElement el in elements)
{
...
}
To Find the element:
IWebElement element = driver.FindElement(By.XPath("//div[#class='label label-success multiplier']"));
To check if an element is displayed, this returns a bool (true if displayed, false if not displayed). If you go with philn's element list code, you can throw this line into his foreach statement and it will tell you which ones are displayed.
el.Displayed;

How to find div Element without an id attribute with Selenium Webdriver

I'm using C# and Selenium Webdriver and I'm trying to find a div Element in my html code which looks like this:
<div class="x-grid-cell-inner" style="text-align: left;" unselectable="on">
phys_tag_desc
</div>
I cant find a method to search for the value of the div Element with Selenium Webdriver. I already searched this site and checked the Selenium Webdriver Documentation, but couldn't find anything.
Well if text value is unique, then solution is simple. Try the xpath below:
//div[text()='phys_tag_desc']
If the text is not exact match. Try following:
//div[contains(text(),'phys_tag_desc')]
I have two ways.
Way 2 is more complex but more effective.
Way 1;
You can loop in all divs and look for some equals
Example:
foreach(HtmlElement o in webbrowser.Document.GetElementByTagName("div"))
{
HtmlElement yourElement;
if(o.GetAttribute("class")=="x-grid-cell-inner"&&o.GetAttribute("style")=="text-align: left;")
{
yourElement=o;
break;
}
DoSomethingWith(yourElememt);
}
The other way is follow elements path;
You can find the closer element that has a ID
Example:
<div id="element">
<div>content..</div>
<div>
<div class="x-grid-cell-inner" style="text-align: left;" unselectable="on">
phys_tag_desc
</div>
</div>
</div>
The closest element that have id on this example is
<div id="element">
your element's parent is 2. children of id="element" div
You can get it and follow path like this
yourElement = webbrowser.Document.GetElementById("element").Children[1].Children[0];
In other situation you can use the XPATH Boolean operators.
Try the xpath below:
By.XPath("//div[contains(#class,'*x-grid-cell-inner*') and contains(#unselectable, '*on*') and contains(text(),'*phys_tag_desc*')]")
Bye

How to display multi line in Label?

The following is the record which I am getting from the database:
"Dear:Thank you for applying to school. We have received your application to the program.As of today,we have received the following for your application:"
I am trying to put the above value into a label. My label looks like the following:
<div id="secondd" style="float:left;width:50%;background-color:#C0D5F2;">
<asp:Label id="valueIntroduction" Cssclass="labelarea" runat="server"> </asp:Label>
<div class="line"></div>
My problem is value is not getting fitted into the label. How to make it as a multi line label?
Here is the HTML that contains this div:
<div id="first" style="float:left;width:50%;background-color:#C0D5F2">
<div id="second" style="float:left;width:50%;background-color:#C0D5F2">
<div id="Introduction" style="float:left;width:100%" class="wote">
Introduction:
</div>
<div class="line"></div>
</div>
<div id="secondd" style="float:left;width:50%;background-color:#C0D5F2;">
<asp:Literal id="valueIntroduction" runat="server"> </asp:Literal>
<div class="line"></div>
</div>
If you want the text to wrap based on the in-line style of your outer <div>, you can change the <asp:label> to an <asp:literal> and use CSS to style the outer <div>.
The difference is that a Literal does not render any HTML markup, whereas a Label will be wrapped in a element. The Literal just inserts the exact text you have, letting your existing HTML and CSS do the styling.
An example of a different style would be:
Less percentage, note 20% instead of 50% for the width attribute:
<div id="secondd" style="float:left;width:20%;background-color:#C0D5F2;">
Or, use a dedicated value of pixels (denoted by the px)
<div id="secondd" style="float:left;width:150px;background-color:#C0D5F2;">
You can even indent the text, using text-indent. I suggest to google some basic CSS and just try different things out, it is the best way to learn.
You just have to play with it to see how it fits in your webpage. Once you get the hang of it, note for future reference that you can use style sheets for this stuff which will make your code cleaner and allow you to create reusable, easily editable styles for your application.

Turning HTML Div code into a Control

I have bunch of HTML code I am using to make rounded edge boxes on my controls. Is there a way to take this code and turn it into some kind of control or something so I do not have to keep pasting 10 lines of HTML code around everything I do?
<div id="BottomBody">
<div class="box1024" >
<div class="content1024">
<div class="top1024"></div>
<h1>My Header Information</h1>
<hr />
<p>Some text for everyone!</p>
</div>
<div class="bottom1024">
<div></div>
</div>
</div>
</div>
One additional thing to note, the number HTML tags used inside the inner most DIV will change depending on where I use it in my site. So in some cases I will only have 1 tag and 1 tag but in other cases I could have 1 tag, 1 tag, 3 tags, and a HTML table. How can I make that work?
Yes, you're thinking of a UserControl. Extract the relevant HTML out, paste it into a UserControl .ascx template.
Now in your case, you'll probably want the text to be customizable, am I right? So you'll need to replace the <h1> through </p> bit with an ASP.NET label. The resulting .ascx HTML (not counting the #Control directive) will look something like:
<div id="BottomBody">
<div class="box1024" >
<div class="content1024">
<div class="top1024"></div>
<asp:Label runat="Server" id="label1" />
</div>
<div class="bottom1024">
<div></div>
</div>
</div>
</div>
Alternatively, you could do two labels -- one for the header, one for the main text. Or even just have the header be runat="Server" itself.
Next, you'll write a little bit of code in the .ascx code-behind file to expose the label's (or labels', as the case may be) Text property. This would probably look something like:
public string Text
{
get { return label1.Text; }
set { label1.Text = value; }
}
If you're in an ASP.NET MVC world, use your Model data instead of a label, and pass in the desired display text string as the model data.
Edit
Addressing the update to the question:
One additional thing to note, the
number HTML tags used inside the inner
most DIV will change depending on
where I use it in my site. So in some
cases I will only have 1 tag and 1
tag but in other cases I could have 1
tag, 1
tag, 3 tags, and a HTML table. How can
I make that work?
The exact same technique, assuming that the content you're referring to is what's within <div class="content1024">. The Text property of a label can contain any desired arbitrary HTML, and of course you can pass any arbitrary amount of HTML as a string to the Model if you're using MVC.
Another left field approach - create a user control but use jQuery to round the corners for you:
<div class="roundcorner">
<h1>My Header Information</h1>
<hr />
<asp:Label runat="Server" id="label1" />
</div>
Issue the following in javascript:
$(document).ready(function(){
$('div.roundedcorner').corner();
});
This eliminates all your extra div's and you can still have a user control that you use at will on the server.
(I know I'm going to get in trouble for this from someone)
If its just static content you can just put it in a separate file and INCLUDE it
<!--#INCLUDE VIRTUAL="/_includes/i_yourfile.htm" -->
(File name, extension and location are arbitrary)

Categories