patternrubyMinor
Mixing Watir::Browser into RSpec
Viewed 0 times
watirintobrowsermixingrspec
Problem
In my previous Watir question I was making a module with
Now I want to make the same but via RSpec. Here is my try:
I see a problem, that previously I was defining
session_FF accepting a block.Now I want to make the same but via RSpec. Here is my try:
require "rspec"
require "watir"
module Session_FF
def method_missing m, *args, &block
@browser.send m, *args, &block
end
def element *args
elements = @browser.elements *args
case elements.size
when 1 ; elements.first
when 0 ; raise "found no nodes using search args: #{args}"
else ; raise "found #{es.size} nodes -- use #elements method or improve args"
end
end
end
RSpec.configure do |config|
config.include Session_FF
config.before{ @browser ||= Watir::Browser.new :ff}
config.after{ @browser.quit }
end
describe "it" do
it "is alive" do
goto "http://example.com/"
element(class: "userpanel").click
end
endI see a problem, that previously I was defining
method_missing in my own module but now include may redefine RSpec::Core::ExampleGroup or smth's #method_missing if it already exists or may appear in RSpec implementation. What is a better way for method_missing approach to forward browser interaction methods into @browser?Solution
As far as I can tell, you have 4 options:
-
Use the current code as-is (and, as you say, risk stepping on an existing
-
You can use RSpec's
-
You can skip
-
You can do something like below, which, admittedly, is somewhat hacky.
Should work, although if
On a side-note, I think it's perhaps a little strange that the module is named
-
Use the current code as-is (and, as you say, risk stepping on an existing
method_missing).-
You can use RSpec's
config.extend to at least limit the inclusion.-
You can skip
method_missing in favor of creating a module explicit method declarations for anything you want to forward to @browser. This is no doubt the safest, but also the most laborious, solution. Still, I'd consider it-
You can do something like below, which, admittedly, is somewhat hacky.
module Session_FF
# Alias existing method_missing implementation when being included
def Session_FF.append_features(target)
if target.instance_methods.include?(:method_missing)
target.send(:alias_method, :overriden_method_missing, :method_missing)
end
super
end
# Define your own method_missing which forwards to @browser
# or to the previous method_missing (if any)
def method_missing(name, *args, &block)
if @browser.respond_to?(name)
@browser.send(name, *args, &block)
elsif respond_to?(:overriden_method_missing)
overriden_method_missing(name, *args, &block)
end
end
def element(*args)
# ...
end
endShould work, although if
@browser also relies on method_missing without a reliable respond_to?, you might have better luck simply trying to call a method @browser and rescue a NoMethodError. Not very pretty, though.On a side-note, I think it's perhaps a little strange that the module is named
_FF when the @browser could be something other than Firefox. WatirSession might be a more inclusive name.Code Snippets
module Session_FF
# Alias existing method_missing implementation when being included
def Session_FF.append_features(target)
if target.instance_methods.include?(:method_missing)
target.send(:alias_method, :overriden_method_missing, :method_missing)
end
super
end
# Define your own method_missing which forwards to @browser
# or to the previous method_missing (if any)
def method_missing(name, *args, &block)
if @browser.respond_to?(name)
@browser.send(name, *args, &block)
elsif respond_to?(:overriden_method_missing)
overriden_method_missing(name, *args, &block)
end
end
def element(*args)
# ...
end
endContext
StackExchange Code Review Q#67839, answer score: 5
Revisions (0)
No revisions yet.