在元素声明中使用id作为id

时间:2014-01-22 19:48:34

标签: ruby metaprogramming watir-webdriver page-object-gem

我有一个超类DemoPage和几个子类SDemoPageEDemoPage等。所有这些页面上都有相同的元素,SDemoPage上有ID看起来像s-demo-test1EDemoPage上的相应ID看起来像e-demo-test1。在我的DemoPage类中,我已经声明了所有元素,并且我需要一种基于子类(调用类)添加id的方法。这就是我目前所拥有的。

class DemoPage
  include PageObject

  @@subclass_ids = {"SDemoPage" => "s-demo-",
   "EDemoPage" => "e-demo-"}

  # class << self; attr_accessor :current_class_id; end

  def initialize(browser, something)
    initialize_elements
    super(browser, something)
  end

  .........

  def initialize_elements
    self.instance_eval do
      select_list(:facility, id: "#{@current_class_id}facility")
      text_field(:account, id: "#{@current_class_id}account")
      text_field(:service, id: "#{@current_class_id}service")
   end
  end
end

class SDemoPage < DemoPage
  include PageObject

  @current_class_id = "s-demo-"
end

但这不起作用。我收到错误undefined method 'select_list' for #<SDemoPage>...

这不是我最初的尝试。我首先尝试设置一个attr_accessor:current_page_id,然后初始化它,但这也没有用。然后我尝试打开元类并在那里设置id。最后,我做了我在这里我在SDemoPage上设置类实例变量的地方,我终于能够使用这段代码:

class DemoPage
  include PageObject

  def initialize(browser, something)
    super(browser, something)
  end

  .........

  SDemoPage.instance_eval do
    select_list(:facility, id: "#{@current_class_id}facility")
    text_field(:account, id: "#{@current_class_id}account")
    text_field(:service, id: "#{@current_class_id}service")
  end
end

但这不允许我根据其他调用类设置id。

我还从我的其他一些尝试中留下了一些代码,比如使用Hash查找,但是这些仍然在initialize方法中设置了实例变量,在页面对象方法已经意识到变量/方法@current_class_id没有存在

我不确定从这里去哪里。


编辑:

所以我终于明白了,但我不确定这是否是解决这个问题的最佳方法:

class DemoPage
  include PageObject
  include DataMagic

  def initialize(browser, visit)
    super(browser, visit)
    instantiate_elements self.class
  end

  def instantiate_elements klass
    klass.class_eval do
      select_list(:facility, id: "#{@class_id}facility")
      text_field(:account, id: "#{@class_id}account")
      text_field(:service, id: "#{@class_id}service")
    end
  end
end

class SDemoPage < DemoPage
  include PageObject
  @class_id = "s-demo-"
end

这样做有什么不对吗?我确实需要对初始化方法进行修补,因为其中还有其他内容我没有在这里展示。因为我已经需要这样做了,有没有理由不在SDemoPage而不是实际DemoPage的上下文中“创建”元素?或者Justin的回答是完全和完全更好的做事方式吗?

编辑2: 我接受了Justin的回答,因为在极少数情况下我不需要在PageObject中修改初始化方法,他的答案会减少重复,减少整体代码。

1 个答案:

答案 0 :(得分:2)

我认为最简单的解决方案是:

  1. 为调用访问者方法的DemoPage定义类方法
  2. 在子页面中调用此方法,将id部分作为参数传递
  3. DemoPage将是:

    class DemoPage
        include PageObject
    
        def self.common_demo_elements(class_id)
            select_list(:facility, id: "#{class_id}facility")
            text_field(:account, id: "#{class_id}account")
            text_field(:service, id: "#{class_id}service")      
        end
    end
    

    子页面为:

    class SDemoPage < DemoPage    
        common_demo_elements("s-demo-")
    end