I have doubts about two mappings on the site-prism - ruby

I don't want to use xpath on the elements below.
element :img_login, :xpath, '//[#id="main-wrapper"]/div/section/div/div[2]/div/div/div[1]/img'
element :msg_login_senha_invalidos, :xpath, '//[#id="main-wrapper"]/div/section/div/div[2]/div/div/div[2]/div/p'
They are on the page as follows:
element img_login
<div class="sc-jRQAMF eRnhep">
<img src="https://quasar-flash-staging.herokuapp.com/assets/login/flashLogo-3a77796fc2a3316fe0945c6faf248b57a2545077fac44301de3ec3d8c30eba3f.png" alt="Quasar Flash">
</div>
element msg_login_senha_invalidos
<p class="MuiFormHelperText-root MuiFormHelperText-contained Mui-error MuiFormHelperText-filled">Login e/ou senha inválidos</p>

You have asked multiple questions about converting from using XPath to some other type of selector when using Site-Prism. StackOverflow is meant to be a place to come, learn, and improve your skills - not just to get someone else to do your work. It really seems you'd be better off reading up on CSS and how it can be used to select elements. Also note that there's nothing specifically wrong with using XPath, per se, it's just the way people new to testing and selecting elements on a page tend to use it (just copying a fully specified selector from their browser) that leads to having selectors that are way too specific and therefore brittle. A good site for you to learn about the different general CSS selector options available is https://flukeout.github.io/ - and you can look at the built-in selector types provided by Capybara at https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb#L18
In your current case the below may work, but with the HTML you have provided all that's possible to say is that they will match the elements shown however they may also match other elements which will give you ambiguous element errors.
element :img_login, :css, 'img[alt="Quasar Flash"]' # CSS attribute selector
element :msg_login_senha_invalidos, :css, 'p.Mui-error', text: 'Login e/ou senha inválidos' # CSS class selector combined with Capybara text filter

Related

XPath: How do I find a page element which contains another element, using the full text of both?

I have an HTML page which contains the following:
<div class="book-info">
The book is <i>Italicized Title</i> by Author McWriter
</div>
When I view this in Chrome Dev Tools, it looks like:
<div class="book-info">
"The book is "
<i>Italicized Title</i>
" by Author McWriter"
</div>
I need a way to find this single div using XPath.
Constraints:
There are many book-info divs on the page, so I can't just look for a div with that class.
Any part of the text within the book-info div might also appear in another, but the complete text within the div is unique. So I want to match the entire text, if possible.
It is not guaranteed that an <i> will exist within the book-info div. The following could also exist, and I need to be able to find it as well (but my code is working for this case):
<div class="book-info">
"Author McWriter's Legacy"
</div>
I think I can detect whether the div I'm looking for contains an <i> or not, and construct a different XPath expression depending on that.
Things I have tried:
//div[text()=concat("The book is ","Italicized Title"," by Author McWriter")]
//div[text()=concat("The book is ","<i>Italicized Title"</i>," by Author McWriter")]
//div[text()=concat("The book is ",[./i[text()="Italicized Title"]," by Author McWriter")]
//div[concat(text()="The book is ", i[text()="Italicized Title"],text()=" by Author McWriter")]
None of these worked for me. What XPath expression would?
You can use this combination of XPath-1.0 predicates in one expression. It matches both cases:
//div[#class="book-info" and ((i and contains(text()[1],"The book is") and contains(text()[2],"by Author McWriter")) or (not(i) and contains(string(.),"Author McWriter&apos;s Legacy")))]

geb: select by existence of attribute

Given the following html:
<a class="foo">
<a class="foo" href="somePonderousJSIDontWantToQuoteInMyTests">
One can select the later from the former using $("a.foo", href: ~/.*/).
Is there a more elegant way of selecting an element, based on whether or not it has a certain attribute?
Thanks!
I don't know if using a CSS3 attribute matcher is more elegant but it's definitelly quicker especialy if your selector would return many elements without the filter because the filtering happens in the browser and not in the jvm as in your approach:
$("a.foo[href]")

How do I get span text value in prototype

