I'm testing this piece of Rails HTML code and its click function:
<tr>
<td class="arrow-uped" id="tupa" onclick="send_vote()">
</td>
<td rowspan="3" class="restname"> Chipotle
</td>
</tr>
<tr>
<td class="votenumber"><%= vote_count %>
</td>
</tr>
<tr>
<td class="arrow-down" id="tdpa" onclick="send_vote()">
</td>
</tr>
To click the element, you could do either
find("#tupa").click
or
page.all('#tupa')[0].click
Once it's clicked, it triggers an ajax call to update the vote counts in database. When the call returns, it updates the vote count on the page accordingly as well. The test reads the actual vote count on the page, and compare with expected value. You have options of doing
assert_equal find(".votenumber").text, "1"
or
votes = page.all('.votenumber').map(&:text)
assert_equal votes,['1']
But if you do this:
votes = page.execute_script("$('td.votenumber').html()")
assert_equal votes,['1']
You will get error message:
Expected: nil
Actual: ["1"]
To validate the JQuery script, I manually ran the script at console.
>>$('td.votenumber').html()
>>"
1
"
So it does return text string 1. Then why the return value from test is nil?
Let's read Capybara Session#execute_script docs:
(Object) execute_script(script)
Execute the given script, not returning a result. This is useful for
scripts that return complex objects, such as jQuery statements.
execute_script should be used over evaluate_script
whenever possible.
That's why! Capybara is designed to return nil for execute_script not to return a value.
Alternatively, there's evaluate_script call defined as:
(Object) evaluate_script(script)
Evaluate the given JavaScript and return the result. Be careful when using
this with scripts that return complex objects, such as jQuery statements.
execute_script might be a better alternative.
So here we should instead use
votes = page.evaluate_script("$('td.votenumber').html()").to_i
assert_equal votes, 1
Then it's all good!