Entering Text into a editInPlace div using PageObject - ruby

How can i enter a text into a Editinplace element as shown below using PageObject:-
New Rule Name
as right now i have to click on the class="editInPlace" and sendkeys to it to enter some text into it
<div id="ruleContainer">
<div class="splitPanel basicInfo">
<div class="subPanel">
<div id="ruleName" class="editInPlace">New Rule Name</div>
</div>

Based on the example you provided you simply need to change the call to use the *_element generated method. Try this:
def name_rule
rule_name_element.send_keys "Test"
end
All element declarations will generate a method that has the pattern "name you provided"_element. This method will return the actual underlying html element that you can make calls on.

Related

What is Valid Xpath for link extract by div class name?

What is Valid Xpath for link extract by div class name?
Here is html code:
<div class="poster">
<a href="/title/tt2091935/mediaviewer/rm4278707200?ref_=tt_ov_i"> <img alt="Mr. Right Poster" title="Mr. Right Poster" src="http://ia.media-imdb.com/images/M/MV5BOTcxNjUyOTMwOV5BMl5BanBnXkFtZTgwMzUxMDk4NzE#._V1_UX182_CR0,0,182,268_AL_.jpg" itemprop="image">
</a> </div>
I want to know exact Xpath as if i found href link.
I try with //a/#href[#class='poster'] but it's doesn't work
The <div> contains the <a> so you can use that to navigate:
//div[#class='poster']/a/#href
Remember that the "poster" class is defined on the <div> not on the <a> so that's where you need to apply the predicate.
//div returns all <div> elements
[#class='poster'] is a predicate that filters by class
/a returns all <a> elements that are children of those <div>s
/#href gives us the attribute we want
Depending on the system you're using you might need to wrap the whole expression in text() in order to bring back the attribute data rather than the DOM node.

Page Object Gem. Making accessors for elements without ids

Lets say I have a simple page that has less IDs than I'd like for testing
<div class="__panel_body">
<div class="__panel_header">Real Estate Rating</div>
<div class="__panel_body">
<div class="__panel_header">Property Rating Info</div>
<a class="icon.edit"></a>
<a class="icon.edit"></a>
</div>
<div class="__panel_body">
<div class="__panel_header">General Risks</div>
<a class="icon.edit"></a>
<a class="icon.edit"></a>
</div>
<div class="__panel_body">
<div class="__panel_header">Amenities</div>
<a class="icon.edit"></a>
<a class="icon.edit"></a>
</div>
</div>
I'm using Jeff Morgan's Page Object gem and I want to make accessors for the edit links in any given section.
The challenge is that the panel headers differentiate what body I want to choose. Then I need to access the parent and get all links with class "icon.edit". Assume I can't change the HTML to solve this.
Here's a start
module RealEstateRatingPageFields
div(:general_risks_section, ....)
def general_risks_edit_links
general_risks_section_element.links(class: "icon.edit")
end
end
How do I get the general_risks_section accessor to work, though?
I want that to represent the parent div to the panel header with text 'General Risks'...
There are a number of ways to get the general risk section.
Using a Block
The accessors can take a block where you can more programatically describe how to locate the element. This allows you to locate a distinguishing element and then traverse the DOM to the element you actually want. In this case, you can locate the header with the matching text and navigate to its parent.
div(:general_risks_section) { div_element(class: '__panel_header', text: 'General Risks').parent }
Using XPath
While harder to read and write, you could also use an XPath locator. The concept and thought process is the same as using the block. The only benefit is that it reduces the number of element calls, which slightly improves performance.
div(:general_risks_section, xpath: './/div[#class="__panel_body"][./div[#class="__panel_header" and text() = "General Risks"]]')
The XPath is saying:
.//div # Find a div element that
[#class="__panel_body"] # Has the class "__panel_body" and
[./div[ # Contains a div element that
#class="__panel_header" and # Has the class "__panel_header" and
text() = "General Risks" # Has the text "General Risks"
]]
Using the Body Text
Given the HTML, you could also just locate the section directly based on its text.
div(:general_risks_section, class: '__panel_body', text: 'General Risks')
Note that this assumes that the HTML given was not simplified. If there are actually other text nodes, this probably would not be the best option.

Access two elements simultaneously in Nokogiri

I have some weirdly formatted HTML files which I have to parse.
This is my Ruby code:
File.open('2.html', 'r:utf-8') do |f|
#parsed = Nokogiri::HTML(f, nil, 'windows-1251')
puts #parsed.xpath('//span[#id="f5"]//div[#id="f5"]').inner_text
end
I want to parse a file containing:
<span style="position:absolute;top:156pt;left:24pt" id=f6>36.4.1.1. варенье, джемы, конфитюры, сиропы</span>
<div style="position:absolute;top:167.6pt;left:24.7pt;width:709.0;height:31.5;padding-top:23.8;font:0pt Arial;border-width:1.4; border-style:solid;border-color:#000000;"><table></table></div>
<span style="position:absolute;top:171pt;left:28pt" id=f5>003874</span>
<div style="position:absolute;top:171pt;left:99pt" id=f5>ВАРЕНЬЕ "ЭКОПРОДУКТ" ЧЕРНАЯ СМОРОДИНА</div>
<div style="position:absolute;top:180pt;left:99pt" id=f5>325гр. </div>
<div style="position:absolute;top:167.6pt;left:95.8pt;width:2.8;height:31.5;padding-top:23.8;font:0pt Arial;border-width:0 0 0 1.4; border-style:solid;border-color:#000000;"><table></table></div>
I need to select either <div> or <span> with id==5. With my current XPath selector it's not possible. If I remove //span[#id="f5"], for example, then the divs are selected correctly. I can output them one after another:
puts #parsed.xpath('//div[#id="f5"]').inner_text
puts #parsed.xpath('//span[#id="f5"]').inner_text
but then the order would be a complete mess. The parsed span have to be directly underneath the div from the original file.
Am I missing some basics? I haven't found anything on the web regarding parallel parsing of two elements. Most posts are concerned with parsing two classes of a div for example, but not two different elements at a time.
If I understand this correctly, you can use the following XPath :
//*[self::div or self::span][#id="f5"]
xpathtester demo
The XPath above will find element named either div or span that have id attribute value equals "f5"
output :
<span id="f5" style="position:absolute;top:171pt;left:28pt">003874</span>
<div id="f5" style="position:absolute;top:171pt;left:99pt">ВАРЕНЬЕ "ЭКОПРОДУКТ" ЧЕРНАЯ СМОРОДИНА</div>
<div id="f5" style="position:absolute;top:180pt;left:99pt">325гр.</div>

How to write the single xpath when the text is in two lines

How to write the single xpath for this
<div class="col-lg-4 col-md-4 col-sm-4 profilesky"> <div class="career_icon">
<span> Boost </span> <br/>
Your Profile </div>
I am able to write by two line using "contains" method.
.//*[contains(text(),'Boost')]
.//*[contains(text(),'Your Profile')]
But i want in a single line to write the xpath for this.
You can try this way :
.//*[#class='career_icon' and contains(., 'Boost') and contains(., 'Your Profile')]
Above xpath check if there is an element having class attribute equals career_icon and contains both Boost and Your Profile texts in the element body.
Note that text() only checks direct child text node. To check entire text content of an element simply use dot (.).
You can combine several rules just by writing them one after another since they refer to the same element:
.//[contains(text(),'Boost')][contains(text(),'Your Profile')]

How to validate the visibility using Page Object?

I am having few overlay's and some elements , where I should check the the visibility of these element. Is that possible to achieve through page object?My intention here is I have a method in my page and it should return the visibility true or false.
Here is my page file
class HomePage
include PageObject
span(:text1, :text=>'text1') #this has 10+matches on my page
def getAvailabilityOf text
return send("#{text}.visible?")
end
end
This is how I am calling from my step definition.
Then(/^I should verify the visibility of "(.*?)" on images$/) do |text|
puts on(HomePage).getAvailabilityOf text
end
Below is the HTML.
<div class="box col2 review-box featured masonry-brick" style="height: 360px; background-image: url("https://stagingfiles.gamestakers.com/images/204/medium.jpg?1408991647"); background-repeat: no-repeat; position: absolute; top: 0px; left: 0px;">
<a href="/interviews/jeremy-spillmann">
<div class="gradient-fade">
<div class="featured-box">Featured</div>
<div class="title">
<span>text1</span>
<h2>Jeremy Spillmann</h2>
</div>
</div>
</a>
</div>
Below is the error I am getting .
Then I should verify the visibility of "text1" on images
undefined method `text1.visible?' for #<HomePage:0x35798b8> (NoMethodE rror)
./features/support/pages/HomePage_page.rb:67:in `getAvailabilityOf'
./features/step_definitions/homepage.rb:45:in `/^I should verify the visib ility of "(.*?)" on images$/'
features\RINavigation.feature:6:in `Then I should verify the visibility of "interview" on images'
I am expecting true or false to be printed on console.
In brief I am expecting page object way of implementing
#browser.span(:text => "text1").visible?
Suggest me some work around
Regards,
Avinash
The problem is that in the line:
return send("#{text}.visible?")
The page-object is looking for a single method called "text1.visible?", which does not exist. send is for making a single method call. It does not evaluate the string - ie it will not determine that you actually want to call a method and then with the returned value call a second method.
You could do the following:
def getAvailabilityOf text
return send("#{text}_element").visible?
end
Note that send("text1") would just return the text of the span element. send("#{text}_element") returns the page object element, which would have the visible? method.
Depending on how you are going to use the method, perhaps you actually want the following, which allows looking for the text without the need to also create the accessor.
def getAvailabilityOf text
return span_element(:text => text).visible?
end
I noticed something subtle in your question.
You indicated in a comment in your sample code:
span(:text1, :text=>'text1') #this has 10+matches on my page
You also added this requirement:
I should check the the visibility of these element(s)
Justin's answer is exactly what you need to do to validate a single, unique element, but when you have multiple elements that have the same attributes and text, then the locator you want to use is span_elements, like so:
def getAvailabilityOf text
return span_elements(:text => text)
end
Presumably you would do some sort of validation on this
Then /^I should verify the visibility of (.*?) on images$/ do |text|
spans = getAvailabilityOf text
spans.each do |s|
#Your validation code goes here
end
end
This validation is not very granular as you don't exactly know which span element you are validating, so make sure to take that into consideration.

Resources