Testing JavaScript

@cpytel As you requested, here is an example of a JavaScript bug I’m having difficulty testing.

Here’s the bug:

Clicking the Time Limit checkbox label on the New Question page does weird things. The time limit boxes will slide up, then down, and the checkbox gets out of sync with the hide/display status of the time limit boxes.

Here’s the code:

$(document).ready(function(){
  $('#time_limit_enabled').click(timeLimitToggle);
  ...
}

function timeLimitToggle() {
  $('#time_limit_parts_box').slideToggle();
  ...
}

The main problem is - how do I write a failing test case for this?

A few other thoughts:

  1. This is legacy Javascript and I should probably convert this to CoffeeScript, although I’m not sure it’s worth the effort.
  2. I’m not great with JavaScript / jQuery and perhaps there is a better way to write this code. Of course, I’d like to have a failing test case first.
  3. Can this be done somehow via asynchronous RoR?

Thanks!

There’s not enough here for me to help much, I’m afraid. From the description, it sounds like slideToggle is actually being called a couple of times (you describe a couple of slides).

What is it your trying to do? Is this an exercise in one of the courses (I’m not familiar with the course material). Would it be possible for you to post a reproduction on something like jsfiddle.net?

Without seeing the code or being familiar with what it’s trying to do, it’s hard to say how you should test it.

Thanks, Derek.

Here is a JSFiddle that illustrates the bug: http://jsfiddle.net/ZCtWy/

The point of the code there is that the second line (the asterisks) should only appear when the checkbox is checked, and should disappear when the checkbox is unchecked. However, click around a bit and you will see the synchronization is off.

Quickly you will see that there are a combination of HTML errors here that cause the problem:

  1. I am wrapping the input inside the label tag
  2. The label tag has an ‘id’ attribute identical to the input tag
  3. The label tag is missing the ‘for’ attribute

One solution would be to write unit tests verifying the HTML is valid and proper. But at the integration-test level, how would I test that clicking on the label doesn’t screw up the show/hide synchornization?

Thanks!

@dsilver829, part of the issue you have is because the jQuery click() method’s argument needs to be a function. Also, slideToggle() simply toggles display: none; on and off. Because of this you need to start with the asterisks hidden. An updated JSFiddle that works as desired can be found here: Edit fiddle - JSFiddle - Code Playground

To test this behavior I would use the be_visible matcher (auto-generated by RSpec from Capybara’s visible? method)

scenario 'user shows/hides asterisks by clicking checkbox' do
  # Asterisks are hidden on initial page view
  visit 'some/url'
  expect(find('#asterisks').to_not be_visible

  # Asterisks are visible after checking the box
  check('#show-asterisks')
  expect(find('#asterisks').to be_visible

  # Asterisks are hidden again after unchecking the box
  uncheck('#show-asterisks')
  expect(find('#asterisks').to_not be_visible
end

Thanks, Joel. Would you use something like capybara-webkit as the driver?

How much slower is that than standard Capybara?

Typically you would use Capybara with one of the following webdrivers:

####Selenium

  • Probably the easiest to set up
  • Pops up an actual browser window and you can see things happen on the page ast the suite runs
  • You need to have Firefox installed
  • I much slower than alternatives
  • Tightly coupled with Firefox (e.g. upgrading FF may cause your tests to fail until you also upgrade selenium)

####Capybara-webkit

  • is a headless browser (it doesn’t actually open a window) which makes it much faster
  • depends on Qt which can sometimes be a pain to install
  • is based on an implementation of webkit (the engine behind Chrome and Safari)

####PhantomJS

  • is also a headless browser
  • is also based on webkit

I tend to stay away from Selenium since it is slow and tightly coupled the the version of Firefox installed on my machine. However, I do sometimes temporarily switch to Selenium when visually seing what is happening during a test would help with debugging.