I'm using SitePrism to create some POM tests. One of my page classes looks like this:
class HomePage < SitePrism::Page
set_url '/index.html'
element :red_colour_cell, "div[id='colour-cell-red']"
element :green_colour_cell, "div[id='colour-cell-green']"
element :blue_colour_cell, "div[id='colour-cell-blue']"
def click_colour_cell(colour)
case colour
when 'red'
has_red_colour_cell?
red_colour_cell.click
when 'green'
has_green_colour_cell?
green_colour_cell.click
when 'blue'
has_blue_colour_cell?
blue_colour_cell.click
end
end
end
The method click_colour_cell()
get its string value passed from a Capybara test step that calls this method.
If I need to create additional similar methods in the future, it can become rather tedious and unwieldy having so many case switches to determine the code flow.
Is there some way I can create a variable that is dynamically named by the string value of another variable? For example, I would like to do something for click_colour_cell()
that resembles the following:
def click_colour_cell(colour)
has_@colour_colour_cell?
@colour_colour_cell.click
end
where @colour
represents the value of the passed value, colour
and would be interpreted by Ruby:
def click_colour_cell('blue')
has_blue_colour_cell?
blue_colour_cell.click
end
Isn't this what instance variables are used for? I've tried the above proposal as a solution, but I receive the ambiguous error:
syntax error, unexpected end, expecting ':'
end
^~~ (SyntaxError)
If it is an instance variable that I need to use, then I'm not sure I'm using it correctly. if it's something else I need to use, please advise.
Instance variables are used define properties of an object.
Instead you can achieve through the method send and string interpolation.
Try the below:
def click_colour_cell(colour)
send("has_#{colour}_colour_cell?")
send("#{colour}_colour_cell").click
end
send
is the method defined in the Object
class (parent class for all the classes).
As the documentation says, it invokes the method identified by the given String or Symbol. You can also pass arguments to the methods you are trying to invoke.
On the below snippet, send will search for a method named testing
and invokes it.
class SendTest
def testing
puts 'Hey there!'
end
end
obj = SendTest.new
obj.send("testing")
obj.send(:testing)
OUTPUT
Hey there!
Hey there!
In your case, Consider the argument passed for colour
is blue
,
"has_#{colour}_colour_cell?"
will return the string"has_blue_colour_cell?"
and send will dynamically invoke the method named has_blue_colour_cell?
. Same is the case for method blue_colour_cell