MichaelR
MichaelR

Reputation: 999

How to turn a string into an element call

Given I have:

b = Watir::Browser.new
b.goto 'google.com'
string = "div(:id => 'main')"

The string is supplied by a user.

Is there a way to use the specified string, which describes how to locate an element, to locate the element in the browser? In other words, how can I execute the string as if the following was written:

b.div(:id => 'main')

I have tried with b.send(string) but this only works for string = url:

b = Watir::Browser.new
b.goto 'google.com'
string = "div(:id => 'main')"
b.send(string)
#=> "https://www.google.com"

When locating an element, like string = "div(:id =>'main')", I get an undefined method error:

b = Watir::Browser.new
b.goto 'google.com'
string = "div(:id => 'main')"
b.send(string)
#=> undefined method `div(:id =>'main')' for #

Upvotes: 1

Views: 292

Answers (2)

Justin Ko
Justin Ko

Reputation: 46846

If you are getting Watir commands as strings, I assume the commands could get more complicated. For example:

# Locating based on a partial match (ie regexp)
string = "div(:id => /main/)"

# A locator value with non-word characters
string = "link(:href => 'some/url')"    

# Locating nested elements
string = "div(:id => 'main').span(:class => 'text')"

Manually parsing these types of strings is more complicated than just scanning the string for words. For example, in the regexp example, just scanning for words would end up giving you the locator {"id"=>"main", :tag_name=>"div"}. Notice that the id is now looking for an exact match of "main", which is not what the string wanted.

Therefore, I think you should use instance_eval, which would eliminate the need for manual parsing:

require 'watir-webdriver'

b=Watir::Browser.new
b.goto 'https://www.google.com'

# Original string
string = "div(:id =>'main')"
p b.instance_eval(string)
#=> #<Watir::Div:0x61221438 located=false selector={:id=>"main", :tag_name=>"div"}>

# Locating based on a partial match (ie regexp)
string = "div(:id => /main/)"
#=> #<Watir::Div:0x42afd800 located=false selector={:id=>/main/, :tag_name=>"div"}>

# A locator value with non-word characters
string = "link(:href => 'some/url')"    
p b.instance_eval(string)
#=> #<Watir::Anchor:0x2b625f26 located=false selector={:href=>"some/url", :tag_name=>"a"}>

# Locating nested elements
string = "div(:id => 'main').span(:class => 'text')"
p b.instance_eval(string)
#=> #<Watir::Span:0x..fb341cd56 located=false selector={:class=>"text", :tag_name=>"span"}>

Upvotes: 3

Arup Rakshit
Arup Rakshit

Reputation: 118299

Try this as below :

require 'watir-webdriver'

b=Watir::Browser.new
b.goto 'https://www.google.com'

string = "div(:id =>'main')"
meth,*selector_arr = string.scan(/\w+/)
# => ["div", "id", "main"]
selector_hsh = Hash[*selector_arr]
p b.send(meth,selector_hsh)
# >> #<Watir::Div:0x5b248f1c located=false selector={"id"=>"main", :tag_name=>"div"}>

Upvotes: 2

Related Questions