Ruby Cucumber using OR - ruby

I'm testing a poorly written webpage where on one page the first heading is a H1 then on the next page it's a H2.
Usually I would write something like find('h1', text: 'bla bla bla') or expect(find('h1')).to have_text 'bla bla bla'
As it keeps changing between H1 and H2, is there a way to say find('h1' || 'h2', text: 'bla bla bla)
I'd like to keep the test looking within the headers as the text sometimes exists within the body of the page too.

Related

Excluding contents of <span> from text using Waitr

Watir
mytext =browser.element(:xpath => '//*[#id="gold"]/div[1]/h1').text
Html
<h1>
This is the text I want
<span> I do not want this text </span>
</h1>
When I run my Watir code, it selects all the text, including what is in the spans. How do I just get the text "This is the text I want", and no span text?
If you have a more complicated HTML, I find it can be easier to deal with this using Nokogiri as it provides more methods for parsing the HTML:
require 'nokogiri'
h1 = browser.element(:xpath => '//*[#id="gold"]/div[1]/h1')
doc = Nokogiri::HTML.fragment(h1.html)
mytext = doc.at('h1').children.select(&:text?).map(&:text).join.strip
Ideally start by trying to avoid using XPath. One of the most powerful features of Watir is the ability to create complicated locators without XPath syntax.
The issue is that calling text on a node gets all content within that node. You'd need to do something like:
top_level = browser.element(id: 'gold')
h1_text = top_level.h1.text
span_text = top_level.h1.span.text
desired_text = h1_text.chomp(span_text)
This is useful for top level text.
If there is only one h1, you can ommit id
#b.h1.text.remove(#b.h1.children.collect(&:text).join(' '))
Or specify it if there are more
#b.h1(id: 'gold').text.remove(#b.h1.children.collect(&:text).join(' '))
Make it a method and call it from your script with get_top_text(#b.h1) to get it
def get_top_text(el)
el.text.chomp(#b.h1.children.collect(&:text).join(' '))
end

xpath syntax for grabbing text data after a strong tag containing header text

<li><strong>Movie Title:</strong> Training Day</li>
How do I grab the textual content in this li tag; "Training Day"?
So I need to say 'if the strong tag has 'Movie Title' in it, return 'Training Day'.
I have tried stuff using the "following-sibling", but don't seem to be able to get this right.
Another attempt was
//li/text()[preceding::strong[contains(text(),'Movie Title')]]
But this returns ALL text, not just what is inside the li class.
Actually //li/text() should return "Training Day", while //li//text()- both "Training Day" and "Movie Title:"
You can try more specific XPath
//li[starts-with(., "Movie Title:")]//text()[not(parent::strong)]
to get "Training Day" only
How do I grab the textual content in this li tag; "Training Day"?
So I need to say 'if the strong tag has 'Movie Title' in it, return 'Training Day'.
The following XPath expression selects all li-element's text-nodes following a strong-element which value contains the string 'Movie Title'.
//li[contains(strong,'Movie Title')]/strong/following-sibling::text()
In your example XML this results in 'Training Day'.
But if more text-nodes followed, you'd have to restrict the expression to the first text-node like this
//li[contains(strong,'Movie Title')]/strong/following-sibling::text()[1]

trying to get all p tag text between two h2 tags

<h2><span>Title1</span></h2>
<p>text I want</p>
<p>text I want</p>
<p>text I want</p>
<p>text I want</p>
<h2>Second Title I want to stop collecting p tags after</h2>
I can get p tags by identifying the text within the h2, then get preceeding-sibling::p but this grabs all p tags to the end of the DOM. I have tried to use the "and" selector to essentially declare a start and end but it returns null. I must be missing something here but I've been stuck on this for quite a while. I cannot predict how many p tags I need so an index number on the p element is not going to help me in this case.
Here is the xpath I used to get all of the following p tags after an h2. the problem is it grabs all p tags to the end of the DOM.
//span[contains(text(), "Title1")]/ancestor::h2/following-sibling::p
So you just want to get all the p tags where they are between two specific h2 tags. The xpath query is exactly as it sounds.
//p[
preceding-sibling::h2[span='Title1'] and
following-sibling::h2[.='Second Title I want to stop collecting p tags after']
]
The query could be simplified by selecting all p where the first preceding h2 element is the starting element. In other words, there are no other h2 previous siblings between the current p and the header.
//p[preceding-sibling::h2[1][span='Title1']]

Textmate: Find and add numeric values

I want to find and replace numerics in my html file as follows e.g.: href="#1" to href="#12". Basically I want to add 10 to the exiting value
from
<p>bla bla
<p>bla bla
to
<p>bla bla
<p>bla bla
how can I do this in textmate?

Hpricot: How to extract inner text without other html subelements

I'm working on a vim rspec plugin (https://github.com/skwp/vim-rspec) - and I am parsing some html from rspec. It looks like this:
doc = %{
<dl>
<dt id="example_group_1">This is the heading text</dt>
Some puts output here
</dl>
}
I can get the entire inner of the using:
(Hpricot.parse(doc)/:dl).first.inner_html
I can get just the dt by using
(Hpricot.parse(doc)/:dl).first/:dt
But how can I access the "Some puts output here" area? If I use inner_html, there is way too much other junk to parse through. I've looked through hpricot docs but don't see an easy way to get essentially the inner text of an html element, disregarding its html children.
I ended up figuring out a route by myself, by manually parsing the children:
(#context/"dl").each do |dl|
dl.children.each do |child|
if child.is_a?(Hpricot::Elem) && child.name == 'dd'
# do stuff with the element
elsif child.is_a?(Hpricot::Text)
text=child.to_s.strip
puts text unless text.empty?
end
end
Note that this is bad HTML you have there. If you have control over it, you should wrap the content you want in a <dd>.
In XML terms what you are looking for is the TextNode following the <dt> element. In my comment I showed how you can select this node using XPath in Nokogiri.
However, if you must use Hpricot, and cannot select text nodes using it, then you could hack this by getting the inner_html and then stripping out the unwanted:
(Hpricot.parse(doc)/:dl).first.inner_html.sub %r{<dt>.+?</dt>}, ''

Resources