7

I want to override the method Selenium::WebDriver.for. This is what I tried:

module SeleniumWebDriverExtension
  def self.for(browser, *args)
    if browser != :phantomjs
      super(browser, *args)
    else
      options = {
          "phantomjs.cli.args" => ["--ssl-protocol=tlsv1"]
      }
      capabilities = Selenium::WebDriver::Remote::Capabilities.phantomjs(options)
      super(browser, desired_capabilities: capabilities)
    end
  end
end

Selenium::WebDriver.prepend(SeleniumWebDriverExtension)

But I got error when Selenium::Webdriver.for(:phantomjs) is called.

NoMethodError: super: no superclass method `for' for Selenium::WebDriver::Driver:Class

How can I call the original method from the overriding method?

sawa
  • 165,429
  • 45
  • 277
  • 381
ironsand
  • 14,329
  • 17
  • 83
  • 176

2 Answers2

10
module SeleniumWebDriverExtension
  def for(browser, *args)
    ...
  end
end

Selenium::WebDriver.singleton_class.prepend(SeleniumWebDriverExtension)
sawa
  • 165,429
  • 45
  • 277
  • 381
  • 1
    Clever, thanks! We now use this to amend `NewRelic::Agent::Hostname.get` with a fallback to super. – Raffael Apr 08 '16 at 22:02
4

When to you use self inside a module like this:

def self.for(browser, *args)

end

it is declared as a module function, not an instance method on the class that will include this module. What this means is that won't appear on included classes when the module is mixed into another class.

It is similar to writing:

 def SeleniumWebDriverExtension::for
 end

So if you want to call super from within the module, declare it as a simple instance method like the accepted answer has suggested. Just wanted to clear you on the reasoning behind this.

Btw SeleniumWebDriverExtension.ancestors to be clear on the inheritance hierarchy.

mhaseeb
  • 1,739
  • 2
  • 12
  • 24