This is my prototype code:
$$('coupon-value').findAll("price").innerHTML
<span class="coupon-value"><span class="price">66.67</span></span>
How do I get the value of .price in the prototype? In my html code there are multiple price classes. In jquery it would be simple:
$(".coupon-value").find(".price").text();
But in prototype I have no idea. Can you help me?
If you would like to get the contents of the <span> with the price class that is a child of a <span> with the coupon-value class you would do it like this
$$('.coupon-value .price').first().innerHTML
This will give you the first element that matches that CSS selector. You can also be very specific with your CSS selection as well.
$$('span.coupon-value span.price').first().innerHTML
you can also select that element and then traverse down the DOM like this
$$('.coupon-value').first().down('.price').innerHTML
Just be aware $$() returns an array of elements that match the CSS selector so you cannot just operate on them like a jQuery collection. However all of the elements in that array are already extended with the PrototypeJS extensions.
Try:
$$('coupon-value').getElementsByClassName("price").innerHTML;
You can change innerHTML for [0]
Like this:
$$('coupon-value .price')[0];
Or even this:
$$('span.price')[0];

How to find the nth element that has a class of .foo in the document with Capybara/Nokogiri

I'm trying to find the n-th element that has a special class in a document. The elements are not necessarily children of the same parent. So for example
<ul>
<li><div class="foo">This</div></li>
<li><div>Nothing</div>
<ul>
<li><div class="foo">This also</div></li>
</ul>
</li>
<li><div class="foo">And this</div><li>
</ul>
I'd like to find the first, second or third element that has the class .foo.
I tried
page.find '.foo'
Which errors in Capybara::Ambiguous: Ambiguous match, found 3 elements matching css ".foo"
I then tried
page.all('.foo')[n]
Which works nice except that it doesn't seem to wait this little time like Capybaras find does, which I need because the HTML is actually generated from ajax data. So how to do this correctly with find?
Okay after a short chat in #RubyOnRails on freenode it became clear to me that this isn't as easy possible as it sounds first. The problem is that Capybara can't know if the .foos that are already inserted into the page are "all" of them. Thats why .all has no (or doesn't need) support for waiting like .find has.
The solution would be to manually wait for an appropriate amount of time and then just use .all.
Nokogiri's CSS queries are effective for finding elements of certain classes. It is explained in the tutorial.
For example you can use the following Ruby one-liner to read from a given file and find the second element of class foo:
ruby -rnokogiri -e 'puts Nokogiri::HTML(readlines.join).css(".foo")[1]' sample.html
which returns
<div class="foo">This also</div>
Replace the number in [1] with the index of the element you want to find and replace sample.html with the html file you want to search in. If you want to pick out certain parts of the elements you can use methods of Nokogiri::XML::Element, e.g. content to get its contents.

watir-webdriver click on image

Folks,
I have an image with the following HTML code:
<div unselectable="on" class="x-grid-cell-inner x-unselectable" style="; text-align: right;" id="ext-gen1453">
<img alt=""src="data:image/gif;base64,FRFRFR/GFFFFFFFFFF==" class="x-action-col-icon x-action-col-0 folder-action-add folder-action" data-qtip="Add New Music File" id="ext-gen1300">
When I click on the image it should open a pop up so that I can add new music file, I tried a few things but I am not able to click on that image. Any suggestions?
Thanks a lot
You can click on it by the class or a partial match of the class.
#browser.image(:class=>/folder-action-add folder-action/).click
Here is a list of the identifiers you can use for watir, I think it's mostly the same for watir-webdriver.
So far, you haven't got a consistent way of actually identifying the element. From what you've said in the comments, you've tried the 'text' attribute which doesn't exist, and the 'id' attribute which is auto generated and different every time.
You need to find a way of consistently identifying the element. It's usually preferable to use a semantic class on the element to make styling and testing easier and less brittle. You have a few classes declared, perhaps 'folder-action-add' expresses the intent of the button clearly? If not, you could add one such as 'add-music-file'.
Then you should be able to use watir to select an element by it's class, I'm not familiar with the syntax but at a guess, #browser.image(:class => 'add-music-file') might do the job.

Resources