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

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.

Related

selenium + capybara: find selector anywhere within element

Assume we have a <div class='whatever'> and somewhere deep inside there is an element <div class='inside-whatever'>
What i need is a way to access that particular inside-whatever-div using Capybara's and/or Selenium's methods.
Problem is, there is another <div class='inside-whatever'> on the page not inside <div class='whatever'>, so
within(:xpath,'//div[#class="whatever"]') do
find(:xpath,'//div[#class="inside-whatever"])
end
returns an error basically saying that there are multiple inside-whatever divs on the page.
What works is to build the xpath from whatever like
'//div[#class="whatever"]/div/div[3]/div/div[5]'
but that is pure madness.
So, is there any better way to look for selector anywhere inside any given element without having to specify a direct path?
You can merge your xpaths like this:
//div[#class="whatever"]//div[#class="inside-whatever"]
The real issue here is that you've fallen into the XPath // trap
find(:xpath,'//div[#class="inside-whatever"])
searches globally rather than from the context node. Instead you should get used to starting your XPaths with .// which will search from the current context node
within(:xpath,'.//div[#class="whatever"]') do
find(:xpath,'.//div[#class="inside-whatever"])
end
and do what you expect. This is mentioned in the Capybara README - https://github.com/teamcapybara/capybara#beware-the-xpath--trap
Note: CSS selectors don't have this issue and for most elements people are selecting read cleaner, which is why Capybara defaults to the :css selector
within('div.whatever') do
find('div.inside-whatever")
end

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.

How can i select this span element?

I am just starting with Selenium and now in need to select this element:
<span class=" close">Matrices</span>
This line of code returns zero elements, so i guess it's not the right one :-)
ReadOnlyCollection<IWebElement> matrixLink = driver.FindElements(By.PartialLinkText("Matrices"));
But I could not find another one suitable, besides the Xpath, but that looks like this (//*[#id=\"Navigation\"]/div[2]/div[2]/ul/li[7]/span), and that seems a bit fragile to me?
EDIT:
the span has the class 'close'.
It's part of a menu, where there are 19 span's with the class 'close' so it's not a unique selector unfortunately....
This will work:
//*[#id=\"Navigation\"]/descendant::span[text()='Matrices']
Note that if you can, be specific in your XPath queries, mainly to aid readability and improve performance...that is the * in your query will query all elements in the page. I don't know what kind of element the Navigation element is, but you should put it's exact element type in, for instance if it's a div, make it:
//div[#id=\"Navigation\"]/descendant::span[text()='Matrices']
A slight explanation for this XPath is that it will grab the Navigation element, and simply look anywhere inside it to find a span element that has the text of Matrices. Without the descendant bit in the XPath, it would only search for direct children. That means elements that a child of Navigation, nothing else - so if an element is a child of TestDiv which is a child of Navigation, descendant would catch it, without it you won't return any results.
As for why By.PartialLinkText would not work, this would only search for anchor links. It is common, as you have seen, that anchor links have a span element inside them or sometimes it is just a span on it's own.
By.PartialLinkText and similarly By.LinkText would not 'see' this element, since it's not an anchor element.
My favorite problem solver for these cases:
Install Selenium IDE
Click the link you need
In the "target" in Selenium IDE you will see different xpath possibilities
But I would use the approach, that its N-th element with "close" class (//span[7] or something like that)
You can use //span[text()='Matrices']
It will select your element.

Why isn't the line-height property of <input> what I set in CSS?

I explicitly set the line-height property of an <input> element in CSS. But when I check the element in firebug, the line-height value of this element is not what I set in CSS. And it seems that the line-height value has nothing to do with what I set in CSS. What is the possible reason for this?
According to the definition of line-height in the CSS 2.1 specification, it has a specific meaning for block container elements and a different meaning for non-replaced inline elements. I can’t find any statement on replaced inline elements there, and an input element can be regarded as a replaced element, somewhat debatably.
Anyway, odd as it may seem, browsers seem to ignore line-height on input elements. As a workaround, you might consider setting the height property, or setting vertical padding. But the results won’t be consistent across browsers. As a rule of thumb, we should expect the rendering of a text input box to the under the control of the browser, though in some cases some features can be tuned using CSS.
not sure if that was the point but i specified margin, padding and got rid of border, here you got exactly 14px: http://jsfiddle.net/mymlyn/Uq5Tt/2/
if you check the dev tools it is (and was before specyfying the above) exactly 14px:
http://dl.dropbox.com/u/26827941/ScreenShot060.png (chrome dev tools)
http://dl.dropbox.com/u/26827941/ScreenShot061.png (firebug in ff)
the reason in your case might be that your input field has a specified id or class,
<input id="someID"/>
and there is something like
input#someID {line-height: 20px;}
in your css somewhere else, andyou might be trying to change its value by setting
input {line-height: 14px;}
if that was not the case im out of ideas :)
The lineheight wont be rendered in firefox but i think it will be in IE. There's a small trick to do, which is to let lineheight style to be rendered as block elements instead of an inline elements.
For example:
This will not work
span {font-size:12px; line-height:14px}
But this will:
span {font-size:12px; line-height:14px; display:block;}

Coldfusion object inheritance sanity check needed

I need to know if I am going about something the right way.
For a given page, I am instantiating an object for the page itself. Let's call that object myPage. Within the page I have containers (usually div tags). When I go to an admin component to work with a specific div, I instantiate an object for that as well. Let's call that myDiv.
Now, one of the things I want to work with for a given div is the styling of that div. So normally I would think that I'd just put in some style-related methods, such as myDiv.getPadding() or myDiv.getBackgroundColor(), etc.
But it occurs to me that I may eventually have other objects for which I may also need to do style-related stuff.
Given this, should I then create a separate style.cfc? Would that then be extended by the div object? Or would the style object extend the div object? My understanding is that the more specific object extends the less specific one, but I am not sure which is more specific in this case: is it the div object, which references a specific div, or the style object, which provides a specific set of data?
Thanks in advance!
First, unless you need to write styles on-the-fly, I would create one or more stylesheets and link them dynamically, instead of creating them dynamically.
Assuming, however, that you do need to create them on-the-fly...
I would not have either the control (div) extend the style or vice-versa. A style is not a more specific definition of a div, nor is the reverse true. What I would do is create a style object that only contains the display meta-data for a given element or element set. This can be contained within your control/div object (not an extension), or can be part of the page object. The style is definitely related to the control, but I would not combine them, as that makes it harder to separate content and presentation.
By no means am I saying this is the best approach, but if you really wanted to use CFCs to style your pages, you could have a DivTag.cfc extend an HtmlTag.cfc, which would act as your base class for all HTML tags. You could then compose a StyleAttribute.cfc into your HtmlTag.cfc to work with any style properties, such as background colors and padding. So then you would end up calling functions like myDiv.getStyle().getPadding().
In general, you should really try to favor composition ("has a") over inheritance ("is a") and not get too crazy with your component hierarchies. In this case, I'd recommend using CSS files to style your pages.