How can Selenium in C# locate this span based on its value? - c#

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.

Related

CSS Element is obscuring Xpath element

A temporary CSS element is obscuring the xpath element I want to click on.
Using Selenium in Visual Studio I am writing a testcase where an element is to be clicked. But when I run this testcase I get an error message telling me:
OpenQA.Selenium.ElementClickInterceptedException Element <a href="#/app/customer/handling/devices"> is not clickable at point (105,221) because another element <div class="showbox layout-align-center-center layout-row ng-star-inserted"> obscures it
The obscuring element seems to be a CSS element. But when I manually go to this page, inspect the code and search for this css element
<div class="showbox layout-align-center-center layout-row ng-star-inserted"> I get no results.
I am therefore assuming that this CSS element is temporary and can only be identified for a couple of seconds while the page is loadning. This assumption is confirmed by the fact that if I put a static wait method Task.Delay(4000).Wait();in this testcase I am able to complete this testcase.
But I'm not interested in a solution where I use a static wait method in my code. I want to be able to wait for the temporary css to disappear so I can click on my desired xpath element.
This is my code:
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to be visible
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
//Waiting for temporary CSS element to disappear
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div/div[2]/nav[2]/div/ul/li[1]/a"))).Click();
//Click on "Handle Tools" link
As you can read by the comments in my code I do three things here:
1. I wait for the temporary CSS to be loaded
2. I wait for it to disappear
3. I click on the xpath element.
When I do this I get an error telling me the CSS selector I'm trying to find is invalid.
If I skip the first step and just wait for the CSS to disappear/be "invisible" it will check this too fast and look before the CSS element have started loading.
So either I'm not writing the By.CssSelector format correctly. Or the CSS element is called something else than Visual Studio is calling it in the error message I quoted above.
So please tell me if I'm using an incorrect way to identify this CSS element here:
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div class='showbox layout-align-center-center layout-row ng-star-inserted'")));
OR
Is there another way to dynamically wait out temporary CSS elements?
OR
Can I somehow confirm that the name of obscuring CSS element is actually called "div class='showbox layout-align-center-center layout-row ng-star-inserted'"?
So I am not 100% sure what you mean by a CSS element. But I am thinking it is just a misnomer you may have picked up. But CSS is cascading style sheets. It is markup that defines the appearance of a Document Object Model (DOM) element.
XPath is an approach to defining the location of an element for a driver to find it and interact with it. Css selectors are an alternative approach to finding elements in the xml or html of a DOM. So there is no such thing as a "Css element" or an "XPath element". They are just "elements".
As for fixing the issue you are seeing, you could try this:
//This is called an extension method. It adds methods to an existing class. This should go in a static class that is accessible to your driver.
private static void WaitUntil(this IWebDriver driver, Func<bool> Condition, float timeout)
{
float timer = timeout;
while (!Condition.Invoke() && timer > 0f)
{
System.Threading.Thread.Sleep(500);
timer -= 0.5f;
}
System.Threading.Thread.Sleep(500);
}
driver.WaitUntil(() => driver.FindElementsBy(By.CssSelector(".showbox.layout-align-center-center.layout-row.ng-star-inserted").length == 0);
Also of note, your CSS Selectors in your description are completely invalid. I suggest reading up on them in a tutorial like this one.
The problem in this case was that my CSS selector was indeed invalid. Removing the "div class=" in the beginning and adding a "." solved the problem.
Before:
"div class='showbox layout-align-center-center layout-row ng-star-inserted'"
After:
".showbox.layout-align-center-center.layout-row.ng-star-inserted"
Thanks to Asyranok for providing me with the correct format for my CSS selector.
I did not need the rest of your code in this case, instead I just copied the correct CSS format from your code into my solution and it worked. :)
I usually only use xpath when trying to identify an element so I'm not that used to CSS and what format to use.
Also thanks to JeffC for confirming my suspicion that I need to wait for the obscuring element to first load and then wait again for it to disappear.

Retrieve the dynamical link text using Selenium

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"]

Selenium WebDriver with RadWindow

I am attempting to access a form within a RadWindow. The web page uses window.radopen() to generate an ASP.NET popup. I need to access that popup, edit it, and click a button. Is there a way to do this using Selenium WebDriver?
Specifically, the radwindow contains a textarea with an id of "txtEntries" and a button with and id of "btnAccept". I have tried finding the textarea first, as below, with no luck.
I am currently attempting:
state = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.CssSelector("div#radWindow #txtEntries"));
});
With failed results.
Yea, there's a way.. Since RadWindow is not an actual window, it makes it significantly easier.
First, use CSS and have a parent selector. Something like,
div#radWindow
Then just add the elements you want to find to that. e.g.
input[type='text'].someclass
then just concatenate them, so it turns into this -
div#radWindow input[type='text'].someclass
which translates in CSS to "first find a div with id radWindow, and find an input that is a descendant of the div, with the type attribute that equals text that has someclass attached.

