3

I'd like to ask your opinion about using jQuery in Capybara specs. Is it really simulating the real user interaction, or is it faking it?

  • Is using find("#my_checkbox[value='1']").set(true)

    the same as page.execute_script("$('#my_checkbox').prop('checked', true);") ?

  • Or find("#my_button").click

    the same as page.execute_script("$('#my_button').click();") ?

I know that the spec result will be the same, but I'm really wondering:

  • the real user won't use the JS browser's console to click on a button, so should we just replicate that without using jQuery in the specs?
  • what about the spec's performance and speed? Is there any advantage on using jQuery?
fabdurso
  • 2,366
  • 5
  • 29
  • 55

1 Answers1

2

Using execute_script/evaluate_script to interact with the page in your tests is NOT simulating real user interaction and in a lot of cases can make your tests pointless. The main reason for this is that it allows you to do things a user never could (changing the values of hidden/readonly/disabled fields, etc). It also doesn't generate the same events a user interacting with elements would generate, so the JS in your page may not be reacting the same way. execute_script does have its place in writing tests but it's limited and usually to get values (as opposed to changing things) or to work around problems in browsers/drivers (once you fully understand the issue you're trying to work around and are sure it isn't a situation where the user couldn't actually do what you're trying to do).

As far as speed goes the execute_script may be slightly faster in some cases but that's only because it's not verifying that a user could actually do what it's doing. Also a slightly faster but meaningless test isn't really saving you anything.

That covers using execute_script with JS which I believe is what your question is really asking, although you specifically mention jQuery. There is also a reason not to use jQuery in any execute_script calls you do have in your tests which is that if you ever refactor your app to remove jQuery and just go with plain JS your tests will break. ie - you could prefer document.getElementById('abc') over $('#abc'). This may not be a big concern to you since there really shouldn't be that many instances of execute_script in your tests.

TLDR -

check('my_checkbox', option: 1) # best
find("#my_checkbox[value='1']").set(true) # valid but too verbose
page.execute_script("$('#my_checkbox').prop('checked', true);") # Don't use - not replicating a user

click_on('my_button') # best if element is a link or button
find("#my_button").click # valid
find("#my_button").trigger('click') # Only supported on some drivers - don't use in tests unless you REALLY understand why you're using it - basically the same as using `execute_script`
page.execute_script("$('#my_button').click()") # Don't use - not replicating a user
Nakilon
  • 34,866
  • 14
  • 107
  • 142
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • HI, I have already asked a question regarding to this issue but you haven't come up. What if I have known all the actions which triggers immediately after click by JS? Will I go wrong anyway? Is it not equal? Okay, In my application, driver doesn't wait for page load because it's not loading as any other webpage loads, there is a circle comes at the front while it loads, the following code I use for my page load `@b.wait_until(timeout: @Page_Load) {@b.execute_script("return (jQuery.active === 0)").eql? true}` Here I used execute script for page to be completely loaded, do you know (continued.) – Rajagopalan Jul 06 '18 at 17:06
  • Do you know what might be the selenium equivalent for this one? If I don't have selenium equivalent, what's the alternative for me? – Rajagopalan Jul 06 '18 at 17:07
  • @Rajagopalan That use of `execute_script` isn't interacting (modfiying/clicking) with anything on the page so it's not really covered by this question at all. It's also a bad way of dealing with page load issues, you should just be finding whatever indicates to the user the page is ready - for instance check for the circle being gone using one of the `have_no_xxx` matchers in Capybara. Anyway, as I said it isn't covered by this question and you shouldn't be hijacking questions in the comments. Post your own question with the Capybara tag if you need help with using Capybara to do something. – Thomas Walpole Jul 06 '18 at 17:45
  • I am not using Capybara, I am using WATIR, but I would like to learn capybara now because I really want to understand what capybara has which WATIR is missing. Okay I will come up with separate question. – Rajagopalan Jul 06 '18 at 17:52