How to chain CSS selectors with text selectors in Webdriver.io - webdriver-io

I have an element that I need to specify using both a CSS selector and the text of the element.
Here's a (slightly) simplified version of the element in the HTML.
<a class="fakeLink ng-binding" ng-click="onSelectNode(arsPeerNode._id)">self</a>
I have this selector, which does work.
var item= $('[ng-click="onSelectNode(arsPeerNode._id)"]').$('..').$("=self");
However, I feel that this is super hacky. Is there a way to more eloquently specify that I want to find the element with the given ng-click and with the given text?
I've tried
var item= $('[ng-click="onSelectNode(arsPeerNode._id)"]=self');
Which as expected, did not work. I think that I can accomplish something slightly neater with xpath? But I suspect there's an easier way to do what I'm describing.

Related

How to write a CSS Selector selecting elements NOT having a certain attribute?

How to write a CSS Selector selecting elements NOT having a certain attribute?
I have 2 <div> nodes as follows:
First:
<div class="weEq5" style="will-change; width;">
<button class="_35EW6">
Second:
<div class="weEq5">
<button class="_35EW6">
I need to select the <div> (with the similar class) and each of them which have a similar descending <button> but without the style attribute.
XPath seems working fine as:
//div[#class and not (#style)]/button
I am looking for an equivalent CssSelector.
Trials:
div[class :not(style)]>button (doesn't works).
I have been through the following discussion but they seem to be discarding the class attribute as :not([class]) as in:
Can I write a CSS selector selecting elements NOT having a certain class?
Is it possible to define in CSS NOT to apply style if element have certain class? [duplicate]
I was looking in similar lines ending with :not(attribute).
I think more accurate CSS Selector is:
div[class]:not([style])>button
because the button element is a child of div element.
Hope it helps you!
That's the code you're looking for:
div:not([style]) button{
background-color: red;
}
Now let's break it down.
We have have four selectors in this example:
div and button - these select html elements. We can replace it for example with a class selector like .weEq5.
:not() - indicates that we want everything that does not qualify as the selector inside the brackets.
[style] - an attribute selector which is very powerful. We can place inside the not any other css selector like html tag names (button or div), class names or ids.
The combination of div:not([style]) means that we want all divs that do not have a style attribute. After which we have a space and a button means that we want all the buttons that are inside the above selector.
Adding a > before the button div:not([style]) > button will only select button elements which are direct children of the selected div. It will exclude from selection buttons that are deeper inside the div.
Normally, you would write :not([style]) to match an element that does not have a style attribute, as described here which emphasizes the use of both () and [] brackets, in that order.
But if this isn't working in Selenium WebDriver, and worse still if :not(style) works exactly like how I would expect :not([style]) to, then that's a bug with its CSS selector parser, since :not(style) actually means "not a style element" which makes div:not(style) redundant as an element can only either be a div or a style but not both at the same time. Unless you absolutely require a selector, I strongly recommend using the XPath locator strategy instead of relying on quirks like this with Selenium WebDriver's CSS selector engine that force you to write selectors that are both incorrect and don't work anywhere else that accepts a selector.
I do not understand how the situation developed in the first place, where the structure of the page necessitates the CSS rules to be aware of whether "style=..." exists in the document itself. Or even why style=... is being used.
The style attribute is old-school now, pre-CSS I believe. It also takes precedence over anything in the CSS. That attribute does not accept CSS class names. It accepts only native html style properties like "width","height","font" - old-school stuff - ultimately those are what your CSS resolves to, no matter how fancy or obfuscated it is through frameworks: font, width, left, top, float.. and so on.
By use of the class attribute (instead of style) in the document you get infinite control from which to write smart selectors in your CSS.
You can put 3 classes in the class attribute of your div for example, if you want, and have your selectors apply styling to it if 2 of the classes are present but not if all 3 are there. Tonnes of flexibility, no need to override or use "style=..." in the document at all.

How to click on checkbox on webpage using selenium vba

I have a query,how to click on checkbox on webpage using selenium vba.
Below is the screen shot where i want to click
Below is the html code.
<span name="locSpans[]" value="Nerul" style="display:block">
<input type="checkbox" name="locArr[]" value="8897" onclick="enableDisableLocality(); showSelectedLoc();">Nerul
<br>
<input type="hidden" name="locArrVal[]" disabled="disabled" value="Nerul">
</span>
FindElementByCss is generally faster unless using IE, and then it depends which version of IE and what type of traversal is required.
Repeated tests have proven FindElementByCss to be more performant than FindElementByXPath (Note: that if there is a unique id present then selecting by id is always the first choice!)
In benchmarked tests Chrome and FireFox saw faster matching using CSS consistently across different traversal paths. They are optimized with CSS in mind and using CSS selectors is advocated as selenium best practice. IE was more variable with most instances of XPath being slightly more performant, but there being some clear paths that favoured CSS selection. Long XPath selectors will be costly and prone to breakage. Later versions of IE saw more variability. Opera12 browser came in with mixed results.
I would use a CSS selector:
So, for a simple selection based on likely unique attribute, I would go with an attribute CSS selector of [value='8897'] to target the value attribute. The [] means attribute selector. So value attribute with value of 8897.
driver.FindElementByCss("[value='8897']").Click
If you want to be more selective you can throw in an additional attribute selector, as follows, to target the type attribute.
driver.FindElementByCss("[type=checkbox][value='8897']").Click
When should I use XPath then?
Older IE versions for sure.
Any requirement for walking up the DOM would point to XPath usage.
XPath has some great additional locator strategies for hard to find elements, but that is not necessary AFAIK here. You can see some of the additional considerations here.
You can use xpath below to get checkbox, it means: find input with type="checkbox" and parent SPAN with text "Nerul".
driver.FindElementByXPath("//input[ancestor::span[normalize-space(.)='Nerul'] and #type='checkbox']").Click
Try this if not go for CSS Selector Option
bot.Window.Maximize
bot.FindElementByName("locArrVal").Click
bot.Wait 1000

Is there a way to get the HTML of an element?

I'm using the FluentAutomation version of Selenium, and I can't find any way to get the HTML of an element. I can get the text and attributes, but there doesn't seem to be any way to get the full HTML content, which I need for a certain kind of test I'm doing.
Is there any way to do this?
Assuming you mean the innerHTML or the outerHTML, you should just be able to call GetAttribute on the element, or whatever it is in your language.
Example C#:
element.GetAttribute("innerHTML");
Example Ruby:
element.attribute('innerHTML')
I am not sure if a straight-forward way exists, anyway, it should be possible to execute something similar to:
((JavascriptExecutor)driver).executeScript("return arguments[0].innerHTML;", element);

Handling dynamic ids and classes

I am using selenium to test a web application, The ids and classes are always changing dynamically.So that I am not able to give correct identification, is it possible to get ids of the element in run time and is there any other method to handle this situation.
It depends on if ids are completely random or if there is some part of the id which remains the same. If yes, then cssSelector is the obvious choice
driver.findElement(By.cssSelector("div[id*=somePart]");
where id* means id contains. If you cant use this approach you will have to track down your element using xpath or again cssSelectors. XPath example is here and CSS selector could look like this
By.cssSelector("boyd table input");
I would strongly recommend locating elements by XPath -- with the caveat that you make your XPaths robust and not just "copy" the xpath using your browser's developer tools. XPath is very easy to learn. You can use XPaths to walk up and down the DOM, and identify elements by their text, or their attributes.
For example, maybe you need to click a button that has a span that contains the text that appears on the button:
<div class="btn-row random-generated-number-1234897395">
...
<button id="random-generated-number-239487340924257">
<span>Click Here!</span>
</button>
...
</div>
You could then use an xpath like this:
//div[contains(#class, 'btn-row')]//button/span[text()='Click Here!']/..
(The /.. at the end walks back up from the span to the button.)
XPath is powerful and flexible and easy to learn. Use it when the ids and classes aren't reliable.

Selenium object identification

I am using Selenium webdriver to test my application & i am facing difficulties in identifiying button on the same. the code snippet is like :
<input type="submit" onclick="return sign(this);" value="Login">
and its xpath is :
html/body/table/tbody/tr[2]/td/center/form/center/table/tbody/tr[3]/td/center/input[1]
Which object property to use and how?
You should not use that XPath.
I would hazard a guess that you used some sort of tool, whether it's Firebug or IDE, to generate that XPath. Stop that now!
XPath is fine to use, and can be used here, just not relying on the tools to generate it for you! That XPath is destined for failure!
You will need to provide more HTML, specifically around that button.
However, you should just be able to use something as simple as:
//input[#value='Login']
You can use the xpath, if that is really stable. I found that it is much easier to define id tags in the html elements and the use a By.id locator. Alternatively you can use css selectors, depending on the "uniqueness" of your button something like this could work:
By.cssSelector("input[value='Login']")