有没有一种“扩展”水豚以便可以使用自定义查找器的方法?

时间:2020-09-22 18:49:41

标签: ruby selenium-webdriver capybara

我想知道是否有一种方法可以创建自定义方法,使我可以“绑定”针对Capybara对象的调用。这可能很难解释,所以这是我尝试实现的示例:

find('#element-id').some_custom_method_here

find('#another-element-id').some_custom_method_here

all('.other-class-id')[3].some_custom_method_here

我希望能够在Capybara对象上使用自定义类方法,以便我可能能够在DOM的 specific 部分中查找/操作/执行动作,整个页面易于重用。

我发现自己能够执行此操作的唯一方法是创建一个函数,该函数首先传递元素,然后继续执行我的代码。像这样:

def some_custom_method_here(capybara_obj, options={})
# do stuff with capybara_obj, find, click, etc
end

3 个答案:

答案 0 :(得分:1)

另一种实现所需功能的方法是一次性“包装”或“装饰”水豚对象。

decorated_node = SomeCustomWrapper.new(find('#element-id'))
decorated_node.some_custom_method

class SomeCustomWrapper < SimpleDelegator
  def some_custom_method
    # do something with self
  end
end

如果您需要做很多事情,您还可以为自己编写一种查找装饰节点的方法:

def find_decorated(selector, options={})
  SomeCustomWrapper.new(find(selector, options))
end

def all_decorated(selector, options={})
  all(selector, options).map { |node| SomeCustomWrapper.new(node) }
end

如果您真的想向水豚对象的实例添加函数,则可以猴子修补相关类,namley:https://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Element

但是我建议您尽量避免使用猴子补丁库。最终,这只会使您安全几行代码,并且在编写时会增加一些便利,但是这会使其他人(或您将来)很难理解您的代码。

答案 1 :(得分:1)

从技术上讲,您可以将方法添加到Capybara::Node::Element中,尽管如果Capybara曾经添加了一个具有相同名称的方法,则可能会造成破坏。一种更安全的解决方案是创建一个包装类,将方法代理到capybara元素,实现to_capybara_node以允许Capybara期望使用包装的元素,并按照

的方式添加它自己的方法
class ElementWrapper
  def initialize(element)
    @capybara_element = element
  end

  def find(...)
    ElementWrapper.new(@capybara_element.find(...))
  end

  ... # wrap the rest of Capybara Elements methods to return wrapper objects

  def custom_method(...)
    implement custom method and return wrapped element if necessary
  end

  def to_capybara_node
    @capybara_element # return the native capybara element
  end
end

那你就拥有

ElementWrapper.new(page.find(...)).custom_method(...).find(...) 

您可以在名称空间中编写自己的find方法,以消除对上面的ElementWrapper.new的需要。

答案 2 :(得分:0)

您可以尝试使用Capybara Test Helpers封装测试代码。

它将允许您利用整个Capybara DSL,同时创建自己的helpersaliases

例如with RSpec

RSpec.describe 'Sample', test_helpers: [:example] do
  scenario 'sample scenario' do
    example.element.some_custom_method_here
    example.another_element.some_custom_method_here
    example.all(:other_element)[3].some_custom_method_here
  end
end

实现可能类似于:

# test_helpers/example_test_helper.rb
class ExampleTestHelper < Capybara::TestHelper
  aliases(
    element: '#element-id',
    another_element: '#another-element-id',
    other_element: '.other-class-id',
  )

  def some_custom_method_here
    click # or any other Capybara command
  end
end

任何返回元素的Capybara命令都将是automatically wrapped,这简化了own methods or assertions的链接。