Popup on mouse hover the word

I am doing a website using asp.net C# and I would like to popup a small window with information as soon as mouse hover a particular word. I know that I have to use jquery but I don't know exactly how to do it.
Any suggestions please?
There are many plugins out there that will help you achieve what you are looking for. However it is also very possible to implement this functionality yourself. I wouldn't be surprised either if some of the plugins you come across also use similar code.
The following is my attempt to demystify tooltip/popup plugin behaviour.
You could wrap the desired word in a <span> element and give it a .hover class.
<div>
This is some text with a <span class="hover">special</span>
word that has hovercraft capabilities.
</div>
Your jQuery (ver 1.7+) would look something like this :
$(".hover").on('mouseenter',function(){
// The popup must be shown here (mouse is over element).
}).on('mouseleave',function(){
// The popup must be hidden here (mouse has left element).
});
I should add here that I am using a great and yet sometimes forgotten capability of jQuery called "chaining". The on() function actually returns the object that it was attached to. In this case $(".hover") - so if I want to call another function on that object I can just add it as another function at the end. Another example of this would be :
$("#myElement").text("An error has occured!").css("color","#FF0000");
That line of code would also at the text to #myElement and also turn the colour red.
With regard to your actual popup - I would suggest two things :
Have an element at the bottom of your markup (written last so highest index - or manually set the highest z-index)
You could also have the popup in a hidden element right next to the element that is supposed to trigger the popup.
What you're after sounds like a 'tool tip'.
The solutions using jQuery are somewhat involved - so I'll just direct you to external resources.
Possible solutions:
ToolTip Plugin for jQuery
Build a Better Tooltip with jQuery Awesomeness

How determine css text of each node in html

How can I iterate over HTML nodes of a web page and get the CSS Text of each node in it? I need something like what Firebug is doing, if you click on a Node, it gives you complete list of all CSS Texts associated with that Node (even inherited styles).
My main problem is not actually iterating over HTML nodes. I am doing it with Html Agility Pack library. I just need to get complete CSS for each node.
p.s. I am sorry, I should have explained that I want to do this in C# (not javascript)
I found the following code snippet useful for all element in the page and 'CurrentStyle' property of them shows their computed style:
HTMLDocument doc = (HTMLDocument)axWebBrowser1.Document;
var body = (HTMLBody)doc.body;//current style
var childs = (IHTMLDOMChildrenCollection)body.childNodes;
var currentelementType = (HTMLBody)childs.item(0);
var width = currentelementType.currentStyle.width;
Note that according to my prev post axWebBrowser1 is a WebBrowser control.
If you want the current styles for an element, look into getComputedStyle(), but if you want the inheritance too then you may have to implement the style cascade. Firebug does quite a lot of work behind the scenes to generate what you see!
You can get the CSS text from the style attribute like this:
node.getAttribute('style')
Or if you want style you can iterate through the keys and values in
node.style
If you want to grab the entire computed style of the element and not just the CSS applied in the style attribute, read this article on computed and cascaded styles.
You can use WebBrowser control in C# to access the htm document object and cast its body tag as following:
HTMLDocument doc = (HTMLDocument)axWebBrowser1.Document;
var body = (HTMLBody)doc.body;
But before that you should add com refrence: MSHTML to you project.
here you could access body.currentStyle that show you all its styles that might be css or inline styles.
You can try for (property in objName) operator as seen here.
I'm not sure if you can simply get "all" CSS properties using JavaScript to be honest, you could look into the [DOMNode].currentStyle, [DOMNode].style and document.defaultView.getComputedStyle thingamajiggy's. They should contain the 'current' style they had. What you could then do is have an array of all CSS properties you want to test and simply loop them through a function of your own that gets the CSS property for everything using forementioned methods (depending on which browser). I usually attempt the DOMNode.style[property] first as this is "inline" javascript and always rules over everything, then I sniff if the browser uses the .currentStyle method or .getComputedStyle and use the correct one.
It's not perfect and you might need to clean up some things (height: auto; to the actual current height, some browsers might return RGB colours instead of HEX) etc.
So, yes, I don't know of anything prefab that you can use in Javascript.

Categories

Resources