How do I get the text of a capybara element including leading whitespace. - ruby

I am trying to write an rspec/capybara/selenium spec that deals with verifying of whitespace. Basically I have a form that can be filled out and once it is saved, the information renders as a row in a table. The issue that I am having is that once I get to a certain td or span and I call .text on it, what is being returned is stripped of the leading and trailing white space. So if you look at the sample below, if I call find('#one').text what is returned is 'FOOO'. What I want to be returned is ' FOOO ' (I.E. including the leading and trailing whitespace).
<tr id="myRow">
<td id="one">
<span> FOOO </span>
</td>
<td id="two">
<span> BAR </span>
</td>
</tr>

The leading and trailing whitespace would be collapsed/ignored by your browser so Capybara does the same. If you want that whitespace to actually be visible in the browser you need to replace the spaces with non-breaking spaces ( ) in your HTML and then Capybara will return them as well.

Related

How Can I get text of all child nodes

I want to get the text of a tag and span tag at the same time.
<td class="desc_autoHeight">
<a rel="nofollow" href="#" target="_blank">Silicon Power</a>
<br><span class="FreeGift">48 Hours Only</span>
</td>
<td class="desc_autoHeight">
<a rel="nofollow" href="#" target="_blank">Silicon Power</a>
48 Hours Only
</td>
Result should be Silicon Power 48 Hours Only
Here is the xpath with concat
concat(//td[#class='desc_autoHeight']/a/text(), ' ', //td[#class='desc_autoHeight']//span[#class='FreeGift']/text())
Screenshot:
If $td is the td element in question, then normalize-space($td) gives you the string you are looking for, at least in this particular example.
In many cases simply using the string value of the element (which you can get using string(), but in many cases that's implicit) is adequate. The difference with normalize-space() is that it turns chunks of spaces and newlines (like the whitespace before the <a> start tag) into a single space, or eliminates it at the start and end.

Split using multiple keywords using regex

Well I have a string containing (actually without line breaks)
<td class="coll-1 name">
<i class="flaticon-divx"></i>
SAME stuff here
<span class="comments"><i class="flaticon-message"></i>1</span>
</td>
and I want an array to store the string which is split using href=" and /"> specifically. How can i do that. I have tried this out.
new_array=my_string.split(/ href=" , \/">/)
Edit:
.split(/href="/)
This works out too good but not with the other part.
.split(/\/">/)
Similarly this works too But i am unable to combine them together into 1 line.
Given this string:
string = <<-HTML
<td class="coll-1 name">
<i class="flaticon-divx"></i>
SAME stuff here
<span class="comments"><i class="flaticon-message"></i>1</span>
</td>
HTML
and assuming that the correct link is the one without icon class, you could use the CSS selector a:not(.icon), for example via Nokogiri:
require 'nokogiri'
doc = Nokogiri::HTML::DocumentFragment.parse(string)
doc.at_css('a:not(.icon)')[:href]
#=> "/torrent/2349324/some-stuuf-here/"
You can take advantage of lookahead and lookbehind, like this:
my_string.scan(/(?<=href=").*(?=\/">)/)
#=> ["/torrent/2349324/some-stuuf-here"]
This will return an array with all occurrences of href=" ... /"> with only the ... part (which can be any string).
Or you can get everything that matches href=".../"> and then remove href=" and the trailing /">, something like this:
my_string.scan(/(?:href=".*\/">)/).map { |e| e.gsub(/(href="|\/">)/, "") }
#=> ["/torrent/2349324/some-stuuf-here"]
This will return an array of all instances that match /href=".*\/">/.
How do i split using 2 keywords using regex
You can use a | to denote an or in regex, like this:
my_string.split(/(?:href="|/">)/)

XPath of the edit button is //*[#id="edit_1088"]

My query is I need to click on the first edit link on the table. The table has 7 columns and rows will be incremented dynamically.
HTML Code for first row:
<tr role="row" class="odd">
<td>
<form method="GET" target="_blank" action>...</form>
<td> ALLOCATION CHANGE</td>
<td class="right"></td>
<td> SATTER, KRAIG</td>
<td> CAFEMANAGER1</td>
<td class="sorting_1">03/08/2016 17:00</td>
<td class="edit_icon" id="edit_1088" onclick="on EditClick(1088)">
<span class="view_icon" style="margin-left: 40%;"></span>
</td>
</tr>
Note: the ID of the edit button keep on changing as the row increments.
Mycode in cucumber -ruby -capybara
And /^I click on the Expresso image$/ do
find(:xpath, '//*[#id="l1row"]/span').click
find('tr:odd > td:edit_icon [id="edit_"] match: first').click
sleep 10
end
Error Message: invalid selector: An invalid or illegal selector was specified
Update based on the posted HTML -
Note: Your first <td> isn't closed, I'm assuming thats just an error when you were adding the HTML to the question.
So from the HTML posted you don't actually have an edit link you just have a td you need to click on - the one in the first row with an id beginning with "edit_" so
find('tr:first-child > td[id^="edit_"]').click
The attempt you posted in your question won't work because there is no such CSS selector as odd or edit_icon and find needs valid CSS selectors (or XPath if you specify XPath or set it as your default)
Previous Answer Based on the wording of the question:
If this is a table then you can do what you want with CSS and not worry about XPath.
find('tr:first-child > td:last-child [id^="edit_"]')
will find the element whose id starts with "edit_" in the last td in the first row. If your rows and columns are not actually a table you'll need to provide some example HTML of what you're talking about.

XPath - Locate node using its flattened descendant text

I got this html :
<tr>
<td>
Some
<strong>
text
</strong>
<em>
and more
</em>
</td>
...
</tr>
I need to locate my td element with this text Some text and more. I know that I can get this text with this XPath expression :
//td//text()
But I can not find a solution to locate td element. I try this :
//td[//text()='Some text and more']
but I get errors. Do you know a working XPath expression for that ?
Firstly, XPath uses forward slashes, never backslashes.
Secondly, I believe this may be the XPath you need:
//td[normalize-space(.) = 'Some text and more']
Could you give that a try?

Retrieving text from an element with children

I am trying to get the text "Weeeeee" but when i use //td[#class='something']/text() I got nothing
<td class="something">
<a href='http://www.google.com'>Google</a>
Weeeeee
<div>
<a>something</a>
</div>
</td>
Try
//td[#class='something']/text()[normalize-space() != ''][1]
as there are three text nodes in your example, the first and the last one consist of whitespace only.
Highlighted with square brackets:
<td class="something">[\n
----]<a href='http://www.google.com'>Google</a>[\n
----Weeeeee\n
----]<div>
<a>something</a>
</div>[\n
]</td>

Resources