有没有办法"extend"水豚,以便可以使用自定义查找器?



我想知道是否有一种方法可以创建自定义方法,使我能够"链";针对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的特定部分中找到/操作/执行操作,从而在整个页面中轻松地重新使用。

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

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

实现您想要的另一个选择是一次"包裹";或";装饰";你的水豚对象。

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

如果你真的想把函数添加到capybaras对象的实例中,你可以对相关的类进行猴子补丁,namley:https://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Element

但我建议,只要你能避免,就不要对库进行猴子补丁。最终,你只需要几行代码就可以安全/在写作时增加一点便利,但这会让其他人(或你将来(更难理解你的代码。

从技术上讲,您可以将方法添加到Capybara::Node::Element中,尽管如果Capybara添加了一个同名的方法,则可能会造成破坏。一个更安全的解决方案是创建一个包装类,将方法代理到capybara元素,实现to_capibara_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的需求。

您可以尝试使用Capybara测试助手来封装测试代码。

它将允许您利用整个Capybara DSL,同时创建自己的助手和别名:

例如,使用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命令都将被自动包装,这简化了链接自己的方法或断言。

最新更新