Is there an autogenerated method in page-object that tell if the element is present?

50 views
Skip to first unread message

NaviHan

unread,
Jan 31, 2019, 8:11:33 AM1/31/19
to Watir General
I have an element defined as

div(:reward_history, :class => 'reward-history-header')


The page-object gem generated four methods for this element which are


'reward_history', 'reward_history_element', and 'reward_history?'



The fourth method 'reward_history?' check if the element exists in the DOM?


But what if the element exists in the DOM but is hidden, which is basically checking if the element is present?


Is there an autogenerated method for this?

I tried 'reward_history(:&present?)' but didn't work

As of now I have to write a method separately which does this

  def is_reward_history_present?
   
return reward_history_element.present?
 
end



Justin Ko

unread,
Jan 31, 2019, 1:01:34 PM1/31/19
to Watir General
You are correct that #reward_history? calls #exists?. There is no auto-generated method for #present?.

It is rather unfortunate. Checking presence is probably more common than checking existence. As a backwards incompatible change, it'll take some time to change.

If you want, you could monkey-patch to use #present? instead of #exists?:

module PageObject
 
module Accessors
   
def standard_methods(name, identifier, method, &block)
      define_method
("#{name}_element") do
       
return call_block(&block) if block_given?
        platform
.send(method, identifier.clone)
     
end
      define_method
("#{name}?") do
       
return call_block(&block).present? if block_given?
        platform
.send(method, identifier.clone).present?
     
end
   
end
 
end
end

I created a feature request (https://github.com/cheezy/page-object/issues/476), but like I said before, it'd take some time to roll out.

- Justin

NaviHan

unread,
Jan 31, 2019, 6:18:51 PM1/31/19
to Watir General
Thanks Justin for creating a feature request.

What I have done is I have created a file name monkeypatch.rb and put the code you have given in there.
Changed the script to use and it passed.
expect(on(MyAccountPage).reward_history?).to be_falsey

Could you please confirm if this is the right way to do this.

By the way Im confused how the script know it has to give priority to standard_methods in the monkypatch.rb rather in the actual PageObject module?

Justin Ko

unread,
Feb 1, 2019, 9:53:17 AM2/1/19
to Watir General
Yes, that would work.

Personally, I find "falsey" hard to type. Technically it also includes "nil", though #present? shouldn't return that. I tend to go with:

expect(on(MyAccountPage).reward_history?).to eq false

The monkey patch is redefining the method. It's one of those good and bad things that Ruby lets you do.

Justin

NaviHan

unread,
Feb 1, 2019, 6:17:10 PM2/1/19
to Watir General
Thanks Justin..
I have two more question though.

1. How does the the method in monkey_path.b takes precedence over the method in actual page-object gem?
2. There are may intances in the application where a div element receives the click rather than a button.

eg
  div(:expand_perks_section_icon, :css => '.icon-plus-wrapper')



This element is  a div and receives the click as shown below.
  def expand_perks_section
    expand_perks_section_icon_element.when_present.click
  end



Writing a separate method each time for such things is really a pain.
Is there a better solution for such cases


On Friday, 1 February 2019 00:11:33 UTC+11, NaviHan wrote:

Justin Ko

unread,
Feb 2, 2019, 10:11:37 AM2/2/19
to Watir General
Hi,

1. The monkey patch is redefining the method. Last definition wins. It is how Ruby is designed, nothing specific to Page-Object. A simpler isolated example:

def a
 
'hi'
end


def a
 
'bye'
end


puts a
#=> "bye"

Notice that you can define the method twice, but when called, the last definition wins.


2. This is a scenario where you will want to use the widget feature (https://github.com/cheezy/page-object/wiki/Custom-page-object-elements-by-using-widgets). The code would be:

# A class to represent your control (ie div that acts like a button)
class DivButton < PageObject::Elements::Div
 
def self.accessor_methods(accessor, name)
   
# Adds method to perform click
    accessor
.send(:define_method, "#{name}") do
     
self.send("#{name}_element").click
   
end
 
end
end
PageObject.register_widget :div_button, DivButton, :div


class MyPage
  include
PageObject
 
 
# Use div_button instead of div to use your widget
  div_button
(:expand_perks_section_icon, :css => '.icon-plus-wrapper')
end


page
= MyPage.new(browser)
page
.expand_perks_section_icon #=> triggers click on div
page
.expand_perks_section_icon? #=> has standard method to check element existence (or presence with the monkey patch)


Hope that helps,
Justin

NaviHan

unread,
Apr 17, 2019, 1:34:40 AM4/17/19
to Watir General
Hi Justin

Sorry to comeback on this thread.
Today I was just trying to understand this piece of code.

Im confused about the methods named "accessor_methods"

Could you please explain a bit about the accessor_methods to define additional methods that will be created for the page object?

Is that a feature of Ruby?

On Friday, 1 February 2019 00:11:33 UTC+11, NaviHan wrote:
Reply all
Reply to author
Forward
0 new messages